{"version":3,"file":"memory-compare-output.test.d.ts","sourceRoot":"","sources":["../../src/core/memory-compare-output.test.ts"],"names":[],"mappings":"","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport type { MemoryHistorySnapshot } from \"./memory.js\";\nimport { formatMemoryDiffOutput, formatMemoryHistoryOutput, formatRelativeAgeLabel } from \"./memory-compare-output.js\";\nimport { resolveSnapshotSelector } from \"./snapshot-selector-resolver.js\";\n\nfunction makeSnapshot(\n\tentryId: string,\n\titems: Array<{ key: string; value: string }>,\n\trecordedAt = \"2026-04-01T12:00:00.000Z\",\n\tisCurrent = false,\n): MemoryHistorySnapshot {\n\treturn {\n\t\tentryId,\n\t\tparentId: null,\n\t\trecordedAt,\n\t\titems: items.map((item) => ({ ...item, timestamp: recordedAt })),\n\t\tisCurrent,\n\t};\n}\n\ndescribe(\"memory compare output\", () => {\n\tit(\"formats history output with shared selector guidance and bracketed IDs\", () => {\n\t\tconst snapshots = [\n\t\t\tmakeSnapshot(\"baseline01-1111\", [{ key: \"alpha\", value: \"first value\" }], \"2026-04-01T10:00:00.000Z\"),\n\t\t\tmakeSnapshot(\"target001-2222\", [{ key: \"beta\", value: \"second value\" }], \"2026-04-01T12:00:00.000Z\", true),\n\t\t];\n\n\t\tconst lines = formatMemoryHistoryOutput(snapshots, {\n\t\t\tgetRelativeAgeLabel: () => \"2h ago\",\n\t\t});\n\n\t\texpect(lines).toContain(\"Use /memory diff <baselineId> <targetId> to compare any two snapshots.\");\n\t\texpect(lines).toContain(\"Accepted: full entryId, 8-char short ID, or strict unique prefix.\");\n\t\texpect(lines).toContain(\"2h ago [current] · 1 item · 4/1/2026, 12:00:00 PM · [target00]\");\n\t});\n\n\tit(\"formats explicit diff output with shared resolved-ID header\", () => {\n\t\tconst snapshots = [\n\t\t\tmakeSnapshot(\"baseline01-1111\", [{ key: \"alpha\", value: \"first\" }], \"2026-04-01T10:00:00.000Z\"),\n\t\t\tmakeSnapshot(\"target001-2222\", [{ key: \"alpha\", value: \"second\" }], \"2026-04-01T12:00:00.000Z\", true),\n\t\t];\n\n\t\tconst lines = formatMemoryDiffOutput(\n\t\t\tsnapshots,\n\t\t\t{\n\t\t\t\tgetRelativeAgeLabel: () => \"2h ago\",\n\t\t\t\tresolveSnapshotSelector: (input) => resolveSnapshotSelector(input, snapshots),\n\t\t\t},\n\t\t\t{ baseline: \"[baseline]\", target: \"[target00]\" },\n\t\t);\n\n\t\texpect(lines.slice(0, 5)).toEqual([\n\t\t\t\"Baseline: 2h ago — 4/1/2026, 10:00:00 AM\",\n\t\t\t\"        ID: [baseline] baseline01-1111\",\n\t\t\t\"Target:   2h ago — 4/1/2026, 12:00:00 PM\",\n\t\t\t\"        ID: [target00] target001-2222\",\n\t\t\t\"(snapshot comparison · not an event log)\",\n\t\t]);\n\t\texpect(lines).toContain(\"~ Changed (1)\");\n\t\texpect(lines).toContain(\"  ~ alpha:\");\n\t});\n\n\tit(\"formats selector resolution failures via the shared formatter path\", () => {\n\t\tconst snapshots = [\n\t\t\tmakeSnapshot(\"baseline01-1111\", [{ key: \"alpha\", value: \"first\" }], \"2026-04-01T10:00:00.000Z\", true),\n\t\t];\n\n\t\tconst lines = formatMemoryDiffOutput(\n\t\t\tsnapshots,\n\t\t\t{\n\t\t\t\tgetRelativeAgeLabel: () => \"2h ago\",\n\t\t\t\tresolveSnapshotSelector: (input) => resolveSnapshotSelector(input, snapshots),\n\t\t\t},\n\t\t\t{ baseline: \"[]\", target: \"missing\" },\n\t\t);\n\n\t\texpect(lines).toEqual([\n\t\t\t\"Snapshot resolution failed in current branch history.\",\n\t\t\t\"\",\n\t\t\t\"Baseline selector is empty.\",\n\t\t\t\"Target ID not found: missing\",\n\t\t\t\"\",\n\t\t\t\"Run /memory history to see available snapshot IDs (shown in brackets after each age label).\",\n\t\t\t\"Accepted forms: full entryId, short ID (8 chars), or strict unique prefix. Brackets are optional.\",\n\t\t]);\n\t});\n\n\tit(\"formats same-snapshot comparisons honestly\", () => {\n\t\tconst snapshots = [\n\t\t\tmakeSnapshot(\"baseline01-1111\", [{ key: \"alpha\", value: \"first\" }], \"2026-04-01T10:00:00.000Z\", true),\n\t\t];\n\n\t\tconst lines = formatMemoryDiffOutput(\n\t\t\tsnapshots,\n\t\t\t{\n\t\t\t\tgetRelativeAgeLabel: () => \"2h ago\",\n\t\t\t\tresolveSnapshotSelector: (input) => resolveSnapshotSelector(input, snapshots),\n\t\t\t},\n\t\t\t{ baseline: \"baseline01-1111\", target: \"[baseline]\" },\n\t\t);\n\n\t\texpect(lines.at(-1)).toBe(\"Baseline and target are the same snapshot — no changes to show.\");\n\t});\n\n\tit(\"formats adjacent initial snapshots honestly\", () => {\n\t\tconst lines = formatMemoryDiffOutput(\n\t\t\t[makeSnapshot(\"baseline01-1111\", [{ key: \"alpha\", value: \"first\" }], \"2026-04-01T10:00:00.000Z\", true)],\n\t\t\t{\n\t\t\t\tgetRelativeAgeLabel: () => \"2h ago\",\n\t\t\t\tresolveSnapshotSelector: () => {\n\t\t\t\t\tthrow new Error(\"not used\");\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\texpect(lines).toEqual([\n\t\t\t\"Initial snapshot — 1 item(s)\",\n\t\t\t\"\",\n\t\t\t\"Recorded: 4/1/2026, 10:00:00 AM\",\n\t\t\t\"(snapshot comparison · not an event log)\",\n\t\t]);\n\t});\n\n\tit(\"formats relative age labels deterministically around thresholds\", () => {\n\t\tconst originalNow = Date.now;\n\t\tDate.now = () => new Date(\"2026-04-01T12:00:00.000Z\").getTime();\n\t\ttry {\n\t\t\texpect(formatRelativeAgeLabel(new Date(\"2026-04-01T11:59:45.000Z\"))).toBe(\"just now\");\n\t\t\texpect(formatRelativeAgeLabel(new Date(\"2026-04-01T11:58:00.000Z\"))).toBe(\"2m ago\");\n\t\t\texpect(formatRelativeAgeLabel(new Date(\"2026-03-31T12:00:00.000Z\"))).toBe(\"1d ago\");\n\t\t} finally {\n\t\t\tDate.now = originalNow;\n\t\t}\n\t});\n});\n"]}