Files
wordpress-theme-aksrt/tests/widget-system/search-quote-card-contract.test.cjs
T
kate522andClaude Opus 5 3c07ef7a8d fix(widgets): restore the 20px bottom gap under the quote and search widgets
The reference wraps these two widgets in a middle .theme-box layer
(widget-container > .theme-box > title + card), which is what supplies the
20px bottom margin. Our outer .jio-widget-box-wrap is only a transparent
layout container, so dropping .theme-box left the quote card flush against
the following module.

- search/quote: emit the reference .theme-box middle layer; the card itself
  stays margin-free like the reference, so the gap is exactly 20px
- keep the generic .widget-content branch for user_card/author_card and the
  other reference widgets untouched (the string is contract-tested)
- contract test now pins the .theme-box layer and asserts the quote card
  carries no margin class of its own

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-11-03 16:09:46 +08:00

69 lines
3.7 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const { execFileSync } = require('node:child_process');
const root = path.resolve(__dirname, '..', '..');
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
test('搜索框与一言小工具只渲染参考主题的一张卡片', () => {
const rendered = JSON.parse(
execFileSync(process.env.PHP_BINARY || 'php', [path.join(__dirname, 'search-quote-render-harness.php')], {
encoding: 'utf8',
})
);
// 参考主题这两个小工具忽略 before_widget,卡片由自身输出一次。
assert.doesNotMatch(rendered.search, /jio-widget-shell/);
assert.doesNotMatch(rendered.quote, /jio-widget-shell/);
// 搜索框:widget-container > .theme-box(承载 20px 底距)+ 标题 + 单张卡片。
assert.equal((rendered.search.match(/class="jio-panel/g) || []).length, 1);
assert.match(rendered.search, /<div class="widget-container"><div class="theme-box"><div class="box-body notop"><div class="title-theme">/);
assert.match(rendered.search, /class="jio-panel widget-search"><div class="search-input">/);
assert.equal((rendered.search.match(/class="search-input"/g) || []).length, 1);
// 一言:同样的 .theme-box 间距层,卡片自身不带底部边距。
assert.equal((rendered.quote.match(/class="yiyan-box/g) || []).length, 1);
assert.match(rendered.quote, /<div class="widget-container"><div class="theme-box"><div class="box-body notop"><div class="title-theme">/);
assert.match(rendered.quote, /class="yiyan-box main-bg text-center box-body radius8 main-shadow jio-yiyan" data-jio-yiyan>/);
assert.doesNotMatch(rendered.quote, /class="yiyan-box[^"]*theme-box/);
assert.match(rendered.quote, /<div class="yiyan"><\/div>/);
});
test('搜索框设置沿用参考主题字段,不再提供自造样式选项', () => {
const schema = read('src/WidgetSystem/WidgetSchemas.php');
const renderer = read('src/WidgetSystem/Renderers/GeneralRenderer.php');
const frontend = read('src/WidgetSystem/FrontendRenderer.php');
for (const field of ["'id' => 'show_keywords'", "'id' => 'show_history'", "'id' => 'keywords_title'", "'id' => 'show_input_cat'", "'id' => 'in_cat'", "'id' => 'more_cats'"]) {
assert.match(schema, new RegExp(field.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
}
assert.doesNotMatch(schema, /search_style/);
assert.doesNotMatch(renderer, /jio-widget-search/);
assert.match(renderer, /function_exists\('jio_get_search_box'\)/);
// 与 TOC 一样由内容自带卡片壳,不走通用 .jio-panel 包裹分支。
assert.match(frontend, /\[['"]search['"], ['"]quote['"]\]/);
assert.match(frontend, /render_reference_widget\(\$definition, \$instance, \$widget, \$content, true\)/);
assert.match(frontend, /bool \$own_card = false/);
});
test('文章内一言沿用参考主题的类名组合,不再使用自定义修饰类', () => {
const single = read('inc/helpers/jio-single-render.php');
const css = read('assets/css/frontend/single-post/hidden-content.css');
assert.equal((single.match(/'article-yiyan theme-box text-center radius8 main-shadow yiyan-box jio-yiyan'/g) || []).length, 2);
assert.match(single, /'yiyan-box main-bg theme-box text-center box-body radius8 main-shadow jio-yiyan'/);
assert.doesNotMatch(single, /yiyan--header|yiyan--footer|yiyan--box/);
assert.doesNotMatch(css, /yiyan--header|yiyan--footer|yiyan--box/);
});
test('遗留的 qv-yiyan.php 渲染请求已移除', () => {
const runtime = read('assets/js/runtime/main.js');
assert.doesNotMatch(runtime, /qv-yiyan\.php/);
assert.doesNotMatch(runtime, /yiyan_nr\(/);
assert.match(read('assets/js/yiyan.js'), /action=jio_yiyan/);
});