Files
Clipboard/test/theme-effective.test.js
2026-09-12 13:59:12 +08:00

118 lines
5.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
/**
* 「跟随系统」开 / 关 时主题显示一致性的接线测试。
*
* 历史问题theme:get / applyThemeChange 旧实现返回的是 appConfig.themeraw
* 渲染端拿到后直接设 data-theme ——「跟随系统」开着的状态下,初次打开设置窗口
* 显示的是 raw 主题(比如 midnight只有等到系统主题切换广播来才换。
* settings 窗口根本收不到那条广播(没切换),于是永远显示错的。
*
* 修法main.js 返回 effectiveTheme带 rawTheme 字段兜底),渲染端按
* effectiveTheme 设 DOM。theme-boot 也读 effectiveTheme 以避免冷启动闪。
*
* 这里钉住三件事,避免后续改动把 effective 字段删了回退到 raw
* 1. main.js 的 theme:get / applyThemeChange / broadcastTheme 三个出口
* 都给 effectiveTheme 字段;
* 2. 渲染端renderer + settings优先用 effectiveTheme 设置 data-theme
* 3. theme-boot.js 在缓存命中时也用 effectiveTheme。
*/
const assert = require('node:assert');
const fs = require('node:fs');
const path = require('node:path');
const root = path.join(__dirname, '..');
const read = (p) => fs.readFileSync(path.join(root, p), 'utf8');
const mainSrc = read('main.js');
const rendererSrc = read('renderer/renderer.js');
const settingsSrc = read('renderer/settings.js');
const themeBootSrc = read('renderer/theme-boot.js');
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; }
}
// ---------- 主进程:所有主题出口都带 effectiveTheme ----------
check('config.effectiveTheme 存在并被 main.js 引用', () => {
assert.match(mainSrc, /configMod\.effectiveTheme\s*\(/,
'main.js 没用 configMod.effectiveTheme —— 跟随系统仍可能在 IPC 出口回退到 raw theme');
});
check('broadcastTheme 广播 effectiveTheme 字段', () => {
const fn = mainSrc.match(/function\s+broadcastTheme\s*\([\s\S]*?\n\}/);
assert.ok(fn, '找不到 broadcastTheme');
assert.match(fn[0], /effectiveTheme\s*:/,
'broadcastTheme 没带 effectiveTheme 字段,订阅的窗口拿不到跟随系统状态');
});
check('applyThemeChange 返回值带 effectiveTheme', () => {
const fn = mainSrc.match(/function\s+applyThemeChange\s*\([\s\S]*?\n\}/);
assert.ok(fn, '找不到 applyThemeChange');
assert.match(fn[0], /effectiveTheme\s*:/,
'applyThemeChange 返回值没带 effectiveTheme —— settings.js 收到 raw theme 会盖掉刚广播的 effective');
});
check('theme:get 处理器返回 effectiveTheme', () => {
const handler = mainSrc.match(/ipcMain\.handle\(\s*'theme:get'[\s\S]*?\n\s{2}\}\s*\)\s*;/);
assert.ok(handler, '找不到 theme:get 处理器');
assert.match(handler[0], /effectiveTheme/,
'theme:get 返回值没带 effectiveTheme —— 启动时设置窗口 / 主窗口会显示 raw 主题');
});
// ---------- 渲染端:用 effectiveTheme 设 data-theme ----------
check('renderer.js 的 applyTheme 用 effectiveTheme 设 data-theme', () => {
const fn = rendererSrc.match(/async\s+function\s+applyTheme\s*\([\s\S]*?\n\}/);
assert.ok(fn, '找不到 applyTheme');
// 必须显式读 cfg.effectiveTheme 而不是 cfg.theme
assert.match(fn[0], /cfg\.effectiveTheme\s*\|\|\s*cfg\.theme/,
'applyTheme 没读 effectiveTheme ——「跟随系统」开时 data-theme 是 raw 主题');
});
check('renderer.js 的 applyTheme 在 localStorage 里同时缓存 raw 和 effective', () => {
// theme-boot 启动读 cache需要 effectiveTheme 才能避免冷启动闪
const fn = rendererSrc.match(/async\s+function\s+applyTheme\s*\([\s\S]*?\n\}/);
assert.ok(fn, '找不到 applyTheme');
assert.match(fn[0], /rawTheme[\s\S]*?effectiveTheme/,
'applyTheme 没把 raw 和 effective 同时写 localStorage —— 启动会有闪');
});
check('renderer.js 的 onSystemChanged 不再写 localStorage避免覆盖 raw', () => {
const fn = rendererSrc.match(/onSystemChanged\(\s*\(payload\)\s*=>\s*\{[\s\S]*?\}\s*\)/);
assert.ok(fn, '找不到 onSystemChanged 回调');
// 注释也明确写了为什么不写payload 里没 rawTheme
assert.ok(
!/localStorage\.setItem/.test(fn[0]),
'onSystemChanged 在写 localStorage —— payload 没有 rawTheme下次启动会拿不到 raw'
);
// DOM 更新仍然要用 effective
assert.match(fn[0], /effectiveTheme\s*\|\|\s*payload\.theme/,
'onSystemChanged 没读 effectiveTheme');
});
check('settings.js initTheme 用 effectiveTheme', () => {
const fn = settingsSrc.match(/async\s+function\s+initTheme\s*\([\s\S]*?\n\}/);
assert.ok(fn, '找不到 initTheme');
assert.match(fn[0], /cfg\.effectiveTheme\s*\|\|\s*cfg\.theme/,
'initTheme 没读 effectiveTheme —— 设置窗口初次打开「跟随系统」开时显示 raw');
});
check('settings.js onSystemChanged 用 effectiveTheme', () => {
const fn = settingsSrc.match(/onSystemChanged\(\s*\(payload\)\s*=>\s*\{[\s\S]*?\}\s*\)/);
assert.ok(fn, '找不到 settings.js onSystemChanged');
assert.match(fn[0], /effectiveTheme\s*\|\|\s*payload\.theme/,
'settings.js onSystemChanged 没读 effectiveTheme');
});
// ---------- theme-boot冷启动也用 effectiveTheme 避免闪 ----------
check('theme-boot.js 优先读 effectiveTheme避免「跟随系统」开时冷启动闪', () => {
assert.match(themeBootSrc, /effectiveTheme\s*\|\|\s*cached\.theme/,
'theme-boot.js 没读 effectiveTheme —— 冷启动在「跟随系统」开时会闪一下 raw 主题');
});
console.log(`\n${passed} checks passed`);