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

108 lines
4.7 KiB
JavaScript
Raw 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';
// 在真实 Electron 窗口尺寸(420x690与 main.js openSettingsWindow 一致)下
// 验证设置窗口的标签页与布局。
// 运行electron test/settings-tabs.test.js
const assert = require('node:assert');
const path = require('node:path');
const { app, BrowserWindow, ipcMain } = require('electron');
const cfg = {
autoLaunch: false, maxItems: 0, displayLimit: 300, pollMs: 1000,
dataDir: 'C:\\Users\\guan\\.clipboard-app',
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-render.test.js 同理settings.js 启动时会订阅主题变更,
// stub 缺这个 handler 会往终端打一条未捕获错误(此测试不断言 console
// 但留着噪音会掩盖真问题)。
ipcMain.handle('theme:subscribe', () => true);
let passed = 0;
async function check(name, fn) {
try { await fn(); console.log(' ok -', name); passed++; }
catch (e) { console.error(' FAIL -', name, '\n', e.message); process.exitCode = 1; }
}
app.whenReady().then(async () => {
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,
},
});
await win.loadFile(path.join(__dirname, '..', 'renderer', 'settings.html'));
await new Promise((r) => setTimeout(r, 900));
const js = (code) => win.webContents.executeJavaScript(code);
await check('三个标签存在且文案顺序正确', async () => {
const labels = JSON.parse(await js(
`JSON.stringify([...document.querySelectorAll('#tab-bar [role="tab"]')].map(t => t.textContent.trim()))`
));
assert.deepStrictEqual(labels, ['外观', '通用', '关于']);
});
await check('初始只显示「外观」页', async () => {
const r = JSON.parse(await js(`JSON.stringify({
visible: [...document.querySelectorAll('.tab-panel')].filter(p => !p.hidden).map(p => p.id),
selected: document.querySelector('[role="tab"][aria-selected="true"]').textContent.trim(),
})`));
assert.deepStrictEqual(r.visible, ['panel-appearance']);
assert.strictEqual(r.selected, '外观');
});
await check('点击「通用」切到通用页并互斥', async () => {
const r = JSON.parse(await js(`(() => {
document.getElementById('tab-general').click();
return JSON.stringify({
visible: [...document.querySelectorAll('.tab-panel')].filter(p => !p.hidden).map(p => p.id),
cur: document.getElementById('tab-general').getAttribute('aria-selected'),
prev: document.getElementById('tab-appearance').getAttribute('aria-selected'),
});
})()`));
assert.deepStrictEqual(r.visible, ['panel-general']);
assert.strictEqual(r.cur, 'true');
assert.strictEqual(r.prev, 'false');
});
await check('→ 键切到下一个标签,← 键回上一个', async () => {
const r = JSON.parse(await js(`(() => {
const bar = document.getElementById('tab-bar');
const cur = () => document.querySelector('[role="tab"][aria-selected="true"]').textContent.trim();
const key = (k) => bar.dispatchEvent(new KeyboardEvent('keydown', { key: k, bubbles: true }));
document.getElementById('tab-appearance').click();
key('ArrowRight'); const right = cur();
key('ArrowLeft'); const back = cur();
return JSON.stringify({ right, back });
})()`));
assert.strictEqual(r.right, '通用');
assert.strictEqual(r.back, '外观');
});
await check('每一页在 690px 窗口内都放得下(不需要滚动)', async () => {
const rows = JSON.parse(await js(`JSON.stringify(
[...document.querySelectorAll('#tab-bar [role="tab"]')].map(t => {
t.click();
const p = document.getElementById(t.getAttribute('aria-controls'));
return { id: p.id, clientH: p.clientHeight, scrollH: p.scrollHeight };
})
)`));
for (const r of rows) {
assert.ok(r.scrollH <= r.clientH + 1,
`${r.id} 内容溢出:${r.scrollH}px > 可视 ${r.clientH}px`);
}
});
console.log(`\n${passed} checks passed`);
app.exit(process.exitCode ? 1 : 0);
});