118 lines
5.5 KiB
JavaScript
118 lines
5.5 KiB
JavaScript
'use strict';
|
||
/**
|
||
* 「跟随系统」开 / 关 时主题显示一致性的接线测试。
|
||
*
|
||
* 历史问题:theme:get / applyThemeChange 旧实现返回的是 appConfig.theme(raw),
|
||
* 渲染端拿到后直接设 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`);
|