flagon-io/g1t

public

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

g1t/apps/sudo/app/lib/nav.test.ts

81 lines3,354 bytesCodeBlame
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { NAV, 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", "Revenue", "Platform", "Support", "Team"],
10 );
11 assert.deepEqual(NAV[0].items.map((item) => item.to), ["/", "/reach-out"]);
12});
13
14test("no section holds a single page, and every section has an icon", () => {
15 for (const group of NAV.filter((group) => group.title)) {
16 assert.ok(group.items.length >= 2, `${group.title} has more than one page`);
17 assert.ok(group.icon, `${group.title} has an icon`);
18 }
19});
20
21test("the section holding the current page is the one drawn open", () => {
22 const open = (path: string) => NAV.filter((group) => group.title && holdsCurrent(group, path)).map((group) => group.title);
23 assert.deepEqual(open("/workspaces/acme"), ["Customers"]);
24 assert.deepEqual(open("/stripe"), ["Platform"]);
25 assert.deepEqual(open("/audit"), ["Team"]);
26 assert.deepEqual(open("/"), []);
27 assert.deepEqual(open("/reach-out"), []);
28});
29
30test("every item has its own path, a label and a line about it", () => {
31 const paths = navItems().map((item) => item.to);
32 assert.equal(new Set(paths).size, paths.length);
33 for (const item of navItems()) {
34 assert.match(item.to, /^\/[a-z-]*$/, item.label);
35 assert.ok(item.label.length > 0);
36 assert.ok(item.about.length > 10, `${item.label} says what it is`);
37 }
38});
39
40test("the built pages are not marked soon", () => {
41 const built = navItems().filter((item) => !item.soon).map((item) => item.to);
42 assert.deepEqual(built, ["/", "/reach-out", "/workspaces", "/enterprises", "/invoices", "/stripe", "/audit"]);
43});
44
45test("every soon page says what it will do, why, and what it will have", () => {
46 const soon = soonItems();
47 assert.ok(soon.length >= 9);
48 for (const item of soon) {
49 assert.ok(item.soon.summary.length >= 1 && item.soon.summary.length <= 4, item.label);
50 assert.ok(item.soon.plans.length >= 3 && item.soon.plans.length <= 6, item.label);
51 if (item.soon.meanwhile?.to) assert.match(item.soon.meanwhile.to, /^\//);
52 }
53});
54
55test("view as customer promises an audit and a time limit", () => {
56 const page = soonFor("/view-as");
57 assert.ok(page);
58 const words = page.soon.summary.join(" ");
59 assert.match(words, /audited/);
60 assert.match(words, /time-limited/);
61});
62
63test("soonFor finds a placeholder by its path, and nothing else", () => {
64 assert.equal(soonFor("/prices")?.label, "Plans & prices");
65 assert.equal(soonFor("/prices/")?.label, "Plans & prices");
66 assert.equal(soonFor("/invoices"), null);
67 assert.equal(soonFor("/workspaces"), null);
68 assert.equal(soonFor("/nope"), null);
69});
70
71test("isCurrent: an item stays lit on the pages beneath it; / only on itself", () => {
72 const overview = { to: "/" };
73 const workspaces = { to: "/workspaces" };
74 assert.ok(isCurrent(overview, "/"));
75 assert.ok(!isCurrent(overview, "/workspaces"));
76 assert.ok(isCurrent(workspaces, "/workspaces"));
77 assert.ok(isCurrent(workspaces, "/workspaces/acme"));
78 assert.ok(isCurrent(workspaces, "/workspaces/"));
79 assert.ok(!isCurrent(workspaces, "/workspaces-old"));
80 assert.ok(isCurrent({ to: "/x", also: ["/y"] }, "/y/z"));
81});