返回 DeepSeek-Reasonix
github-link-rendering.test.tsx
根目录 / desktop / frontend / src / __tests__ / github-link-rendering.test.tsx
1 // Run: tsx src/__tests__/github-link-rendering.test.tsx
2
3 import { readFileSync } from "node:fs";
4 import { fileURLToPath } from "node:url";
5 import { JSDOM } from "jsdom";
6 import { createElement } from "react";
7 import { renderToStaticMarkup } from "react-dom/server";
8 import { classifyLinkIcon, parseGitHubLink } from "../components/githubLink";
9 import { RichMarkdownLink } from "../components/githubLink";
10
11 let passed = 0;
12 let failed = 0;
13
14 function ok(value: unknown, label: string) {
15 eq(Boolean(value), true, label);
16 }
17
18 function eq(actual: unknown, expected: unknown, label: string) {
19 if (JSON.stringify(actual) === JSON.stringify(expected)) {
20 process.stdout.write(` PASS ${label}\n`);
21 passed += 1;
22 } else {
23 process.stdout.write(
24 ` FAIL ${label}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}\n`,
25 );
26 failed += 1;
27 }
28 }
29
30 console.log("\ngithub link rendering");
31
32 eq(parseGitHubLink("https://github.com/esengine/DeepSeek-Reasonix/issues/6856"), {
33 kind: "issue",
34 owner: "esengine",
35 repo: "DeepSeek-Reasonix",
36 value: "6856",
37 compactLabel: "#6856",
38 }, "recognizes GitHub issue links");
39
40 eq(parseGitHubLink("https://github.com/esengine/DeepSeek-Reasonix/pull/123?diff=split"), {
41 kind: "pull",
42 owner: "esengine",
43 repo: "DeepSeek-Reasonix",
44 value: "123",
45 compactLabel: "PR #123",
46 }, "recognizes GitHub pull request links with query parameters");
47
48 eq(parseGitHubLink("https://github.com/esengine/DeepSeek-Reasonix/commit/abcdef1234567890"), {
49 kind: "commit",
50 owner: "esengine",
51 repo: "DeepSeek-Reasonix",
52 value: "abcdef1234567890",
53 compactLabel: "abcdef1",
54 }, "recognizes GitHub commit links");
55
56 eq(parseGitHubLink("https://github.com/esengine/DeepSeek-Reasonix"), null, "leaves repository links unchanged");
57 eq(parseGitHubLink("http://github.com/esengine/DeepSeek-Reasonix/issues/1"), null, "rejects insecure GitHub links");
58 eq(parseGitHubLink("https://example.com/issues/6856"), null, "leaves non-GitHub links unchanged");
59 eq(parseGitHubLink("javascript:alert(1)"), null, "does not enhance unsafe links");
60
61 eq(classifyLinkIcon("https://github.com/esengine/DeepSeek-Reasonix"), "github", "adds a GitHub icon to repository links");
62 eq(classifyLinkIcon("https://example.com/docs"), "external", "adds an external-link icon to web links");
63 eq(classifyLinkIcon("http://localhost:5173/docs"), "external", "adds an external-link icon to HTTP links");
64 eq(classifyLinkIcon("mailto:hello@example.com"), "mail", "adds a mail icon to email links");
65 eq(classifyLinkIcon("./docs/GUIDE.md"), null, "leaves relative links without an icon");
66 eq(classifyLinkIcon("#section"), null, "leaves page fragments without an icon");
67 eq(classifyLinkIcon("javascript:alert(1)"), null, "does not add icons to unsafe protocols");
68
69 function renderLink(href: string, label: string = href) {
70 const markup = renderToStaticMarkup(
71 createElement(RichMarkdownLink, { href, children: label }),
72 );
73 return new JSDOM(markup).window.document.querySelector("a");
74 }
75
76 {
77 const href = "https://github.com/esengine/DeepSeek-Reasonix/pull/6976";
78 const link = renderLink(href);
79 const label = link?.querySelector(".md-rich-link__label");
80 eq(label?.textContent, href, "keeps the original GitHub URL in selectable DOM text");
81 eq(label?.getAttribute("data-display-label"), "PR #6976", "exposes the compact visual PR label");
82 eq(
83 link?.getAttribute("aria-label"),
84 "GitHub esengine/DeepSeek-Reasonix pull request #6976",
85 "gives compact PR links a contextual accessible name",
86 );
87 ok(link?.querySelector("svg[aria-hidden=\"true\"]"), "hides the decorative GitHub icon from assistive technology");
88
89 const selection = link?.ownerDocument.defaultView?.getSelection();
90 const range = link?.ownerDocument.createRange();
91 if (link && selection && range) {
92 range.selectNodeContents(link);
93 selection.removeAllRanges();
94 selection.addRange(range);
95 }
96 eq(selection?.toString(), href, "copies the original URL instead of the compact visual label");
97 }
98
99 {
100 const link = renderLink(
101 "https://github.com/esengine/DeepSeek-Reasonix/issues/6856",
102 "Readable issue title",
103 );
104 eq(link?.textContent, "Readable issue title", "preserves an explicit Markdown link label");
105 eq(
106 link?.querySelector(".md-rich-link__label")?.hasAttribute("data-display-label"),
107 false,
108 "does not compact explicit Markdown link labels",
109 );
110 eq(link?.hasAttribute("aria-label"), false, "does not override an explicit accessible link label");
111 }
112
113 {
114 const link = renderLink("https://example.com/a/very/long/documentation/path");
115 ok(link?.classList.contains("md-rich-link--external"), "renders ordinary HTTPS destinations as rich external links");
116 ok(link?.querySelector("svg[aria-hidden=\"true\"]"), "renders a decorative external-link icon");
117 }
118
119 {
120 const relative = renderLink("./docs/GUIDE.md", "Guide");
121 eq(relative?.className, "", "leaves relative links without rich-link styling");
122 eq(relative?.querySelector("svg"), null, "leaves relative links without an icon");
123 }
124
125 {
126 const styles = readFileSync(fileURLToPath(new URL("../styles.css", import.meta.url)), "utf8");
127 ok(
128 /\.md \.md-rich-link\s*\{[^}]*white-space:\s*normal;/.test(styles),
129 "allows rich links to wrap on narrow layouts",
130 );
131 ok(
132 /\.md \.md-rich-link__label\s*\{[^}]*min-width:\s*0;[^}]*overflow-wrap:\s*anywhere;/.test(styles),
133 "lets long unbroken link labels shrink and wrap",
134 );
135 }
136
137 console.log(`\n${passed} passed, ${failed} failed, ${passed + failed} total`);
138 if (failed > 0) process.exit(1);
139
139 lines Plain Text