This commit is contained in:
2026-09-12 13:55:57 +08:00
commit 30f1cedd39
95 changed files with 42057 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
// 回归测试H7 — modified 默认选择是 'both'OR 合并状态)
//
// 背景:旧版 defaultResolutions 把 modified 默认设为 'b'(用本地)。这导致
// 磁盘侧修改的标记completed / important / current被默默丢弃 ——
// 用户可能根本不知道,文件里的重要标记就消失了。
//
// 修复v3.7+modified 默认 'both'OR 合并。current 在 v4 起改为:
// - 仅一边 current=true → OR 保留(修复 H3用户在 UI 标 [▶] 后,磁盘
// 还没同步,合并不丢标记)
// - 两边都 current=true → 强制 false仍是单值指针
// 跑法node scripts/check-conflict-default.mjs
import { defaultResolutions, diffCategories, applyResolutions } from '../src/utils/markdown-diff.js';
import { check, summary, printSummary } from './_lib/check.mjs';
const makeCat = (name, kind = 'normal', parentOtherTasks = true, tasks = []) =>
({ name, kind, isSpecial: false, meta: null, parentOtherTasks, tasks });
const container = { name: '全部任务', kind: 'other_tasks', isSpecial: true, meta: null, parentOtherTasks: false, tasks: [] };
const trash = { name: '回收站', kind: 'trash', isSpecial: true, meta: null, parentOtherTasks: false, tasks: [] };
// ── [1] defaultResolutionsmodified 默认 'both' ──
console.log('\n[1] defaultResolutionsmodified 默认 "both"');
{
// v4 起completed=true 任务也参与 diff按 effective cat name所以两侧都用
// completed=falseimportant 字段不同即可触发 modified。
const catsA = [
container,
makeCat('工作', 'normal', true, [
{ text: 'X', completed: false, important: true, current: false }, // 仅 A
]),
makeCat('学习', 'normal', true, [
{ text: 'Y', completed: false, important: true, current: false }, // modified两侧 important 不同)
]),
trash,
];
const catsB = [
container,
makeCat('工作', 'normal', true, [
{ text: 'Z', completed: false, important: false, current: false }, // 仅 B
]),
makeCat('学习', 'normal', true, [
{ text: 'Y', completed: false, important: false, current: false }, // 与 A 文本同important 不同
]),
trash,
];
const diff = diffCategories(catsA, catsB);
const res = defaultResolutions(diff);
check('diff 至少一条 modified', diff.modified.length >= 1,
`modified=${JSON.stringify(diff.modified)}`);
check('diff 有 onlyInAX', diff.onlyInA.length >= 1);
check('diff 有 onlyInBZ', diff.onlyInB.length >= 1);
// modified 默认值
const modifiedKey = diff.modified[0].key;
check(`modified 默认是 'both'`,
res[modifiedKey] === 'both',
`actual=${res[modifiedKey]}, key=${modifiedKey}`);
check(`onlyInA 默认是 'a'`,
res[diff.onlyInA[0].key] === 'a');
check(`onlyInB 默认是 'b'`,
res[diff.onlyInB[0].key] === 'b');
}
// ── [2] 仅 modified无 onlyIn* —— 默认仍 'both' ──
console.log('\n[2] 纯 modified 场景:默认值仍是 "both"');
{
// v4completed=false 两侧 + important 不同 —— 进入 modified 分支。
const catsA = [container, makeCat('工作', 'normal', true, [
{ text: 'T', completed: false, important: true, current: false },
]), trash];
const catsB = [container, makeCat('工作', 'normal', true, [
{ text: 'T', completed: false, important: false, current: false },
]), trash];
const diff = diffCategories(catsA, catsB);
const res = defaultResolutions(diff);
check('纯 modified diff 的 default 是 both',
diff.modified.length === 1 && res[diff.modified[0].key] === 'both',
`modified.len=${diff.modified.length}, res=${JSON.stringify(res)}`);
}
// ── [3] applyResolutionsmodified 默认 'both'(无显式 resolution 时) ──
console.log('\n[3] applyResolutionsmodified 默认 "both"OR 合并)');
{
// 两侧 completed=falseimportant 不同 → 进 modified
// catsB 有 current=truecatsA 是 false —— v4 H3 修复:单边 true 保留 OR 结果。
const catsA = [container, makeCat('工作', 'normal', true, [
{ text: 'T', completed: false, important: false, current: false },
]), trash];
const catsB = [container, makeCat('工作', 'normal', true, [
{ text: 'T', completed: false, important: true, current: true },
]), trash];
const diff = diffCategories(catsA, catsB);
// 不传 resolutions空对象—— 验证 applyResolutions 内部的默认值
const merged = applyResolutions(catsA, diff, {});
const t = merged.find(c => c.name === '工作').tasks[0];
check('默认合并后 completed = OR(false, false) = false两边都没勾选',
t.completed === false,
`t=${JSON.stringify(t)}`);
check('默认合并后 important = OR(false, true) = true',
t.important === true);
check('默认合并后 current = OR(false, true) = trueH3 修复:单边 true 不再被吞)',
t.current === true,
`t.current=${t.current}, expected true`);
}
// ── [4] current 双边 true → 合并后强制 false仍是单值指针 ──
console.log('\n[4] applyResolutionscurrent 双边 true → 强制 false');
{
// 两侧都标了 [▶] —— 矛盾,强制 false 让用户手动重选。
// 必须有其他状态字段不同(这里用 important让两侧落到 modified 分支;
// 完全相同的两侧会被 tasksStateEqual 判 unchanged根本不走 mergeTaskStates。
const catsA = [container, makeCat('工作', 'normal', true, [
{ text: 'T', completed: false, important: false, current: true },
]), trash];
const catsB = [container, makeCat('工作', 'normal', true, [
{ text: 'T', completed: false, important: true, current: true },
]), trash];
const diff = diffCategories(catsA, catsB);
const merged = applyResolutions(catsA, diff, {});
const t = merged.find(c => c.name === '工作').tasks[0];
check('双边 current=true → 合并后 current=false',
t.current === false,
`t=${JSON.stringify(t)}`);
}
printSummary('check-conflict-default');