- 覆盖率 96.42%(行):新增 59 测试共 385 个,覆盖 DOM 交互事件、对话框按钮交互、Intl/localStorage 异常路径、React 渲染生命周期 - 测试环境重构:SSR 分支用 defineProperty 真正覆盖 document/window;新增 tests/dom.test.ts、tests/setup.ts - jest 覆盖率门禁 lines >= 95%;CI lint 改必过;新增 publish.yml(v* tag 自动发布到 Gitea registry) - 修复:Toast.off 空数组残留、Toast.on 取消函数 this 绑定、action close:false 冒泡关闭、use() 重复注册钩子、i18n catch 引用错误 - 删除死代码 autoApplySystemTheme;lint 零警告(no-console 策略 + caughtErrorsIgnorePattern)
59 lines
2.3 KiB
TypeScript
59 lines
2.3 KiB
TypeScript
/**
|
||
* 环境隔离测试 — 需要切换 document/window/localStorage 环境并调用 jest.resetModules()。
|
||
* 独立成文件:resetModules 会清空模块缓存,若与其他测试同文件会导致
|
||
* 后续 require 拿到新模块实例、与 import 时绑定的实例状态分裂。
|
||
* 注:jsdom 以 getter 暴露 document/window,普通赋值无效,须用 defineProperty 覆盖。
|
||
* @module tests
|
||
* @version 0.5.0
|
||
*/
|
||
|
||
/** 临时移除全局对象,返回恢复函数 */
|
||
const hideGlobal = (key: string): (() => void) => {
|
||
const desc = Object.getOwnPropertyDescriptor(global, key);
|
||
Object.defineProperty(global, key, { value: undefined, configurable: true, writable: true });
|
||
return () => {
|
||
if (desc) Object.defineProperty(global, key, desc);
|
||
else delete (global as Record<string, unknown>)[key];
|
||
};
|
||
};
|
||
|
||
describe('环境隔离(SSR / localStorage 异常路径)', () => {
|
||
test('escapeHTML SSR 路径(无 document)', () => {
|
||
const restore = hideGlobal('document');
|
||
jest.resetModules();
|
||
const { escapeHTML } = require('../src/utils.js');
|
||
const result = escapeHTML('<script>alert("xss")</script>');
|
||
expect(result).not.toContain('<script>');
|
||
expect(result).toContain('<script>');
|
||
restore();
|
||
});
|
||
|
||
test('prefersDark 无 window 时返回 false', () => {
|
||
const restore = hideGlobal('window');
|
||
jest.resetModules();
|
||
const { prefersDark } = require('../src/utils.js');
|
||
expect(prefersDark()).toBe(false);
|
||
restore();
|
||
});
|
||
|
||
test('saveTheme localStorage 异常被捕获', () => {
|
||
const orig = (global as Record<string, unknown>).localStorage;
|
||
(global as Record<string, unknown>).localStorage = undefined;
|
||
jest.resetModules();
|
||
const { saveTheme } = require('../src/themes.js');
|
||
expect(() => saveTheme('dark')).not.toThrow();
|
||
(global as Record<string, unknown>).localStorage = orig;
|
||
});
|
||
|
||
test('loadLocale localStorage 异常返回 default', () => {
|
||
const orig = (global as Record<string, unknown>).localStorage;
|
||
(global as Record<string, unknown>).localStorage = {
|
||
getItem: () => { throw new Error('quota'); },
|
||
};
|
||
jest.resetModules();
|
||
const { loadLocale } = require('../src/i18n.js');
|
||
expect(typeof loadLocale()).toBe('string');
|
||
(global as Record<string, unknown>).localStorage = orig;
|
||
});
|
||
});
|