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.

115 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { NAV, countFor, holdsCurrent, isCurrent, navItems, soonFor, soonItems } from "./nav.ts";
5
6test("the sidebar: two top-level links, then sections that fold", () => {
7 assert.deepEqual(
8 NAV.map((group) => group.title),
9 [null, "Customers", "Spend", "Revenue", "Platform", "Support", "Team"],
10 );
11 assert.deepEqual(
12 NAV[0].items.map((item) => item.to),
13 ["/", "/reach-out"],
14 );
15});
16
17test("no section holds a single page, and every section has an icon", () => {
18 for (const group of NAV.filter((group) => group.title)) {
19 assert.ok(group.items.length >= 2, `${group.title} has more than one page`);
20 assert.ok(group.icon, `${group.title} has an icon`);
21 }
22});
23
24test("the section holding the current page is the one drawn open", () => {
25 const open = (path: string) => NAV.filter((group) => group.title && holdsCurrent(group, path)).map((group) => group.title);
26 assert.deepEqual(open("/workspaces/acme"), ["Customers"]);
27 assert.deepEqual(open("/stripe"), ["Platform"]);
28 assert.deepEqual(open("/overages"), ["Spend"]);
29 assert.deepEqual(open("/audit"), ["Team"]);
30 assert.deepEqual(open("/"), []);
31 assert.deepEqual(open("/reach-out"), []);
32});
33
34test("every item has its own path, a label and a line about it", () => {
35 const paths = navItems().map((item) => item.to);
36 assert.equal(new Set(paths).size, paths.length);
37 for (const item of navItems()) {
38 assert.match(item.to, /^\/[a-z-]*$/, item.label);
39 assert.ok(item.label.length > 0);
40 assert.ok(item.about.length > 10, `${item.label} says what it is`);
41 }
42});
43
44test("the built pages are not marked soon", () => {
45 const built = navItems()
46 .filter((item) => !item.soon)
47 .map((item) => item.to);
48 assert.deepEqual(built, [
49 "/",
50 "/reach-out",
51 "/workspaces",
52 "/privacy",
53 "/enterprises",
54 "/invites",
55 "/aliases",
56 "/requests",
57 "/overages",
58 "/velocity",
59 "/invoices",
60 "/credits",
61 "/stripe",
62 "/costs",
63 "/abuse",
64 "/blocked-domains",
65 "/incidents",
66 "/audit",
67 ]);
68});
69
70test("every soon page says what it will do, why, and what it will have", () => {
71 const soon = soonItems();
72 assert.ok(soon.length >= 7);
73 for (const item of soon) {
74 assert.ok(item.soon.summary.length >= 1 && item.soon.summary.length <= 4, item.label);
75 assert.ok(item.soon.plans.length >= 3 && item.soon.plans.length <= 6, item.label);
76 if (item.soon.meanwhile?.to) assert.match(item.soon.meanwhile.to, /^\//);
77 }
78});
79
80test("view as customer promises an audit and a time limit", () => {
81 const page = soonFor("/view-as");
82 assert.ok(page);
83 const words = page.soon.summary.join(" ");
84 assert.match(words, /audited/);
85 assert.match(words, /time-limited/);
86});
87
88test("soonFor finds a placeholder by its path, and nothing else", () => {
89 assert.equal(soonFor("/prices")?.label, "Plans & prices");
90 assert.equal(soonFor("/prices/")?.label, "Plans & prices");
91 assert.equal(soonFor("/invoices"), null);
92 assert.equal(soonFor("/workspaces"), null);
93 assert.equal(soonFor("/nope"), null);
94});
95
96test("isCurrent: an item stays lit on the pages beneath it; / only on itself", () => {
97 const overview = { to: "/" };
98 const workspaces = { to: "/workspaces" };
99 assert.ok(isCurrent(overview, "/"));
100 assert.ok(!isCurrent(overview, "/workspaces"));
101 assert.ok(isCurrent(workspaces, "/workspaces"));
102 assert.ok(isCurrent(workspaces, "/workspaces/acme"));
103 assert.ok(isCurrent(workspaces, "/workspaces/"));
104 assert.ok(!isCurrent(workspaces, "/workspaces-old"));
105 assert.ok(isCurrent({ to: "/x", also: ["/y"] }, "/y/z"));
106});
107
108test("open incidents show beside Incidents, and nothing waits beside Invites", () => {
109 const incidents = navItems().find((item) => item.to === "/incidents")!;
110 assert.equal(incidents.count, "incidents");
111 assert.equal(countFor([incidents], { incidents: 2 }), 2);
112 assert.equal(countFor([incidents], {}), 0);
113 const invites = navItems().find((item) => item.to === "/invites")!;
114 assert.equal(invites.count, undefined);
115});