{"version":3,"file":"snapshot-selector-formatter.test.d.ts","sourceRoot":"","sources":["../../src/core/snapshot-selector-formatter.test.ts"],"names":[],"mappings":"","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport type { MemoryHistorySnapshot } from \"./memory.js\";\nimport {\n\tformatAdjacentDiffHeader,\n\tformatExplicitDiffHeader,\n\tformatResolvedSnapshotId,\n\tformatSnapshotSelectorAcceptedForms,\n\tformatSnapshotSelectorHistoryGuidance,\n\tformatSnapshotSelectorIssues,\n\tformatSnapshotSelectorResolutionFailure,\n\tformatSnapshotShortId,\n} from \"./snapshot-selector-formatter.js\";\nimport type { SnapshotResolution } from \"./snapshot-selector-resolver.js\";\nimport { MEMORY_SNAPSHOT_SHORT_ID_LENGTH } from \"./snapshot-selector-resolver.js\";\n\nfunction makeSnapshot(entryId: string, recordedAt = \"2026-04-01T00:00:00.000Z\"): MemoryHistorySnapshot {\n\treturn {\n\t\tentryId,\n\t\tparentId: null,\n\t\trecordedAt,\n\t\titems: [],\n\t\tisCurrent: false,\n\t};\n}\n\nfunction makeResolution(overrides: Partial<SnapshotResolution>): SnapshotResolution {\n\treturn {\n\t\tsnapshot: undefined,\n\t\tmatchedInput: \"\",\n\t\tresolvedId: undefined,\n\t\terror: undefined,\n\t\tcandidates: [],\n\t\t...overrides,\n\t};\n}\n\ndescribe(\"snapshot selector formatter\", () => {\n\tit(\"formats empty selector issues\", () => {\n\t\tconst lines = formatSnapshotSelectorIssues([\n\t\t\t{ label: \"Baseline\", resolution: makeResolution({ error: \"empty\" }) },\n\t\t]);\n\n\t\texpect(lines).toEqual([\"Baseline selector is empty.\"]);\n\t});\n\n\tit(\"formats not-found selector issues\", () => {\n\t\tconst lines = formatSnapshotSelectorIssues([\n\t\t\t{ label: \"Target\", resolution: makeResolution({ error: \"not_found\", matchedInput: \"abc12345\" }) },\n\t\t]);\n\n\t\texpect(lines).toEqual([\"Target ID not found: abc12345\"]);\n\t});\n\n\tit(\"formats ambiguous selector issues with candidate IDs\", () => {\n\t\tconst lines = formatSnapshotSelectorIssues([\n\t\t\t{\n\t\t\t\tlabel: \"Baseline\",\n\t\t\t\tresolution: makeResolution({\n\t\t\t\t\terror: \"ambiguous\",\n\t\t\t\t\tmatchedInput: \"abc\",\n\t\t\t\t\tcandidates: [\"abc00001-1111\", \"abc00002-2222\"],\n\t\t\t\t}),\n\t\t\t},\n\t\t]);\n\n\t\texpect(lines).toEqual([\n\t\t\t\"Baseline ID is ambiguous: abc\",\n\t\t\t\"  [abc00001] abc00001-1111\",\n\t\t\t\"  [abc00002] abc00002-2222\",\n\t\t]);\n\t});\n\n\tit(\"combines failure header, issue details, and accepted forms guidance\", () => {\n\t\tconst lines = formatSnapshotSelectorResolutionFailure([\n\t\t\t{ label: \"Baseline\", resolution: makeResolution({ error: \"empty\" }) },\n\t\t\t{ label: \"Target\", resolution: makeResolution({ error: \"not_found\", matchedInput: \"deadbeef\" }) },\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: deadbeef\",\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\tformatSnapshotSelectorAcceptedForms(),\n\t\t]);\n\t});\n\n\tit(\"returns empty failure output when no issues are present\", () => {\n\t\texpect(\n\t\t\tformatSnapshotSelectorResolutionFailure([\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Baseline\",\n\t\t\t\t\tresolution: makeResolution({ snapshot: makeSnapshot(\"abc12345-1111\"), resolvedId: \"abc12345-1111\" }),\n\t\t\t\t},\n\t\t\t]),\n\t\t).toEqual([]);\n\t});\n\n\tit(\"formats history guidance lines deterministically\", () => {\n\t\texpect(formatSnapshotSelectorHistoryGuidance()).toEqual([\n\t\t\t\"Use /memory diff <baselineId> <targetId> to compare any two snapshots.\",\n\t\t\t\"IDs shown in brackets ([xxxxxxxx]) can be copied directly; brackets are optional.\",\n\t\t\t\"Accepted: full entryId, 8-char short ID, or strict unique prefix.\",\n\t\t]);\n\t});\n\n\tit(\"formats short IDs and resolved IDs\", () => {\n\t\texpect(formatSnapshotShortId(\"abc12345-1111\")).toBe(\"[abc12345]\");\n\t\texpect(formatResolvedSnapshotId(\"abc12345-1111\")).toBe(\"[abc12345] abc12345-1111\");\n\t});\n\n\tit(\"formats explicit diff header with resolved IDs\", () => {\n\t\tconst lines = formatExplicitDiffHeader({\n\t\t\tbaselineSnapshot: makeSnapshot(\"baseline01-1111\", \"2026-04-01T10:00:00.000Z\"),\n\t\t\ttargetSnapshot: makeSnapshot(\"target001-2222\", \"2026-04-01T12:00:00.000Z\"),\n\t\t\tgetRelativeAgeLabel: () => \"2h ago\",\n\t\t});\n\n\t\texpect(lines).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\t\"\",\n\t\t]);\n\t});\n\n\tit(\"formats adjacent diff header\", () => {\n\t\tconst lines = formatAdjacentDiffHeader({\n\t\t\tbaselineSnapshot: makeSnapshot(\"baseline01-1111\", \"2026-04-01T10:00:00.000Z\"),\n\t\t\ttargetSnapshot: makeSnapshot(\"target001-2222\", \"2026-04-01T12:00:00.000Z\"),\n\t\t\tgetRelativeAgeLabel: () => \"2h ago\",\n\t\t});\n\n\t\texpect(lines).toEqual([\n\t\t\t\"Comparing: 2h ago → 2h ago\",\n\t\t\t\"4/1/2026, 10:00:00 AM → 4/1/2026, 12:00:00 PM\",\n\t\t\t\"(snapshot comparison · not an event log)\",\n\t\t\t\"\",\n\t\t]);\n\t});\n\n\tit(\"respects custom short ID length where applicable\", () => {\n\t\texpect(formatSnapshotShortId(\"abc12345-1111\", 4)).toBe(\"[abc1]\");\n\t\texpect(formatResolvedSnapshotId(\"abc12345-1111\", 4)).toBe(\"[abc1] abc12345-1111\");\n\t\texpect(formatSnapshotSelectorAcceptedForms(6)).toContain(\"6 chars\");\n\t\texpect(formatSnapshotSelectorHistoryGuidance(6)[1]).toBe(\n\t\t\t\"IDs shown in brackets ([xxxxxx]) can be copied directly; brackets are optional.\",\n\t\t);\n\t\texpect(MEMORY_SNAPSHOT_SHORT_ID_LENGTH).toBe(8);\n\t});\n});\n"]}