✅ Cover the discriminant-key popup

This commit is contained in:
tmu committed 2026-09-21 22:36:30 +00:00
1 parent 8ab3c6dbc6
commit 78e9af600d
1 file changed
+52
+52
View File
@@ -398,3 +398,55 @@ test("autocomplete: a fallback makes the remaining tags optional", () => {
assert.deepEqual([...result], ["a?", "b?", "c?"]); assert.deepEqual([...result], ["a?", "b?", "c?"]);
}); });
}); });
// `Mixed` has two common keys, but `id`'s value is not a tag, so only `kind`
// may serve as the discriminant.
const MIXED_SOURCE = `type Mixed = { id: Date; kind: "a"; a: number } | { id: Date; kind: "b"; b: number };`;
const discriminantLabelsFor = ({
name,
factory,
typeName,
typeSource,
}: {
readonly name: string;
readonly factory: "getTaggedUnionMatcher" | "getTaggedUnionMatcherW";
readonly typeName: string;
readonly typeSource: string;
}): Promise<readonly string[]> => {
const session = new LspSession(REPO_ROOT);
const target: CompletionTarget = {
file: `src/__autocomplete_${name}.ts`,
source: [
`import { ${factory} } from "./index.ts";`,
typeSource,
`const m = ${factory}<${typeName}>()(/*COMPLETE*/);`,
"",
].join("\n"),
};
return session
.completionLabelsAt(target)
.then((result) => result.labels)
.finally(() => session.close());
};
test("autocomplete: the discriminant key is offered at the key argument", () => {
// Arrange
const name = "tagged_union_discriminant";
// Act
const labels = discriminantLabelsFor({
name,
factory: "getTaggedUnionMatcher",
typeName: "Mixed",
typeSource: MIXED_SOURCE,
});
// Assert
return labels.then((result) => {
// The argument position also offers every global identifier, so assert
// inclusion of the discriminant and exclusion of the non-tag key.
assert.ok(result.includes('"kind"'));
assert.ok(!result.includes('"id"'));
});
});