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); }); });