Files
wordpress-theme-aksrt/tests/forum/widgets-contract.test.cjs
T
kate522andClaude Fable 5 eceddb5f7d feat(forum): add the reference forum widgets
Port the six forum widgets from the reference theme: posts list,
multi-tab posts, plate list (default and card), plate info, moderator
list and topic list. They join the schema widget catalog under a forum
group that stays hidden while the forum module is off, reuse the shared
forum cards, paginate through the widget REST client contract, and pull
the forum stylesheet/runtime onto any sidebar that hosts them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-11-11 15:47:13 +08:00

87 lines
4.4 KiB
JavaScript

const test = require('node:test')
const assert = require('node:assert/strict')
const fs = require('node:fs')
const path = require('node:path')
const root = path.resolve(__dirname, '..', '..')
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8')
const SLUGS = ['forum_posts', 'forum_tab_posts', 'forum_plates', 'forum_plate_info', 'forum_moderators', 'forum_topics']
test('every reference forum widget is catalogued with a schema and a renderer', () => {
const catalog = read('src/WidgetSystem/WidgetCatalog.php')
const registry = read('src/WidgetSystem/RendererRegistry.php')
const schemas = read('src/Forum/WidgetSchemas.php')
const renderer = read('src/Forum/WidgetRenderer.php')
for (const slug of SLUGS) {
assert.ok(catalog.includes(`['${slug}',`), `${slug} missing from the widget catalog`)
assert.ok(registry.includes(`'${slug}' => \\Jio\\Forum\\WidgetRenderer::class`), `${slug} missing from the renderer registry`)
}
// The plate info card is configuration-free, like the reference widget.
for (const slug of SLUGS.filter((slug) => slug !== 'forum_plate_info')) {
assert.ok(schemas.includes(`case '${slug}':`), `${slug} missing a field schema`)
}
for (const slug of SLUGS) {
assert.ok(renderer.includes(`case '${slug}':`), `${slug} renderer missing`)
}
assert.match(catalog, /\$forum \? \\Jio\\Forum\\WidgetSchemas::for\(\$slug\) : WidgetSchemas::for\(\$slug\)/)
})
test('forum widgets reuse the shared reference cards instead of forking markup', () => {
const renderer = read('src/Forum/WidgetRenderer.php')
for (const helper of ['Cards::post_detail(', 'Cards::post_mini(', 'Cards::title(', 'Cards::plate_item(', 'Cards::plate_slide(', 'Cards::follow_button(']) {
assert.ok(renderer.includes(helper), `forum widgets must reuse ${helper}`)
}
assert.doesNotMatch(renderer, /zib|zibll|Qinver/i)
})
test('forum widget lists paginate through the widget REST client contract', () => {
const renderer = read('src/Forum/WidgetRenderer.php')
const query = read('src/Forum/WidgetQuery.php')
const registry = read('src/WidgetSystem/RendererRegistry.php')
const rest = read('src/WidgetSystem/RestController.php')
// The container carries the attributes frontend.js reads, with the skeleton inside it.
assert.match(renderer, /class="widget-ajaxpager"/)
assert.match(renderer, /data-widget-items data-widget=/)
assert.match(renderer, /post_ajax_loader/)
assert.doesNotMatch(renderer, /post_ajax_trigger/)
// Item payloads resolve through the forum query builder, not the article one.
assert.match(rest, /\\Jio\\Forum\\WidgetQuery::payload/)
assert.match(registry, /WidgetRenderer::SUPPORTS_ITEMS/)
assert.match(query, /jio_forum_list/)
// Pagination exposes the widget client's page hooks and the reference modes.
assert.match(query, /data-widget-page=/)
assert.match(query, /data-next-page=/)
assert.match(query, /ajaxpager-target="\.widget-ajaxpager"/)
const schemas = read('src/Forum/WidgetSchemas.php')
assert.match(schemas, /'ajax_lists'/)
assert.match(schemas, /'default' => '数字翻页按钮'/)
})
test('plate-scoped forum widgets stay silent outside plate and post pages', () => {
const renderer = read('src/Forum/WidgetRenderer.php')
const core = read('src/Forum/Core.php')
assert.match(core, /public static function current_plate_id\(\)/)
for (const method of ['plate_info', 'moderators']) {
const start = renderer.indexOf(`private static function ${method}(`)
const body = renderer.slice(start, renderer.indexOf('private static function', start + 10))
assert.match(body, /Core::current_plate_id\(\)/)
assert.match(body, /Core::PLATE/)
}
})
test('forum widgets load the forum card styles and runtime on any sidebar', () => {
const core = read('src/Forum/Core.php')
const runtime = read('assets/js/forum-runtime.js')
assert.match(core, /add_action\('wp_enqueue_scripts', \[self::class, 'widget_assets'\]/)
assert.match(core, /public static function enqueue_css\(\)/)
assert.match(core, /is_active_widget\(false, false, 'jio_widget_' \. \$slug, true\)/)
assert.match(runtime, /document\.getElementById\('forum'\) \|\| document\.body/)
})
test('forum widgets keep the module off until it is enabled', () => {
const catalog = read('src/WidgetSystem/WidgetCatalog.php')
assert.match(catalog, /if \(\$group === 'forum' && !\$forum_on\)/)
assert.match(catalog, /function_exists\('jio_get_setting'\) && \\Jio\\Forum\\Core::enabled\(\)/)
})