const fs = require('fs'); const os = require('os'); const path = require('path'); const { app, BrowserWindow } = require('electron'); const ROOT = path.resolve(__dirname, '..', '..', '..'); const TMP = fs.mkdtempSync(path.join(os.tmpdir(), 'peoplelib-startup-ui-')); app.setPath('appData', TMP); process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true'; const results = []; function check(name, pass, detail) { results.push([pass ? 'OK' : 'FAIL', name, detail || '']); } async function waitUntil(fn, timeout = 10000) { const end = Date.now() + timeout; while (Date.now() < end) { try { const value = await fn(); if (value) return value; } catch (e) { /* 窗口仍在加载 */ } await new Promise((resolve) => setTimeout(resolve, 25)); } throw new Error(`等待条件超时(${timeout}ms)`); } function printSummary() { console.log('\n========== 启动响应集成验证 =========='); for (const [status, name, detail] of results) { console.log(`${status.padEnd(5)} ${name}${detail ? ` [${detail}]` : ''}`); } const failed = results.filter((item) => item[0] === 'FAIL').length; console.log(`\n通过 ${results.length - failed}/${results.length}`); return failed; } app.whenReady().then(async () => { const library = require(path.join(ROOT, 'src', 'library', 'store')); let scanStartedAt = 0; library.scan = () => { scanStartedAt = Date.now(); Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 2200); return { added: 0, missing: 0, total: 0 }; }; const startedAt = Date.now(); require(path.join(ROOT, 'main.js')); const win = await waitUntil(() => ( BrowserWindow.getAllWindows().find((item) => item.getTitle() === 'PeopleLib') )); win.hide(); await waitUntil(() => win.webContents.executeJavaScript( `document.readyState === 'complete' && ['dark', 'light'].includes(document.documentElement.dataset.uiTheme)` )); const configReadyMs = Date.now() - startedAt; check('慢速书库扫描不会阻塞窗口配置加载', configReadyMs < 1200, `${configReadyMs}ms`); const sourceRows = await waitUntil(() => win.webContents.executeJavaScript(`(() => { const rows = Array.from(document.querySelectorAll('#sourceList input[data-id]')).map((input) => ({ id: input.dataset.id, checked: input.checked, name: input.parentElement.querySelector('span').textContent })); return rows.length >= 16 ? rows : null; })()`)); const expectedSources = ['openstax', 'opentextbook', 'wikisource-zh', 'wikisource-en']; check('新增开放书源出现在设置页且新安装默认启用', expectedSources.every((id) => sourceRows.some((row) => row.id === id && row.checked)), sourceRows.filter((row) => expectedSources.includes(row.id)).map((row) => `${row.id}:${row.name}`).join(', ')); await waitUntil(() => scanStartedAt > 0, 7000); check('启动维护在首屏完成后延迟执行', scanStartedAt - startedAt >= 1400, `${scanStartedAt - startedAt}ms`); for (const window of BrowserWindow.getAllWindows()) { if (!window.isDestroyed()) window.destroy(); } const failed = printSummary(); app.exit(failed ? 1 : 0); }).catch((error) => { console.error('异常:', error); check('启动验证未发生异常', false, error.message || String(error)); for (const window of BrowserWindow.getAllWindows()) { if (!window.isDestroyed()) window.destroy(); } printSummary(); app.exit(1); });