| 1 | import { describe, expect, it } from "vite-plus/test"; |
| 2 | import type { ComposerContextId, ReviewCommentContextRecord } from "@t3tools/contracts"; |
| 3 | import { |
| 4 | enrichedContextLinkPresentation, |
| 5 | enrichedLinkVariantPattern, |
| 6 | enrichedSkillLinkRegex, |
| 7 | enrichedSkillReference, |
| 8 | ENRICHED_INLINE_FILE_LINK_REGEX, |
| 9 | } from "./enrichedLinkPresentation"; |
| 10 | |
| 11 | describe("Enriched link presentation", () => { |
| 12 | it("recognizes file-shaped code without turning commands or URLs into links", () => { |
| 13 | for (const path of [ |
| 14 | "src/app.tsx", |
| 15 | "./README.md", |
| 16 | "/tmp/report.md", |
| 17 | "C:\\repo\\app.tsx", |
| 18 | "app.tsx:12:3", |
| 19 | ]) { |
| 20 | expect(ENRICHED_INLINE_FILE_LINK_REGEX.test(path), path).toBe(true); |
| 21 | } |
| 22 | for (const text of [ |
| 23 | "npm run dev", |
| 24 | "port:3000", |
| 25 | "TODO:12", |
| 26 | "example.com", |
| 27 | "https://example.com/app.tsx", |
| 28 | "x + y", |
| 29 | "README.md", |
| 30 | "/app/settings", |
| 31 | ]) { |
| 32 | expect(ENRICHED_INLINE_FILE_LINK_REGEX.test(text), text).toBe(false); |
| 33 | } |
| 34 | }); |
| 35 | |
| 36 | it("only recognizes complete known skill names and escapes their punctuation", () => { |
| 37 | const regex = enrichedSkillLinkRegex([{ name: "check" }, { name: "check.mobile" }]); |
| 38 | expect(regex?.exec("Try $check.mobile next")?.[0]).toBe("$check.mobile"); |
| 39 | expect(regex?.exec("Try $check-mobile next")).toBeNull(); |
| 40 | expect(regex?.exec("Try $checkXmobile next")).toBeNull(); |
| 41 | expect(regex?.exec("prefix$check next")).toBeNull(); |
| 42 | expect(enrichedSkillLinkRegex([])).toBeNull(); |
| 43 | }); |
| 44 | it.each(["$", "€", "£", "¥", "₹", "₩", "₿", "𑿝"])( |
| 45 | "recognizes and presents known skills with %s while rejecting adjacent tokens", |
| 46 | (sigil) => { |
| 47 | const skills = [{ name: "check", displayName: "Check" }]; |
| 48 | const regex = enrichedSkillLinkRegex(skills)!; |
| 49 | expect(regex.exec(`Try ${sigil}check now`)?.[0]).toBe(`${sigil}check`); |
| 50 | expect(enrichedSkillReference(`${sigil}check`, skills)).toBe(skills[0]); |
| 51 | expect(regex.test(`prefix${sigil}check`)).toBe(false); |
| 52 | expect(regex.test(`${sigil}check-extra`)).toBe(false); |
| 53 | expect(regex.test(`${sigil}unknown`)).toBe(false); |
| 54 | expect(regex.test(`${sigil}${sigil}check`)).toBe(false); |
| 55 | }, |
| 56 | ); |
| 57 | it("matches only the complete URL, including literal regex metacharacters", () => { |
| 58 | const url = "file:///workspace/app[1].tsx?line=3+4"; |
| 59 | const pattern = new RegExp(enrichedLinkVariantPattern(url)); |
| 60 | expect(pattern.test(url)).toBe(true); |
| 61 | expect(pattern.test(`${url}/child`)).toBe(false); |
| 62 | expect(pattern.test("file:///workspace/app1Xtsx?line=34")).toBe(false); |
| 63 | }); |
| 64 | |
| 65 | it("uses context identity for PR status even when labels are identical", () => { |
| 66 | const record: ReviewCommentContextRecord = { |
| 67 | version: 1, |
| 68 | contextId: "review_1" as ComposerContextId, |
| 69 | kind: "review-comment", |
| 70 | label: "Review", |
| 71 | sectionId: "pull-request:7", |
| 72 | sectionTitle: "Review", |
| 73 | filePath: "app.tsx", |
| 74 | startIndex: 0, |
| 75 | endIndex: 1, |
| 76 | rangeLabel: "line 1", |
| 77 | text: "Comment", |
| 78 | diff: "", |
| 79 | pullRequest: { |
| 80 | number: 7, |
| 81 | title: "Review", |
| 82 | url: "https://github.com/example/repo/pull/7", |
| 83 | headBranch: "feature", |
| 84 | baseBranch: "main", |
| 85 | state: "merged", |
| 86 | isDraft: false, |
| 87 | }, |
| 88 | }; |
| 89 | expect( |
| 90 | enrichedContextLinkPresentation("t3-context://v1/review-comment/review_1", [record]), |
| 91 | ).toEqual({ color: "#8a70dd", icon: "git" }); |
| 92 | expect( |
| 93 | enrichedContextLinkPresentation("t3-context://v1/review-comment/review_2", [record]), |
| 94 | ).toEqual({ color: "#8a70dd", icon: "markdown" }); |
| 95 | }); |
| 96 | |
| 97 | it("retains recognizable presentation for unavailable and future context kinds", () => { |
| 98 | expect(enrichedContextLinkPresentation("t3-context://v1/terminal/missing")).toEqual({ |
| 99 | color: "#009f6e", |
| 100 | icon: "bash", |
| 101 | }); |
| 102 | expect(enrichedContextLinkPresentation("t3-context://v1/skill/missing")).toEqual({ |
| 103 | color: "#b261be", |
| 104 | icon: "mcp", |
| 105 | }); |
| 106 | expect(enrichedContextLinkPresentation("t3-context://v1/future/missing")).toEqual({ |
| 107 | color: "#0090cd", |
| 108 | icon: "default", |
| 109 | }); |
| 110 | expect(enrichedContextLinkPresentation("https://example.com/terminal/missing")).toBeUndefined(); |
| 111 | }); |
| 112 | }); |