shoc-frontend-new/src/test/domain/work-orders/utils/comment-mentions.test.ts

119 lines
3.7 KiB
TypeScript
Raw Normal View History

import { describe, expect, it } from "vitest";
import {
buildCommentBodySegments,
encodeMentionToken,
extractMentionIds,
filterMentionCandidates,
findActiveMentionQuery,
insertMentionToken,
toDisplayText,
} from "@/domain/work-orders/utils/comment-mentions";
describe("comment-mentions", () => {
it("encodes and extracts mention ids from tokens", () => {
const token = encodeMentionToken("user-1", "Jane Doe");
const text = `Please review ${token} today`;
expect(text).toBe("Please review @[user-1:Jane Doe] today");
expect(extractMentionIds(text)).toEqual(["user-1"]);
expect(toDisplayText(text)).toBe("Please review @Jane Doe today");
});
it("builds highlight segments from encoded tokens", () => {
const text = `Hi ${encodeMentionToken("42", "Alex Smith")}!`;
expect(buildCommentBodySegments(text)).toEqual([
{ type: "text", value: "Hi " },
{ type: "mention", userId: "42", label: "Alex Smith" },
{ type: "text", value: "!" },
]);
});
it("highlights plain @names when response mentions are provided", () => {
const text = "Ping @Jane Doe about this";
expect(
buildCommentBodySegments(text, ["user-1"], [{ id: "user-1", name: "Jane Doe" }]),
).toEqual([
{ type: "text", value: "Ping " },
{ type: "mention", userId: "Jane Doe", label: "Jane Doe" },
{ type: "text", value: " about this" },
]);
});
it("does not highlight casual @names from the full user roster without mentions", () => {
const text = "See @Jane Doe later";
expect(buildCommentBodySegments(text, undefined, [{ id: "user-1", name: "Jane Doe" }])).toEqual(
[{ type: "text", value: "See @Jane Doe later" }],
);
});
it("highlights plain @names before encoded tokens when mentioned", () => {
const encoded = encodeMentionToken("2", "Bob");
const text = `Hi @Jane Doe and ${encoded}`;
expect(
buildCommentBodySegments(
text,
["user-1", "2"],
[
{ id: "user-1", name: "Jane Doe" },
{ id: "2", name: "Bob" },
],
),
).toEqual([
{ type: "text", value: "Hi " },
{ type: "mention", userId: "Jane Doe", label: "Jane Doe" },
{ type: "text", value: " and " },
{ type: "mention", userId: "2", label: "Bob" },
]);
});
it("does not highlight shorter mention names as prefixes of longer @words", () => {
const text = "Check @Annual maintenance with @Ann";
expect(buildCommentBodySegments(text, ["user-ann"], [{ id: "user-ann", name: "Ann" }])).toEqual(
[
{ type: "text", value: "Check @Annual maintenance with " },
{ type: "mention", userId: "Ann", label: "Ann" },
],
);
});
it("finds active mention query at cursor", () => {
const text = "Hello @ja";
const query = findActiveMentionQuery(text, text.length);
expect(query).toEqual({ start: 6, query: "ja" });
expect(findActiveMentionQuery("email@test.com", 13)).toBeNull();
});
it("filters mention candidates by query", () => {
const candidates = [
{ id: "1", name: "Jane Doe" },
{ id: "2", name: "John Smith" },
];
expect(filterMentionCandidates(candidates, "jo")).toEqual([{ id: "2", name: "John Smith" }]);
});
it("inserts encoded mention token replacing active query", () => {
const text = "Hello @ja";
const activeQuery = findActiveMentionQuery(text, text.length);
expect(activeQuery).not.toBeNull();
if (!activeQuery) {
return;
}
const { nextText, nextCursor } = insertMentionToken(text, activeQuery.start, text.length, {
id: "1",
name: "Jane Doe",
});
expect(nextText).toBe("Hello @[1:Jane Doe] ");
expect(nextCursor).toBe(nextText.length);
});
});