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.

68 linesCodeBlameRaw
1import { test } from "node:test";
2import assert from "node:assert/strict";
3
4import { cleanLinks, cleanUrl, projectLinks, storedLinks } from "./links.ts";
5
6test("an address is http or https, with https added when none is given", () => {
7 assert.deepEqual(cleanUrl(" g1t.sh "), { ok: true, value: "https://g1t.sh" });
8 assert.deepEqual(cleanUrl("HTTP://docs.example.com/guide?x=1#a"), { ok: true, value: "http://docs.example.com/guide?x=1#a" });
9 assert.deepEqual(cleanUrl("example.com:8080/app"), { ok: true, value: "https://example.com:8080/app" });
10 assert.deepEqual(cleanUrl(""), { ok: true, value: null });
11 assert.deepEqual(cleanUrl(null), { ok: true, value: null });
12});
13
14test("anything else is refused, naming what it is", () => {
15 for (const bad of [
16 "javascript:alert(1)",
17 "mailto:a@example.com",
18 "ftp://example.com",
19 "localhost:3000",
20 "https://",
21 "https://exa mple.com",
22 "https://user@example.com",
23 "https://.com",
24 ]) {
25 assert.equal(cleanUrl(bad).ok, false, bad);
26 }
27 assert.deepEqual(cleanUrl("ftp://x.io", "The homepage"), { ok: false, message: "The homepage is an http or https address." });
28 assert.equal(cleanUrl(`https://example.com/${"a".repeat(260)}`).ok, false);
29});
30
31test("links: blank rows dropped, labels from the host, at most ten", () => {
32 assert.deepEqual(
33 cleanLinks([
34 { label: " Status ", url: "status.example.com" },
35 { label: "", url: "" },
36 { label: "", url: "https://npmjs.com/package/x" },
37 ]),
38 {
39 ok: true,
40 value: [
41 { label: "Status", url: "https://status.example.com" },
42 { label: "npmjs.com", url: "https://npmjs.com/package/x" },
43 ],
44 },
45 );
46 assert.deepEqual(cleanLinks([{ label: "Chat", url: "" }]), { ok: false, message: "Give Chat an address." });
47 assert.deepEqual(cleanLinks([{ label: "Chat", url: "irc://x.io" }]), { ok: false, message: "The address for Chat is an http or https address." });
48 assert.equal(cleanLinks([{ label: "x".repeat(41), url: "x.io" }]).ok, false);
49 const eleven = Array.from({ length: 11 }, (_, i) => ({ label: `L${i}`, url: `l${i}.io` }));
50 assert.equal(cleanLinks(eleven).ok, false);
51 assert.equal(cleanLinks(eleven.slice(0, 10)).ok, true);
52 assert.equal(cleanLinks("nope").ok, false);
53});
54
55test("stored links that cannot be read are none", () => {
56 assert.deepEqual(storedLinks('[{"label":"A","url":"https://a.io"},{"label":1}]'), [{ label: "A", url: "https://a.io" }]);
57 assert.deepEqual(storedLinks("not json"), []);
58 assert.deepEqual(storedLinks(null), []);
59});
60
61test("a repository's own project follows its website until it has a homepage of its own", () => {
62 const row = { is_primary: 1, homepage: null, repo_website: "https://example.com", docs_url: null, links: null };
63 assert.deepEqual(projectLinks(row), { homepage: "https://example.com", homepageInherited: true, docs: null, custom: [] });
64 assert.equal(projectLinks({ ...row, homepage: "https://g1t.sh" }).homepage, "https://g1t.sh");
65 assert.equal(projectLinks({ ...row, homepage: "https://g1t.sh" }).homepageInherited, false);
66 // Another project in the same repository does not.
67 assert.deepEqual(projectLinks({ ...row, is_primary: 0 }).homepage, null);
68});