Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

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