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

120 lines
5.0 KiB
JavaScript
Raw Permalink 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';
/**
* 老数据目录(%USERPROFILE%\.clipboard-app→ 新默认目录(项目/exe 同级 data/
* 的一次性迁移。
*
* 三条底线:
* 1. 迁完 config.json 里的 dataDir 必须指向新目录 —— 否则下次启动又跑回老地方;
* 2. 新目录已经在用时不得覆盖(幂等,重复启动不会拿老库盖新库);
* 3. 老文件保留 —— 复制不是移动,出问题能回退。
*/
const assert = require('node:assert');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'clip-mig-'));
const home = path.join(root, 'home');
const target = path.join(root, 'Clipboard Data'); // 模拟 D:\Clipboard Data
const legacy = path.join(home, '.clipboard-app');
process.env.USERPROFILE = home;
process.env.HOME = home;
process.env.CLIPBOARD_APP_DATA_DIR = target;
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; }
}
function resetTarget() {
fs.rmSync(target, { recursive: true, force: true });
}
function seedLegacy(extraCfg) {
fs.rmSync(legacy, { recursive: true, force: true });
fs.mkdirSync(legacy, { recursive: true });
fs.writeFileSync(path.join(legacy, 'history.db'), 'OLD-HISTORY');
fs.writeFileSync(path.join(legacy, 'history.db-wal'), 'OLD-WAL');
fs.writeFileSync(path.join(legacy, 'favorites.db'), 'OLD-FAV');
fs.writeFileSync(path.join(legacy, 'history.db-shm'), 'OLD-SHM');
fs.writeFileSync(
path.join(legacy, 'config.json'),
JSON.stringify({ maxItems: 500, pollMs: 500, theme: 'carbon', dataDir: legacy, ...extraCfg }),
);
}
check('老数据被复制到新目录,且 dataDir 改写为新目录', () => {
resetTarget();
seedLegacy();
const r = cfg.migrateLegacyData();
assert.strictEqual(r.migrated, true);
assert.strictEqual(fs.readFileSync(path.join(target, 'history.db'), 'utf8'), 'OLD-HISTORY');
assert.strictEqual(fs.readFileSync(path.join(target, 'history.db-wal'), 'utf8'), 'OLD-WAL');
assert.strictEqual(fs.readFileSync(path.join(target, 'favorites.db'), 'utf8'), 'OLD-FAV');
const c = cfg.loadConfig();
assert.strictEqual(path.resolve(c.dataDir), path.resolve(target), 'dataDir 必须指向新目录');
assert.strictEqual(c.maxItems, 500, '其他设置要保留');
assert.strictEqual(c.theme, 'carbon');
});
check('-shm 不搬SQLite 自己重建)', () => {
assert.ok(!fs.existsSync(path.join(target, 'history.db-shm')));
});
check('老文件保留,不是移动', () => {
assert.ok(fs.existsSync(path.join(legacy, 'history.db')));
assert.ok(fs.existsSync(path.join(legacy, 'config.json')));
});
check('幂等:新目录已在用时不覆盖', () => {
fs.writeFileSync(path.join(target, 'history.db'), 'NEW-HISTORY');
const r = cfg.migrateLegacyData();
assert.strictEqual(r.migrated, false);
assert.strictEqual(r.reason, 'target-in-use');
assert.strictEqual(fs.readFileSync(path.join(target, 'history.db'), 'utf8'), 'NEW-HISTORY');
});
check('没有老数据时什么都不做', () => {
resetTarget();
fs.rmSync(legacy, { recursive: true, force: true });
const r = cfg.migrateLegacyData();
assert.strictEqual(r.migrated, false);
assert.strictEqual(r.reason, 'nothing-to-migrate');
assert.ok(!fs.existsSync(path.join(target, 'config.json')));
});
check('老 config 指向自定义目录时,从那个目录搬', () => {
resetTarget();
const custom = path.join(root, 'custom');
fs.mkdirSync(custom, { recursive: true });
fs.writeFileSync(path.join(custom, 'history.db'), 'CUSTOM-HISTORY');
seedLegacy({ dataDir: custom });
const r = cfg.migrateLegacyData();
assert.strictEqual(r.migrated, true);
assert.strictEqual(path.resolve(r.from), path.resolve(custom));
assert.strictEqual(fs.readFileSync(path.join(target, 'history.db'), 'utf8'), 'CUSTOM-HISTORY');
assert.strictEqual(path.resolve(cfg.loadConfig().dataDir), path.resolve(target));
});
check('老 config 缺 dataDir 字段时,从老目录搬(不能用 sanitize 回填的新默认目录当源)', () => {
// sanitize 会把缺省的 dataDir 补成新默认目录(= target拿它当 src
// 就是"从 target 搬到 target":什么也没搬却报 migrated老数据永久遗留。
resetTarget();
fs.rmSync(legacy, { recursive: true, force: true });
fs.mkdirSync(legacy, { recursive: true });
fs.writeFileSync(path.join(legacy, 'history.db'), 'OLD-HISTORY');
fs.writeFileSync(path.join(legacy, 'config.json'), JSON.stringify({ maxItems: 100, pollMs: 500 }));
const r = cfg.migrateLegacyData();
assert.strictEqual(r.migrated, true);
assert.strictEqual(path.resolve(r.from), path.resolve(legacy), 'src 必须是老目录');
assert.strictEqual(fs.readFileSync(path.join(target, 'history.db'), 'utf8'), 'OLD-HISTORY');
});
fs.rmSync(root, { recursive: true, force: true });
console.log(`\n${passed} checks passed`);