92 lines
3.7 KiB
JavaScript
92 lines
3.7 KiB
JavaScript
'use strict';
|
||
const assert = require('node:assert');
|
||
const fs = require('node:fs');
|
||
const path = require('node:path');
|
||
|
||
const rendererSrc = fs.readFileSync(
|
||
path.join(__dirname, '..', 'renderer', 'renderer.js'), 'utf8'
|
||
);
|
||
|
||
let passed = 0;
|
||
function check(name, fn) {
|
||
try { fn(); console.log(' ok -', name); passed++; }
|
||
catch (e) { console.error(' FAIL -', name, e.message); process.exitCode = 1; }
|
||
}
|
||
|
||
// ---------- buildCard 抽函数 ----------
|
||
|
||
check('renderer.js 定义了 buildCard 函数', () => {
|
||
assert.ok(
|
||
/function\s+buildCard\s*\(/.test(rendererSrc),
|
||
'找不到 buildCard(c, i) 定义'
|
||
);
|
||
});
|
||
|
||
check('render() 调用 buildCard 而不是手写卡片构建', () => {
|
||
const renderFn = rendererSrc.match(/function\s+render\s*\(\s*\)\s*\{[\s\S]*?\n\}/);
|
||
assert.ok(renderFn, '找不到 render()');
|
||
assert.ok(
|
||
/buildCard\s*\(/.test(renderFn[0]),
|
||
'render() 没调用 buildCard'
|
||
);
|
||
// 抽函数后,render() 内不应该有 cloneNode(true) 这种属于 buildCard 的细节
|
||
assert.ok(
|
||
!/cloneNode\s*\(\s*true\s*\)/.test(renderFn[0]),
|
||
'render() 还在做 cloneNode,buildCard 抽得不够彻底'
|
||
);
|
||
});
|
||
|
||
// ---------- onAdded 增量插入路径 ----------
|
||
|
||
check('onAdded 在 history Tab + 无搜索时走 prepend 而非 reload', () => {
|
||
const onAdded = rendererSrc.match(/onAdded\s*\(\s*\(\s*\w+\s*\)\s*=>\s*\{[\s\S]*?\}\s*\)/);
|
||
assert.ok(onAdded, '找不到 onAdded 回调');
|
||
// 存在非 reload 的快路径:增量插入。reload 只应出现在跳过分支(收藏 Tab/
|
||
// 搜索中)和 catch 兜底里 —— 最多 2 次。快路径由下一条断言(insertBefore/
|
||
// unshift)单独保证。原计划写死 <=1 与 spec 强制的 catch fallback 冲突,
|
||
// 这里修正为 <=2 以匹配 spec(见 task-7 报告的 controller addendum)。
|
||
const reloadCount = (onAdded[0].match(/\breload\s*\(/g) || []).length;
|
||
assert.ok(reloadCount <= 2, `onAdded 内 reload 次数 ${reloadCount},应是跳过分支 + catch 兜底 ≤ 2 次`);
|
||
// 应该有 prepend 路径或 append 增量逻辑
|
||
assert.ok(
|
||
/insertBefore|prepend|unshift/.test(onAdded[0]),
|
||
'onAdded 没走增量插入路径(看不到 insertBefore / unshift)'
|
||
);
|
||
});
|
||
|
||
check('onAdded 跳过条件:搜索框非空或非 history Tab', () => {
|
||
const onAdded = rendererSrc.match(/onAdded\s*\(\s*\(\s*\w+\s*\)\s*=>\s*\{[\s\S]*?\}\s*\)/);
|
||
assert.ok(onAdded, '找不到 onAdded 回调');
|
||
assert.ok(
|
||
/currentTab\s*!==\s*'history'/.test(onAdded[0]),
|
||
'onAdded 没判断非 history Tab 时跳过 prepend'
|
||
);
|
||
assert.ok(
|
||
/\$search\.value\.trim\s*\(\s*\)\s*!==\s*''/.test(onAdded[0]),
|
||
'onAdded 没判断搜索框非空时跳过 prepend'
|
||
);
|
||
});
|
||
|
||
// ---------- 增量插入的两个回归坑 ----------
|
||
|
||
check('prependClip 熄灭空状态(#empty)', () => {
|
||
// 空列表时 render() 亮起 #empty;第一条增量不走 render(),
|
||
// 不主动隐藏就会出现"卡片 + 暂无内容"同屏。
|
||
const prepend = rendererSrc.match(/function\s+prependClip\s*\([\s\S]*?\n\}/);
|
||
assert.ok(prepend, '找不到 prependClip()');
|
||
assert.ok(
|
||
/\$empty\.classList\.add\(\s*'hidden'\s*\)/.test(prepend[0]),
|
||
'prependClip 没有隐藏 #empty —— 空列表收到第一条增量时空状态不熄灭'
|
||
);
|
||
});
|
||
|
||
check('buildCard 的点击选中按运行时下标,不捕获构建时 i', () => {
|
||
// prependClip 会把已有卡片整体后移,捕获构建时下标的闭包会选中错误的项。
|
||
assert.ok(
|
||
/node\.onclick\s*=\s*\(\)\s*=>\s*select\(\s*\$cards\.indexOf\(node\)\s*\)/.test(rendererSrc),
|
||
'node.onclick 应在点击时从 $cards 现取下标(select($cards.indexOf(node))),而不是捕获构建时的 i'
|
||
);
|
||
});
|
||
|
||
console.log(`\n${passed} checks passed`);
|