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

108 lines
4.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';
/**
* 回归测试:设置窗口必须真正渲染出配置内容(尤其是"数据保存位置"路径)。
*
* 守护两类曾经发生过的静默失败:
* 1. settings.js 顶层 `const themeApi` 与 contextBridge 暴露的不可配置全局属性
* window.themeApi 同名 → 脚本实例化阶段抛 SyntaxError整个文件一行都不执行。
* 2. 重构时误删了末尾的 refresh() 调用 → 函数定义了却从未调用,界面全空白。
*
* 两种情况下界面都"看起来正常"但内容为空,只有断言 DOM 实际文本才能发现。
* 运行npx electron test/settings-render.test.js
*/
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('node:path');
const assert = require('node:assert');
const DATA_DIR = 'C:\\Users\\probe\\.clipboard-app';
const cfg = {
// 只用 config.js ALLOWED_* 里的合法值,且必须是 settings.html 里存在的 <option>
autoLaunch: false, maxItems: 0, displayLimit: 300, pollMs: 1000,
hotkey: 'Ctrl+Alt+V',
dataDir: DATA_DIR, theme: 'linear', accent: 'purple', followSystem: false,
};
ipcMain.handle('settings:get', () => ({ ...cfg }));
ipcMain.handle('settings:set', () => ({ ...cfg }));
ipcMain.handle('settings:clear-history', () => 0);
ipcMain.handle('settings:open-dir', () => {});
ipcMain.handle('settings:choose-dir', () => ({ ok: false }));
ipcMain.handle('theme:get', () => ({ ...cfg }));
ipcMain.handle('theme:set', (_e, { theme }) => ({ theme, accent: cfg.accent }));
ipcMain.handle('theme:set-accent', (_e, { accent }) => ({ theme: cfg.theme, accent }));
ipcMain.handle('theme:set-follow-system', () => ({ theme: cfg.theme, accent: cfg.accent }));
// settings.js 的 initTheme() 会订阅主题变更stub 里缺这个 handler 时
// invoke 会抛错,渲染层的 catch 打 console.error被下面的"无脚本错误"
// 断言当成 SyntaxError 一类的致命问题误杀。
ipcMain.handle('theme:subscribe', () => true);
let failed = 0;
function check(name, fn) {
try { fn(); console.log(' ok -', name); }
catch (e) { console.error(' FAIL -', name, '\n ', e.message); failed++; }
}
app.whenReady().then(async () => {
// 与 main.js openSettings() 一致的窗口尺寸
const win = new BrowserWindow({
width: 420, height: 690, show: false, frame: false, resizable: false,
webPreferences: {
preload: path.join(__dirname, '..', 'preload.js'),
contextIsolation: true, nodeIntegration: false, sandbox: false,
},
});
const errors = [];
win.webContents.on('console-message', (_e, level, message) => {
// level 3 = error
if (level === 3) errors.push(message);
});
await win.loadFile(path.join(__dirname, '..', 'renderer', 'settings.html'));
await new Promise((r) => setTimeout(r, 900));
const state = await win.webContents.executeJavaScript(`(() => {
const dir = document.getElementById('opt-datadir');
const grid = document.getElementById('theme-grid');
const accents = document.getElementById('accent-grid');
return {
dirText: dir ? dir.textContent : null,
themeCards: grid ? grid.children.length : -1,
accentSwatches: accents ? accents.children.length : -1,
maxItems: (document.getElementById('opt-maxitems')||{}).value,
displayLimit: (document.getElementById('opt-displaylimit')||{}).value,
pollMs: (document.getElementById('opt-pollms')||{}).value,
hotkey: (document.getElementById('opt-hotkey')||{}).value,
};
})()`);
console.log('设置窗口渲染回归测试:');
check('settings.js 无脚本错误SyntaxError 会让整个文件不执行)', () => {
assert.deepStrictEqual(errors, []);
});
check('"数据保存位置" 渲染出真实路径', () => {
assert.strictEqual(state.dirText, DATA_DIR);
});
check('主题网格已渲染出 6 张卡片', () => {
assert.strictEqual(state.themeCards, 6);
});
check('强调色已渲染出 5 个色块', () => {
assert.strictEqual(state.accentSwatches, 5);
});
check('最大保留条数已回填配置值', () => {
assert.strictEqual(state.maxItems, '0');
});
check('界面显示条数已回填配置值', () => {
assert.strictEqual(state.displayLimit, '300');
});
check('轮询间隔已回填配置值', () => {
assert.strictEqual(state.pollMs, '1000');
});
check('唤起快捷键已回填配置值', () => {
assert.strictEqual(state.hotkey, 'Ctrl+Alt+V');
});
console.log(failed === 0 ? '\n全部通过' : `\n${failed} 项失败`);
app.exit(failed === 0 ? 0 : 1);
});