This commit is contained in:
2026-09-12 13:59:12 +08:00
commit 941ce4baab
71 changed files with 13037 additions and 0 deletions

110
test/config.test.js Normal file
View File

@@ -0,0 +1,110 @@
'use strict';
const assert = require('node:assert');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
// 用临时目录隔离,避免污染真实配置。
// 默认数据目录现在是"项目根/data",不再跟 HOME 走 —— 必须用
// CLIPBOARD_APP_DATA_DIR 覆盖,否则测试会写进仓库里的 data/。
const tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), 'clip-cfg-'));
process.env.USERPROFILE = tmpHome;
process.env.HOME = tmpHome;
process.env.CLIPBOARD_APP_DATA_DIR = path.join(tmpHome, 'data');
const cfg = require('../config.js');
let passed = 0;
function check(name, fn) {
try { fn(); console.log(' ok -', name); passed++; }
catch (e) { console.error(' FAIL -', name, '\n', e.message); process.exitCode = 1; }
}
check('defaults 结构完整', () => {
assert.strictEqual(cfg.DEFAULTS.autoLaunch, false);
assert.strictEqual(cfg.DEFAULTS.maxItems, 0);
assert.strictEqual(cfg.DEFAULTS.displayLimit, 300);
assert.strictEqual(cfg.DEFAULTS.pollMs, 1000);
assert.strictEqual(cfg.DEFAULTS.hotkey, 'Ctrl+Alt+V');
assert.ok(typeof cfg.DEFAULTS.dataDir === 'string' && cfg.DEFAULTS.dataDir.length > 0);
});
check('默认数据目录不是 ~/.clipboard-app且被 CLIPBOARD_APP_DATA_DIR 覆盖', () => {
// 不去硬编码 'D:\\Clipboard Data':那是个环境相关的常量,谁换机就炸。
// 这里要测的是两条契约1) 不再是 home 下的 .clipboard-app2) 环境变量能覆盖。
assert.notStrictEqual(path.resolve(cfg.defaultDataDir()), path.resolve(cfg.legacyDataDir()));
assert.strictEqual(path.resolve(cfg.defaultDataDir()), path.resolve(tmpHome, 'data'));
// config.json 跟着默认目录走
assert.strictEqual(path.dirname(cfg.getConfigPath()), path.resolve(cfg.defaultDataDir()));
});
check('默认数据目录D 盘可用时首选 D 盘', () => {
// 默认目录的契约有两个 caseD 盘存在 → 首选 D:\Clipboard Data
// 不存在 → 降级到 home 下的 Clipboard Data。这条只测前者。
const saved = process.env.CLIPBOARD_APP_DATA_DIR;
delete process.env.CLIPBOARD_APP_DATA_DIR;
delete require.cache[require.resolve('../config.js')];
const cfg2 = require('../config.js');
// D 盘在 CI / 开发机上不一定存在,强行断言会让套件不可移植。
// 这里只断言「D 盘可用时返回 D 盘」:先探测一次,能用才断言。
process.env.CLIPBOARD_APP_DATA_DIR = saved;
if (cfg2.isDirUsable('D:\\Clipboard Data')) {
assert.strictEqual(path.resolve(cfg2.defaultDataDir()), path.resolve('D:\\Clipboard Data'));
} else {
// 当前机器 D 盘不可用 → 跳过本断言fallback case 在 data-dir-fallback.test.js
console.log(' (D:\\Clipboard Data 不可用,跳过 — 见 data-dir-fallback.test.js)');
}
});
check('缺文件时 loadConfig 返回全默认', () => {
const c = cfg.loadConfig();
assert.strictEqual(c.maxItems, 0);
assert.strictEqual(c.displayLimit, 300);
assert.strictEqual(c.pollMs, 1000);
assert.strictEqual(c.autoLaunch, false);
});
check('sanitize 回落非法枚举值', () => {
const c = cfg.sanitize({ maxItems: 999, displayLimit: 42, pollMs: 17, autoLaunch: 'yes', dataDir: 42 });
assert.strictEqual(c.maxItems, 0);
assert.strictEqual(c.displayLimit, 300);
assert.strictEqual(c.pollMs, 1000);
assert.strictEqual(c.autoLaunch, false);
assert.strictEqual(typeof c.dataDir, 'string');
});
check('sanitize hotkey非法值回落默认合法预设保留空串 = 禁用不算非法', () => {
// 自由组合键不认 —— 设置界面只给预设档位,白名单外的一律回落
assert.strictEqual(cfg.sanitize({ hotkey: 'Ctrl+Shift+F13' }).hotkey, 'Ctrl+Alt+V');
assert.strictEqual(cfg.sanitize({ hotkey: 42 }).hotkey, 'Ctrl+Alt+V');
assert.strictEqual(cfg.sanitize({ hotkey: 'Alt+Shift+V' }).hotkey, 'Alt+Shift+V');
// '' 是明确的「禁用」语义,绝不能回落默认 —— 否则禁不掉
assert.strictEqual(cfg.sanitize({ hotkey: '' }).hotkey, '');
// 老配置没有 hotkey 字段(升级场景)→ 默认,等于自动获得快捷键
assert.strictEqual(cfg.sanitize({}).hotkey, 'Ctrl+Alt+V');
// 默认值本身必须在白名单里(否则首次启动的 register 必炸)
assert.ok(cfg.ALLOWED_HOTKEYS.includes(cfg.DEFAULTS.hotkey));
// 白名单里的每一个值都得能通过自己(防 ALLOWED_HOTKEYS 与默认值写岔)
for (const k of cfg.ALLOWED_HOTKEYS) {
assert.strictEqual(cfg.sanitize({ hotkey: k }).hotkey, k, `白名单成员 ${JSON.stringify(k)} 应通过校验`);
}
});
check('save 后 load 往返一致', () => {
cfg.saveConfig({ autoLaunch: true, maxItems: 1000, displayLimit: 500, pollMs: 500, dataDir: tmpHome, hotkey: 'Ctrl+Alt+C' });
const c = cfg.loadConfig();
assert.strictEqual(c.autoLaunch, true);
assert.strictEqual(c.maxItems, 1000);
assert.strictEqual(c.displayLimit, 500);
assert.strictEqual(c.pollMs, 500);
assert.strictEqual(c.dataDir, tmpHome);
assert.strictEqual(c.hotkey, 'Ctrl+Alt+C');
});
check('坏 JSON 不抛异常,返回默认', () => {
fs.writeFileSync(cfg.getConfigPath(), '{ this is not json ');
const c = cfg.loadConfig();
assert.strictEqual(c.maxItems, 0);
});
console.log(`\n${passed} checks passed`);