Files
kandev/apps/web/lib/entity-references/message-references.test.ts
T
José Almeida 7de788ceed feat: add cross-integration entity references (#1862)
* feat: add cross-integration entity references

* fix(web): anchor entity reference menu to composer

* fix: keep Kandev tasks under @ mentions

* fix: address entity reference review findings

* test(e2e): use option role for prompt menu

* test(e2e): update passthrough mention roles

* fix: preserve queued references and paginate Azure PRs
2026-07-23 09:03:56 +01:00

131 lines
3.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { EntityReference } from "@/lib/types/entity-reference";
import {
entityReferenceMarkdown,
entityReferencesFromMetadata,
matchEntityReferenceLink,
survivingEntityReferences,
} from "./message-references";
function taskReference(overrides: Partial<EntityReference> = {}): EntityReference {
return {
version: 1,
ref: "mention:v1:kandev:task:workspace-1:task-1",
provider: "kandev",
kind: "task",
id: "task-1",
key: "KAN-1",
title: "Fix authentication",
url: "/t/task-1",
scope: "workspace-1",
...overrides,
};
}
function issueReference(overrides: Partial<EntityReference> = {}): EntityReference {
return {
version: 1,
ref: "mention:v1:jira:issue:https%3A%2F%2Fjira.example:10001",
provider: "jira",
kind: "issue",
id: "10001",
key: "ENG[1]",
title: "Fix the login flow",
url: "https://jira.example/browse/ENG-1?q=hello world(test)",
scope: "https://jira.example",
...overrides,
};
}
describe("entityReferencesFromMetadata", () => {
it("runtime-validates v1 references and deduplicates ref in first-valid order", () => {
const first = taskReference();
const second = issueReference();
const metadata = {
entity_references: [
{ ...first, version: 2 },
{ ...first, url: "javascript:alert(1)" },
first,
{ ...first, title: "Conflicting duplicate" },
second,
],
};
expect(entityReferencesFromMetadata(metadata)).toEqual([first, second]);
});
it("rejects malformed metadata containers and noncanonical identities", () => {
expect(entityReferencesFromMetadata({ entity_references: "not-an-array" })).toEqual([]);
expect(
entityReferencesFromMetadata({
entity_references: [taskReference({ ref: "made-up", title: "" })],
}),
).toEqual([]);
});
});
describe("entity reference Markdown matching", () => {
it("matches only the exact generated label and encoded URL", () => {
const reference = issueReference();
expect(entityReferenceMarkdown(reference)).toBe(
"[#ENG\\[1\\]](https://jira.example/browse/ENG-1?q=hello%20world%28test%29)",
);
expect(
matchEntityReferenceLink([reference], "#ENG[1]", reference.url.replaceAll(" ", "%20")),
).toBeNull();
expect(
matchEntityReferenceLink(
[reference],
"#ENG[1]",
"https://jira.example/browse/ENG-1?q=hello%20world%28test%29",
),
).toEqual(reference);
expect(
matchEntityReferenceLink(
[reference],
"#Wrong",
"https://jira.example/browse/ENG-1?q=hello%20world%28test%29",
),
).toBeNull();
expect(
matchEntityReferenceLink([reference], "#ENG[1]", "https://evil.example/ENG-1"),
).toBeNull();
});
});
describe("survivingEntityReferences", () => {
it("returns exact generated links in document order and deduplicates repeats", () => {
const task = taskReference();
const issue = issueReference();
const taskMarkdown = entityReferenceMarkdown(task);
const issueMarkdown = entityReferenceMarkdown(issue);
const content = [
issueMarkdown,
"[wrong label](/t/task-1)",
taskMarkdown,
issueMarkdown,
"[#KAN-1](https://evil.example/task-1)",
].join(" then ");
expect(survivingEntityReferences(content, [task, issue])).toEqual([issue, task]);
});
it("returns an empty replacement when no generated links survive", () => {
expect(survivingEntityReferences("plain edited text", [taskReference()])).toEqual([]);
});
it("ignores generated-link text that Markdown treats as literal code or escaped text", () => {
const reference = taskReference();
const markdown = entityReferenceMarkdown(reference);
const content = [
`\\${markdown}`,
`\`${markdown}\``,
`\`\`\`md\n${markdown}\n\`\`\``,
`!${markdown}`,
].join("\n");
expect(survivingEntityReferences(content, [reference])).toEqual([]);
});
});