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\(\)/) })