Files
wordpress-theme-aksrt/tests/widget-system/comment-hard-cut-contract.test.cjs
T

190 lines
8.9 KiB
JavaScript

'use strict';
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const root = path.resolve(__dirname, '..', '..');
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
const exists = (file) => fs.existsSync(path.join(root, file));
test('comment area styles are fully owned (hard cut from vendor main.css)', () => {
const layout = read('assets/css/frontend/comments/layout.css');
const mobile = read('assets/css/frontend/comments/mobile-item.css');
// 1:1 移植的关键布局选择器必须存在于自有文件。
const layoutSelectors = [
'#comments .comment-box .comments-closed',
'#comments #postcomments .comt-ctrl .but',
'#comment {',
'.comment-signarea {',
'#postcomments .comment-footer {',
'#postcomments .avatar-img {',
'#postcomments .children {',
'#postcomments .comt-meta > span:not(:empty)',
'#postcomments .comment-approve-link.approve {',
'#postcomments .comment-approve-link.unapprove {',
'#postcomments .comt-meta > span .comment-trash-link {',
'.comment-content {',
'#postcomments .comment-content img {',
'#comments .virtual-input {',
'.commentlist .no-more {',
];
for (const selector of layoutSelectors) {
assert.ok(layout.includes(selector), `layout.css must contain ${selector}`);
}
// 桌面隐藏必须带 #comments 前缀(id 特异性),任何后加载的
// .flex{display:flex} 单类工具规则都无法在宽屏把假输入条顶出来。
assert.equal(layout.includes('\n.virtual-input {'), false, 'desktop hide must be id-scoped, not bare .virtual-input');
// 移动端弹层 / 虚拟输入 / 640px 覆盖。
const mobileSelectors = [
'@media (max-width: 767px)',
'@media (max-width: 640px)',
'#comments .virtual-input {',
'.drop-fixed-sm .dropdown-menu,',
'.mobile-fixed {',
'#respond.mobile-fixed {',
'.drop-fixed-sm .dropdown-menu::before {',
'#comments .comt-box {',
'#postcomments .commentlist > .comment > .list-inline .comment-footer {',
];
for (const selector of mobileSelectors) {
assert.ok(mobile.includes(selector), `mobile-item.css must contain ${selector}`);
}
// 自有文件不得包含表情/快捷回复样式。
for (const [file, source] of [['layout.css', layout], ['mobile-item.css', mobile]]) {
for (const token of ['smilie', 'dropdown-quick-often', 'quick-reply-item', 'quick-reply-action']) {
assert.equal(source.includes(token), false, `${file} must not contain ${token}`);
}
}
// 构建产物 comments.css 聚合了自有规则。
const built = read('assets/css/build/comments.css');
for (const selector of ['#postcomments .comt-meta > span:not(:empty)', '.mobile-fixed {', '#comments .virtual-input {', '#comments .comt-title {']) {
assert.ok(built.includes(selector), `build/comments.css must contain ${selector}`);
}
});
test('vendor main.css no longer carries comment-area rules (no dual path)', () => {
for (const file of ['assets/css/main.css', 'assets/css/main.min.css']) {
const source = read(file);
for (const token of [
'#postcomments',
'.commentlist',
'.comt-',
'.comment-signarea',
'.comment-filter',
'.mobile-fixed',
'.drop-fixed-sm',
'#respond',
'#comments',
]) {
assert.equal(source.includes(token), false, `${file} must not contain ${token}`);
}
// 小部件与共享规则仍留在全站表。
assert.ok(source.includes('.comment-widget-item'), `${file} must keep .comment-widget-item`);
assert.ok(source.includes('.comment-mini-lists'), `${file} must keep .comment-mini-lists`);
assert.ok(source.includes('.content-after-box'), `${file} must keep .content-after-box`);
assert.ok(source.includes('.theme-pagination.pagenav'), `${file} must keep .theme-pagination.pagenav`);
}
});
test('quick reply is removed across the owned comment stack', () => {
const files = [
'assets/admin/src/schema/sections/post-list/comment.js',
'assets/css/main.css',
'assets/css/build/comments.css',
'assets/js/comment-tools.js',
'inc/helpers/aksrt-comments.php',
'inc/helpers/comments/form-parts.php',
'src/Admin/Schema/SchemaPostList.php',
'src/Core/ScriptsPart1c.php',
'src/Settings/PostDisplay.php',
];
const tokens = [
'comment_quick_s',
'comment_quick_often',
'quick_phrases',
'parse_comment_quick_phrases',
'quick-reply-item',
'dropdown-quick-often',
'input-quick',
'commentQuickPhrases',
'快捷回复',
];
for (const file of files) {
const source = read(file);
for (const token of tokens) {
assert.equal(source.includes(token), false, `${file} must not contain ${token}`);
}
}
});
test('dead vendor comment archives stay deleted', () => {
for (const file of [
'assets/js/runtime/comment.js',
'assets/js/runtime/comment.min.js',
'assets/js/runtime/input-expand.js',
'assets/js/runtime/input-expand.min.js',
]) {
assert.equal(exists(file), false, `${file} must not exist`);
}
const loader = read('assets/js/runtime/loader.js');
assert.doesNotMatch(loader, /['"](?:comment|input-expand)['"]\s*:/, 'legacy comment modules must have no loader mapping');
assert.doesNotMatch(read('assets/js/runtime/main.js'), /stubVendorCommentModule|unbindVendorAjaxLoop/);
});
test('every comment-rendering singular loads the owned build bundle', () => {
// 旧的静态聚合文件已删除:它缺 layout.css 且 @import 无版本号,
// 曾导致页面/资源页手机端 .mobile-fixed 抽屉规则缺失、表单直接内联显示。
assert.equal(exists('assets/css/frontend/comments.css'), false, 'stale frontend/comments.css aggregator must not exist');
const part1b = read('src/Core/ScriptsPart1b.php');
// 统一入口:任何渲染评论区的 singular 都加载 build 聚合。
assert.ok(
part1b.includes('is_singular() && !empty($singular_assets[\'needs_comments\'])'),
'ScriptsPart1b must enqueue the comments bundle for every comment-rendering singular'
);
assert.ok(part1b.includes('assets/css/build/'), 'comments enqueue must point at the build bundle');
// 旧的两处按需入口必须移除(否则资源页/页面回到缺规则的聚合文件)。
assert.equal(part1b.includes("$enqueue_module('comments')"), false, 'stale aggregator enqueue must be gone');
});
test('comment markup keeps the 1:1 legacy DOM contract', () => {
const item = read('inc/helpers/comments/item.php');
// 点赞按钮(legacy: zib_get_comment_like — svg + text + count)。
assert.ok(item.includes("<text></text><count>"), 'like button must render <text> before <count>');
assert.ok(item.includes('aksrt_get_comment_icon(\'like\''), 'like button must use the sprite icon');
assert.ok(item.includes('aksrt_get_comment_icon(\'topping\')'), 'topping badge must use the sprite icon');
assert.ok(item.includes('aksrt_get_comment_icon(\'approve\''), 'approve action must use the sprite icon');
assert.ok(item.includes('aksrt_get_comment_icon(\'menu_2\')'), 'action dropdown must use the sprite icon');
assert.ok(item.includes('data-toggle="tooltip"'), 'time/reply tooltip parity');
assert.equal(item.includes('fa fa-thumbs-up'), false, 'legacy fa like icon must be gone');
const comments = read('inc/helpers/aksrt-comments.php');
assert.ok(comments.includes('post_password_required() || !comments_open()'), 'closed comments must render nothing');
assert.ok(comments.includes('user_url_enabled'), 'guest url field toggle must be wired');
assert.ok(comments.includes("name=\"url\""), 'guest url input must render');
assert.ok(comments.includes("aksrt_get_comment_icon('signup', 'icon mr10')"), 'signarea signup must use the sprite icon');
assert.ok(comments.includes('aksrt_render_vip_badge'), 'comt-title must render the vip badge (legacy: zibpay_get_vip_icon)');
assert.equal(comments.includes('aksrt_render_user_identity_chips'), false, 'identity chips must not crowd the narrow comt-title');
const formParts = read('inc/helpers/comments/form-parts.php');
assert.ok(formParts.includes("case 'link':"), 'link dropdown case must exist');
assert.equal(formParts.includes("case 'quick':"), false, 'quick case must be gone');
assert.equal(formParts.includes('fa-bolt'), false, 'quick button icon must be gone');
const icons = read('inc/helpers/comments/icons.php');
assert.ok(icons.includes('function aksrt_get_comment_icon'), 'sprite icon helper must exist');
const bootstrap = read('inc/bootstrap.php');
assert.ok(bootstrap.includes("comments/icons.php"), 'bootstrap must load the icon helper');
// 设置契约:link / user_url 开关进入显示设置。
const settings = read('src/Settings/PostDisplay.php');
assert.ok(settings.includes("'link' => !empty($settings['comment_link'])"), 'toolbar link toggle');
assert.ok(settings.includes("'user_url' => !empty($settings['comment_user_url_s'])"), 'user url toggle');
});