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.

109 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { confirmsName, daysUntil, filterCounts, filterRepos, longDate, parseFilter, renamedBranchPath, summariseBulk, tidyName } from "./repo-lifecycle.ts";
5
6test("the typed name confirms only the full name, in any case", () => {
7 assert.equal(confirmsName("acme/web", "acme/web"), true);
8 assert.equal(confirmsName(" ACME/Web ", "acme/web"), true);
9 assert.equal(confirmsName("web", "acme/web"), false);
10 assert.equal(confirmsName("", "acme/web"), false);
11 assert.equal(confirmsName(null, "acme/web"), false);
12});
13
14const repos = [
15 { name: "web", description: "The site", topics: ["astro"], isPrivate: false, archivedAt: null },
16 { name: "api", description: "Rust service", topics: ["rust", "cli"], isPrivate: true, archivedAt: null },
17 { name: "old-site", description: null, topics: [], isPrivate: false, archivedAt: "2026-01-01T00:00:00Z" },
18];
19
20test("filters by visibility and archived", () => {
21 assert.deepEqual(
22 filterRepos(repos, "all", "").map((r) => r.name),
23 ["web", "api", "old-site"],
24 );
25 assert.deepEqual(
26 filterRepos(repos, "public", "").map((r) => r.name),
27 ["web", "old-site"],
28 );
29 assert.deepEqual(
30 filterRepos(repos, "private", "").map((r) => r.name),
31 ["api"],
32 );
33 assert.deepEqual(
34 filterRepos(repos, "archived", "").map((r) => r.name),
35 ["old-site"],
36 );
37});
38
39test("search matches every word in name, description or topics", () => {
40 assert.deepEqual(
41 filterRepos(repos, "all", "rust").map((r) => r.name),
42 ["api"],
43 );
44 assert.deepEqual(
45 filterRepos(repos, "all", "SITE").map((r) => r.name),
46 ["web", "old-site"],
47 );
48 assert.deepEqual(
49 filterRepos(repos, "all", "site astro").map((r) => r.name),
50 ["web"],
51 );
52 assert.deepEqual(
53 filterRepos(repos, "private", "site").map((r) => r.name),
54 [],
55 );
56});
57
58test("counts each filter", () => {
59 assert.deepEqual(filterCounts(repos), { all: 3, public: 2, private: 1, archived: 1 });
60});
61
62test("an unknown filter is all", () => {
63 assert.equal(parseFilter("archived"), "archived");
64 assert.equal(parseFilter("nope"), "all");
65 assert.equal(parseFilter(null), "all");
66});
67
68test("a bulk action is summed up, with each failure and why", () => {
69 assert.deepEqual(
70 summariseBulk(
71 [
72 { name: "web", ok: true },
73 { name: "api", ok: false, error: "Only owners can archive a repository." },
74 { name: "cli", ok: true },
75 ],
76 "archived",
77 ),
78 {
79 message: "2 repositories archived. 1 repository could not be.",
80 failures: ["api: Only owners can archive a repository."],
81 },
82 );
83 assert.equal(summariseBulk([{ name: "web", ok: true }], "unarchived").message, "1 repository unarchived.");
84 assert.equal(summariseBulk([], "archived").message, "Nothing was selected.");
85});
86
87test("a renamed branch keeps the rest of the address", () => {
88 assert.equal(renamedBranchPath("/acme/web/tree/master/src/lib", "?x=1", "main"), "/acme/web/tree/main/src/lib?x=1");
89 assert.equal(renamedBranchPath("/acme/web/blob/old/README.md", "", "feature/new"), "/acme/web/blob/feature%2Fnew/README.md");
90 assert.equal(renamedBranchPath("/acme/web/tree/master", "", "main"), "/acme/web/tree/main");
91 assert.equal(renamedBranchPath("/acme/web/commits", "", "main"), null);
92});
93
94test("days until a date, never negative", () => {
95 const now = Date.parse("2026-10-05T12:00:00Z");
96 assert.equal(daysUntil("2026-11-04T12:00:00Z", now), 30);
97 assert.equal(daysUntil("2026-10-05T13:00:00Z", now), 1);
98 assert.equal(daysUntil("2026-10-01T00:00:00Z", now), 0);
99 assert.equal(daysUntil("not a date", now), 0);
100});
101
102test("dates read the same everywhere", () => {
103 assert.equal(longDate("2026-11-04T23:30:00Z"), "4 November 2026");
104 assert.equal(longDate("nope"), "nope");
105});
106
107test("names are tidied, not judged", () => {
108 assert.equal(tidyName(" my new site "), "my-new-site");
109});