update
This commit is contained in:
107
test/settings-render.test.js
Normal file
107
test/settings-render.test.js
Normal file
@@ -0,0 +1,107 @@
|
||||
'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);
|
||||
});
|
||||
Reference in New Issue
Block a user