| 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; |
| 3 | |
| 4 | import { G1T_MENTION_HREF, rehypeReferences } from "./markdown-plugins.ts"; |
| 5 | |
| 6 | type Node = { type: string; value?: string; tagName?: string; properties?: Record<string, unknown>; children?: Node[] }; |
| 7 | |
| 8 | /** The links a paragraph of `text` gets: each one's href and text. */ |
| 9 | function links(text: string): [string, string][] { |
| 10 | const tree: Node = { type: "root", children: [{ type: "element", tagName: "p", properties: {}, children: [{ type: "text", value: text }] }] }; |
| 11 | rehypeReferences({ repo: { namespace: "acme", name: "web" } })(tree as never); |
| 12 | return (tree.children![0]!.children ?? []).filter((node) => node.tagName === "a").map((node) => [String(node.properties!.href), node.children![0]!.value!]); |
| 13 | } |
| 14 | |
| 15 | test("@name links to the person or workspace", () => { |
| 16 | assert.deepEqual(links("thanks @Ana."), [["/ana", "@Ana"]]); |
| 17 | assert.deepEqual(links("me@example.com"), []); |
| 18 | }); |
| 19 | |
| 20 | test("@g1t is g1t's agent, never the workspace alias at /g1t", () => { |
| 21 | assert.deepEqual(links("@g1t fix this, then ask @G1T again"), [ |
| 22 | [G1T_MENTION_HREF, "@g1t"], |
| 23 | [G1T_MENTION_HREF, "@G1T"], |
| 24 | ]); |
| 25 | assert.ok(!G1T_MENTION_HREF.startsWith("/")); |
| 26 | // Names that only start with g1t are anyone's. |
| 27 | assert.deepEqual(links("@g1t-fans"), [["/g1t-fans", "@g1t-fans"]]); |
| 28 | }); |
| 29 | |
| 30 | test("@workspace/team links to the team", () => { |
| 31 | assert.deepEqual(links("cc @acme/backend, @ana"), [ |
| 32 | ["/acme/-/teams/backend", "@acme/backend"], |
| 33 | ["/ana", "@ana"], |
| 34 | ]); |
| 35 | assert.deepEqual(links("(@Acme/Web-Platform)"), [["/acme/-/teams/web-platform", "@Acme/Web-Platform"]]); |
| 36 | }); |
| 37 | |
| 38 | /** The links a paragraph of `text` gets, read in `options`' repository or workspace. */ |
| 39 | function linksIn(text: string, options: { repo?: { namespace: string; name: string }; workspace?: string }): [string, string][] { |
| 40 | const tree: Node = { type: "root", children: [{ type: "element", tagName: "p", properties: {}, children: [{ type: "text", value: text }] }] }; |
| 41 | rehypeReferences(options)(tree as never); |
| 42 | return (tree.children![0]!.children ?? []).filter((node) => node.tagName === "a").map((node) => [String(node.properties!.href), node.children![0]!.value!]); |
| 43 | } |
| 44 | |
| 45 | test("#12 in a repository is read there, by the page that asks the work service", () => { |
| 46 | // Its pull request, the work item its issue became, the workspace's work |
| 47 | // item or another repository's pull request: lib/refs.ts says which page asks. |
| 48 | assert.deepEqual(links("see #12 and other/repo#3"), [ |
| 49 | ["/acme/web/ref/12", "#12"], |
| 50 | ["/other/repo/ref/3", "other/repo#3"], |
| 51 | ]); |
| 52 | }); |
| 53 | |
| 54 | test("#12 in a workspace's text is its work item, and workspace#12 is that workspace's", () => { |
| 55 | assert.deepEqual(linksIn("see #12, beta#4 and beta/api#7", { workspace: "acme" }), [ |
| 56 | ["/acme/-/work/12", "#12"], |
| 57 | ["/beta/-/work/4", "beta#4"], |
| 58 | ["/beta/api/ref/7", "beta/api#7"], |
| 59 | ]); |
| 60 | // A repository's text reads `workspace#12` in that workspace too. |
| 61 | assert.deepEqual(links("Part of acme#9"), [["/acme/-/work/9", "acme#9"]]); |
| 62 | }); |
| 63 | |
| 64 | test("#12 with nowhere to read it stays text, and so does a link's fragment", () => { |
| 65 | assert.deepEqual(linksIn("see #12", {}), []); |
| 66 | assert.deepEqual(linksIn("see /docs#12 and ##3", { workspace: "acme" }), []); |
| 67 | }); |