Files
wordpress-theme-aksrt/tests/widget-system/mini-pay-badge-reference.test.cjs
T
kate522andClaude Fable 5 48e54dc115 fix(tests): restore green contract suite
Drop the legacy credits_added message label per the hard-cut rule, switch
three remaining Font Awesome 4 icons to FA5 solid, and align two widget
contracts with the badge rule grouping and renderer list from fc04bf65.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-31 14:18:01 +08:00

96 lines
4.8 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const { execFileSync } = require('node:child_process');
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 cases = JSON.parse(execFileSync('php', [path.join(__dirname, 'tab-posts-render-harness.php')], { encoding: 'utf8' })).cases;
function row(html, id) {
const result = html.split('<div class="posts-mini ajax-item">').slice(1)
.find((item) => item.includes(`href="https://example.test/post/${id}"`));
assert.ok(result, `the actual mini renderer emitted post ${id}`);
return result;
}
function badge(html, id) {
const result = row(html, id).match(/<item class="meta-pay\b[\s\S]*?<\/item>/g) || [];
assert.equal(result.length, 1, 'each article has exactly one compact paid badge');
return result[0];
}
test('cash mini badges show type icons, a smaller currency mark and the published amount', () => {
const expected = [
[70, 'fa fas fa-book', '付费阅读', '12.5'],
[69, 'fa fas fa-download', '付费资源', '12'],
[68, 'fa far fa-file-image', '付费图片', '8.6'],
[67, 'fa fas fa-play-circle', '付费视频', '5'],
];
for (const [id, icon, title, amount] of expected) {
assert.equal(badge(cases.pay_meta_right, id),
`<item class="meta-pay badg badg-sm mr6 c-yellow" data-toggle="tooltip" title="${title}"><i class="${icon} mr3" aria-hidden="true"></i><span class="em09">¥</span>${amount}</item>`);
}
assert.doesNotMatch(cases.pay_meta_right, /旧版资源标签/);
assert.match(badge(cases.pay_meta_custom_currency, 70), /<span class="em09">€<\/span>12\.5<\/item>/);
assert.match(badge(cases.pay_meta_right, 55), /<span class="em09">¥<\/span>0\.5<\/item>/);
});
test('points mini badges use the existing SVG mark inside em09 without the long currency name', () => {
for (const [id, amount] of [[62, 125], [61, 60], [60, 500], [59, 12]]) {
const html = badge(cases.pay_meta_right, id);
assert.ok(html.includes(`<span class="em09"><svg class="points-mark" aria-hidden="true"><use xlink:href="#icon-points"></use></svg></span>${amount}</item>`));
assert.doesNotMatch(html, /积分|¥|€|class="icon"/);
}
});
test('zero prices render the short free badge and take priority over VIP purchase limits', () => {
for (const [id, title] of [[66, '免费阅读'], [65, '免费资源'], [64, '免费图片'], [63, '免费视频']]) {
const html = badge(cases.pay_meta_right, id);
assert.ok(html.includes(`title="${title}"`));
assert.match(html, /<\/i>免费<\/item>$/);
assert.doesNotMatch(html, /会员专属|jb-vip|em09|免费资源<\/item>/);
}
});
test('VIP badges use the selected level image inline and keep the reference membership-switch rule', () => {
for (const html of [cases.pay_meta_right, cases.pay_vip1_only, cases.pay_vip2_only]) {
for (const [id, level, name] of [[58, 1, '黄金会员'], [57, 2, '钻石会员']]) {
const current = badge(html, id);
assert.ok(current.includes(`mr6 jb-vip${level}"`));
assert.ok(current.includes(`<img class="img-icon mr3" src="https://example.test/vip-${level}.svg" data-toggle="tooltip" title="${name}" alt="${name}">会员专属`));
assert.doesNotMatch(current, /fa-certificate|class="em09"/);
}
}
for (const id of [58, 57]) {
const html = badge(cases.pay_vip_disabled, id);
assert.match(html, /mr6 c-yellow/);
assert.match(html, /<span class="em09">¥<\/span>12\.5/);
assert.doesNotMatch(html, /会员专属|img-icon|jb-vip/);
}
});
test('mini badges stay on the correct meta side, disappear with meta and ignore non-paid posts', () => {
const right = row(cases.pay_meta_right, 70);
const left = row(cases.pay_meta_left, 70);
assert.ok(right.indexOf('class="meta-right"') < right.indexOf('class="meta-pay '));
assert.ok(left.indexOf('class="meta-pay ') < left.indexOf('class="meta-right"'));
badge(cases.pay_meta_right, 70);
badge(cases.pay_meta_left, 70);
assert.doesNotMatch(cases.pay_meta_hidden, /meta-pay|item-meta/);
assert.doesNotMatch(row(cases.pay_meta_right, 51), /meta-pay/);
assert.equal(cases.pay_empty, '');
});
test('mini badge styles preserve reference padding and VIP aspect ratio across page bundles', () => {
const widgetCss = read('assets/widgets/frontend.css');
const rule = widgetCss.match(/\.widget-tab-post \.item-meta \.meta-pay, \.widget-main-post \.item-meta \.meta-pay\s*\{([^}]+)\}/)[1];
assert.match(rule, /padding:\s*0 4px/);
assert.match(rule, /cursor:\s*auto/);
for (const file of ['assets/css/frontend/post-card.css', 'assets/css/build/homepage.css']) {
assert.doesNotMatch(read(file), /\.item-meta \.meta-pay img\s*\{/);
}
assert.match(read('assets/css/main.css'), /\.img-icon\s*\{[^}]*height:\s*1\.1em;[^}]*display:\s*inline-block/s);
});