'use strict'; /** * 测试入口。 * * 为什么要有这个文件,而不是在 package.json 里串一长串 && : * * 1. ABI。better-sqlite3 是原生模块,只能编译给一个运行时。仓库里它是按 * Electron 的 ABI 编译的(postinstall / npm run rebuild),所以用普通 * `node` 跑任何碰 DB 的测试都会直接 ERR_DLOPEN_FAILED。 * 解法:用 ELECTRON_RUN_AS_NODE=1 借 Electron 自带的 node 来跑 —— * ABI 天然对得上,而且测的就是应用真正加载的那个二进制。 * * 2. 手写清单会漏。settings-render.test.js 就这么被漏掉过:文件在、 * 专门防一类回归,但从来没被执行。这里改成扫目录,新加的测试自动进来。 */ const { spawnSync } = require('node:child_process'); const fs = require('node:fs'); const path = require('node:path'); const testDir = __dirname; // 需要真实 Electron GUI(BrowserWindow / app)的,走 npm run test:ui const GUI_ONLY = new Set(['settings-tabs.test.js', 'settings-render.test.js']); // 用 node:test 运行器的 const NODE_TEST_RUNNER = new Set(['theme.test.js']); const files = fs.readdirSync(testDir) .filter((f) => f.endsWith('.test.js') && !GUI_ONLY.has(f)) .sort(); if (files.length === 0) { console.error('没有找到任何测试文件'); process.exit(1); } function electronBin() { try { return require('electron'); // 返回可执行文件的绝对路径 } catch (_) { return null; } } const bin = electronBin(); if (!bin || typeof bin !== 'string') { console.error('找不到 electron。先跑 npm install。'); process.exit(1); } const failed = []; for (const f of files) { const args = NODE_TEST_RUNNER.has(f) ? ['--test', path.join(testDir, f)] : [path.join(testDir, f)]; console.log(`\n─── ${f} ${'─'.repeat(Math.max(0, 56 - f.length))}`); const r = spawnSync(bin, args, { stdio: 'inherit', env: { ...process.env, ELECTRON_RUN_AS_NODE: '1' }, }); if (r.status !== 0) failed.push(f); } console.log('\n' + '═'.repeat(64)); if (failed.length) { console.error(`✗ ${failed.length}/${files.length} 个测试文件失败:`); for (const f of failed) console.error(' - ' + f); process.exit(1); } console.log(`✓ ${files.length} 个测试文件全部通过`);