update
This commit is contained in:
84
test/echo-wiring.test.js
Normal file
84
test/echo-wiring.test.js
Normal file
@@ -0,0 +1,84 @@
|
||||
'use strict';
|
||||
/**
|
||||
* 回声抑制的**接线**断言:main.js 必须真的在用 lib/echo-suppress.js 的本体。
|
||||
*
|
||||
* 为什么需要这份测试:echo-suppress.test.js 只测 lib 本体。本体的行为全对,
|
||||
* 也挡不住 main.js 把接线改坏 —— 比如漏调 seed(每次重启把剪贴板里的旧内容
|
||||
* 重入一次)、漏调 markOwnWrite(自己的复制被当新内容重复入库)、observe 的
|
||||
* 返回值不再按四态分发('empty' 当 'new' 入库 = 空剪贴板噪音灌满列表)。
|
||||
* lib 测试对这类回归永远是绿的 —— 正是这个文件头当年批评旧测试的那句话。
|
||||
*
|
||||
* 风格沿用 window-factory.test.js / window-lifecycle.test.js 的静态断言:
|
||||
* grep main.js 源码里的调用点。静态断言测不了运行时,但能拦住"重构时把
|
||||
* 调用点删了/改名了"这类最常见的接线回归,成本几乎为零。
|
||||
*/
|
||||
const assert = require('node:assert');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const MAIN = fs.readFileSync(path.join(__dirname, '..', 'main.js'), 'utf8');
|
||||
|
||||
let passed = 0;
|
||||
function check(name, fn) {
|
||||
try { fn(); console.log(' ok -', name); passed++; }
|
||||
catch (e) { console.error(' FAIL -', name, '\n', e.message); process.exitCode = 1; }
|
||||
}
|
||||
|
||||
check('main.js 引用的是 lib/echo-suppress 本体', () => {
|
||||
assert.match(MAIN, /require\('\.\/lib\/echo-suppress'\)/);
|
||||
const { createEchoSuppress } = require('../lib/echo-suppress.js');
|
||||
assert.strictEqual(typeof createEchoSuppress, 'function');
|
||||
});
|
||||
|
||||
check('文本 / 图片各一个独立状态机实例(两份状态不能共用)', () => {
|
||||
assert.match(MAIN, /textSuppress\s*=\s*createEchoSuppress\(\)/);
|
||||
assert.match(MAIN, /imageSuppress\s*=\s*createEchoSuppress\(\)/);
|
||||
const instances = MAIN.match(/createEchoSuppress\(\)/g) || [];
|
||||
assert.strictEqual(instances.length, 2, `应有且仅有 2 个实例,实际 ${instances.length}`);
|
||||
});
|
||||
|
||||
check('启动采样两条线都调 seed:漏掉会导致重启时旧内容重入库', () => {
|
||||
assert.match(MAIN, /textSuppress\.seed\(/);
|
||||
assert.match(MAIN, /imageSuppress\.seed\(/);
|
||||
});
|
||||
|
||||
check('轮询两条线都调 observe:漏掉 text 的 = 搜索不到新复制,漏掉 image 的 = 图片全丢', () => {
|
||||
assert.match(MAIN, /textSuppress\.observe\(/);
|
||||
assert.match(MAIN, /imageSuppress\.observe\(/);
|
||||
});
|
||||
|
||||
check('observe 的四态都被分发:empty / suppressed / new 各自有分支', () => {
|
||||
// unchanged 不需要显式分支(落空即图片分支),但其余三态必须显式处理。
|
||||
// 漏 'empty':清空剪贴板的 '' 会被当新文本入库;漏 'suppressed':自己的回声重复入库。
|
||||
for (const verdict of ['empty', 'suppressed', 'new']) {
|
||||
assert.ok(
|
||||
MAIN.includes(`verdict === '${verdict}'`),
|
||||
`pollClipboard 缺少对 '${verdict}' 的分发`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
check('写剪贴板两条线都调 markOwnWrite:漏掉 = 点"复制"后自己的回声被当新内容入库', () => {
|
||||
assert.match(MAIN, /textSuppress\.markOwnWrite\(/);
|
||||
assert.match(MAIN, /imageSuppress\.markOwnWrite\(/);
|
||||
});
|
||||
|
||||
check('1×1 空图走 resetBaseline 而不是直接赋基线', () => {
|
||||
assert.match(MAIN, /imageSuppress\.resetBaseline\(\)/);
|
||||
});
|
||||
|
||||
check('入库失败两条线都 abortLastObserve:漏掉 = 用户那条复制永久吞掉直到重启', () => {
|
||||
// 用户报告"卡住"的核心修法:observe 把 last 设成新内容后入库失败,
|
||||
// 必须回滚基线,否则下次 tick 读到同一条内容判 'unchanged' 静默吞掉。
|
||||
assert.match(MAIN, /textSuppress\.abortLastObserve\(\)/);
|
||||
assert.match(MAIN, /imageSuppress\.abortLastObserve\(\)/);
|
||||
});
|
||||
|
||||
check('复制失败的两条 catch 都 clearPending:漏掉会吞掉用户下一次真实复制', () => {
|
||||
const clears = MAIN.match(/textSuppress\.clearPending\(\)/g) || [];
|
||||
assert.ok(clears.length >= 2, `textSuppress.clearPending 应至少 2 处(clip / fav 复制),实际 ${clears.length}`);
|
||||
const imgClears = MAIN.match(/imageSuppress\.clearPending\(\)/g) || [];
|
||||
assert.ok(imgClears.length >= 2, `imageSuppress.clearPending 应至少 2 处,实际 ${imgClears.length}`);
|
||||
});
|
||||
|
||||
console.log(`\n${passed} checks passed`);
|
||||
Reference in New Issue
Block a user