diff --git a/internal/server/copy_preflight_drop_reason_parity_test.go b/internal/server/copy_preflight_drop_reason_parity_test.go index 4d6f52772..9e3938e81 100644 --- a/internal/server/copy_preflight_drop_reason_parity_test.go +++ b/internal/server/copy_preflight_drop_reason_parity_test.go @@ -38,26 +38,35 @@ func readWebFile(t *testing.T, rel string) string { return string(b) } -// dropReasonSwitchBody returns just the body of CopyItemDialog's `dropReason` -// function. Scoped rather than searched whole: the component has other -// switches, and one of them matching `case 'not_found':` for an unrelated -// purpose would satisfy this test while the dialog still rendered the raw enum -// — a guard that passes on the wrong evidence. -func dropReasonSwitchBody(t *testing.T, src string) string { +// dropReasonMapBody returns the body of the renderer's message map. +// +// REPOINTED IN IDEA-2894, and the repointing is the reason this helper still +// earns its keep. The mapper moved out of CopyItemDialog.svelte into +// `web/src/lib/items/copyDropReasons.ts` so it could be unit-tested at all, +// and this gate FAILED LOUDLY on that move — exactly as the fatal below says +// it should — rather than passing on a file that no longer contained what it +// was reading for. A parity gate that cannot tell "no such reason" from "no +// such function" is worse than none. +// +// Scoped to the map's body rather than searching the file whole for the same +// reason the old version scoped to the switch: the module also exports the +// reason LIST, and a reason present there but missing a message would satisfy +// a whole-file search while the dialog still rendered the raw enum. +func dropReasonMapBody(t *testing.T, src string) string { t.Helper() - const marker = "function dropReason(reason: string): string {" + const marker = "const MESSAGES: Record = {" start := strings.Index(src, marker) if start < 0 { - t.Fatalf("CopyItemDialog.svelte no longer declares %q — this gate is reading for a "+ - "function that moved or was renamed, so its green means nothing until it is repointed", marker) + t.Fatalf("copyDropReasons.ts no longer declares %q — this gate is reading for a "+ + "declaration that moved or was renamed, so its green means nothing until it is "+ + "repointed", marker) } rest := src[start+len(marker):] - // The function's own closing brace: the first line that is exactly a tab - // followed by `}`, matching the component's indentation for a top-level - // declaration in