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