This commit is contained in:
2026-09-12 14:15:26 +08:00
commit 9c06d3f4be
99 changed files with 41853 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
// shared/ai-errors.js 与 renderer 端 LOCAL_AI_ERROR_FALLBACK 的漂移防护测试
//
// audit fix (CQ-MED-7):之前主进程错误码字面量靠注释提醒同步,实际曾漂移
// renderer ERR_TIMEOUT='ERR_TIMEOUT' 与 main 'AI_TIMEOUT' 对不上,
// aiErrorMessage switch 永不命中)。现在 renderer 在 jsdom 单测里走
// LOCAL_AI_ERROR_FALLBACK 这份本地副本,与 shared/ai-errors.js#AI_ERROR 必须
// 严格一致 —— 本测试校验两边字面值一一对应,新增 / 删除 / 改名都必须在两边同步改。
import { describe, it, expect } from 'vitest';
// shared/ai-errors.js 是 CJSmodule.exports = { AI_ERROR }ESM 解析器
// 不支持 named import from CJS —— vitest 在 node 环境下走 require 链路。
const { AI_ERROR: SHARED_AI_ERROR } = require('../../shared/ai-errors.js');
import { AI_ERROR as RENDERER_AI_ERROR } from '../../src/ai/ai-status.js';
describe('shared/ai-errors.js 与 src/ai/ai-status.js 错误码漂移防护 (CQ-MED-7)', () => {
it('shared 与 renderer 的 key 集合完全一致', () => {
const sharedKeys = Object.keys(SHARED_AI_ERROR).sort();
const rendererKeys = Object.keys(RENDERER_AI_ERROR).sort();
expect(rendererKeys).toEqual(sharedKeys);
});
it('shared 与 renderer 的每个 key 字面值完全一致', () => {
for (const key of Object.keys(SHARED_AI_ERROR)) {
expect(RENDERER_AI_ERROR[key]).toBe(SHARED_AI_ERROR[key]);
}
});
it('renderer 的 AI_ERROR 在 jsdom 环境(无 preload下能取到非空对象', () => {
// 本测试文件跑在 jsdom 下,没有 window.api → 应走 LOCAL_AI_ERROR_FALLBACK。
// 若拿到空对象 / undefined说明 fallback 链路断了 —— 单测会假阳性通过,
// 实际渲染时 aiErrorMessage 永远走 default 分支。
expect(RENDERER_AI_ERROR).toBeDefined();
expect(Object.keys(RENDERER_AI_ERROR).length).toBeGreaterThan(0);
});
it('跨进程错误码main ↔ renderer 都会引用)的字面值是稳定的字符串', () => {
// 不允许 undefined / null / 空串 —— main 返回这些值给 renderer 后,
// ai-controller 会拿它们走 switch落到 default 分支。
for (const code of Object.values(SHARED_AI_ERROR)) {
expect(typeof code).toBe('string');
expect(code.length).toBeGreaterThan(0);
}
});
});