This commit is contained in:
2026-09-20 23:35:03 +08:00
parent 941ce4baab
commit 388c700996
19 changed files with 393 additions and 71 deletions

View File

@@ -80,6 +80,18 @@ check('prependClip 熄灭空状态(#empty)', () => {
);
});
check('prependClip 重排 slot 徽标数字(后移的卡序号 +1)', () => {
// 新卡插到最顶后,原第 1-9 位的卡整体后移:只隐藏第 10 位会留下两个「1」,
// 数字键 1-9 按实际下标复制,显示序号与按键错位。曾被"优化"成只动边界卡,
// 这里守住:必须把后移卡的 textContent 改写成 i+1。
const prepend = rendererSrc.match(/function\s+prependClip\s*\([\s\S]*?\n\}/);
assert.ok(prepend, '找不到 prependClip()');
assert.ok(
/slotEl\.textContent\s*=\s*String\(\s*i\s*\+\s*1\s*\)/.test(prepend[0]),
'prependClip 没有改写后移卡片的 slot 数字 —— 序号会与实际下标错位'
);
});
check('buildCard 的点击选中按运行时下标,不捕获构建时 i', () => {
// prependClip 会把已有卡片整体后移,捕获构建时下标的闭包会选中错误的项。
assert.ok(

View File

@@ -136,6 +136,33 @@ check('defaultDataDir: D 盘可用时首选 D 盘(契约保留)', () => {
}
});
// ---------- main.js 源码级契约:兜底状态下 openDb/openFavDb 不能 mkdir 坏目录 ----------
// 启动时 dataDir 不可用会切到 sessionDataDir 兜底,但 openDb/openFavDb 如果
// mkdir 的是裸 appConfig.dataDir(坏目录),mkdirSync 直接抛 ENOENT ——
// 兜底逻辑被这一行废掉,照样弹「启动失败」。pin 住:两个函数都必须 mkdir
// effectiveDataDir()(含 session 兜底)。
{
const mainSrc = fs.readFileSync(path.join(__dirname, '..', 'main.js'), 'utf8');
const openDbFn = mainSrc.match(/function openDb\(\) \{[\s\S]*?\n\}/);
const openFavDbFn = mainSrc.match(/function openFavDb\(\) \{[\s\S]*?\n\}/);
check('openDb mkdir effectiveDataDir()(含 session 兜底),不是裸 appConfig.dataDir', () => {
assert.ok(openDbFn, '找不到 openDb 函数');
assert.ok(
/mkdirSync\(\s*effectiveDataDir\(\s*\)/.test(openDbFn[0]),
'openDb 仍在 mkdir appConfig.dataDir —— 配置目录不可用时兜底失效,启动照样失败'
);
});
check('openFavDb mkdir effectiveDataDir()(含 session 兜底),不是裸 appConfig.dataDir', () => {
assert.ok(openFavDbFn, '找不到 openFavDb 函数');
assert.ok(
/mkdirSync\(\s*effectiveDataDir\(\s*\)/.test(openFavDbFn[0]),
'openFavDb 仍在 mkdir appConfig.dataDir —— 配置目录不可用时兜底失效,启动照样失败'
);
});
}
// 清理
fs.rmSync(tmpHome, { recursive: true, force: true });
console.log(`\n${passed} checks passed`);

View File

@@ -35,6 +35,9 @@ ipcMain.handle('theme:set-follow-system', () => ({ theme: cfg.theme, accent: cfg
// invoke 会抛错,渲染层的 catch 打 console.error,被下面的"无脚本错误"
// 断言当成 SyntaxError 一类的致命问题误杀。
ipcMain.handle('theme:subscribe', () => true);
// settings.js 启动时还会拉标题栏图标(window.api.getAppIcon -> app:get-icon),
// stub 缺这个 handler 同样打一条未捕获错误噪音;返回空串表示图标缺失(静默路径)。
ipcMain.handle('app:get-icon', () => '');
let failed = 0;
function check(name, fn) {

View File

@@ -25,6 +25,9 @@ ipcMain.handle('theme:set-follow-system', () => ({ theme: cfg.theme, accent: cfg
// stub 缺这个 handler 会往终端打一条未捕获错误(此测试不断言 console,
// 但留着噪音会掩盖真问题)。
ipcMain.handle('theme:subscribe', () => true);
// settings.js 启动时还会拉标题栏图标(window.api.getAppIcon -> app:get-icon),
// stub 缺这个 handler 同样打一条未捕获错误噪音;返回空串表示图标缺失(静默路径)。
ipcMain.handle('app:get-icon', () => '');
let passed = 0;
async function check(name, fn) {