Skip to content

g1t/apps/web/app/lib/checklist.test.ts

174 lines7,495 bytesCodeBlame
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import {
5 type ChecklistFacts,
6 agentWasAssigned,
7 checklistPlan,
8 dismiss,
9 dismissKey,
10 hasInstructions,
11 isDismissed,
12 productionChecklist,
13 progress,
14 releaseChecklist,
15 startChecklist,
16} from "./checklist.ts";
17
18const fresh: ChecklistFacts = {
19 base: "/acme/web",
20 hasCode: false,
21 deploysEnabled: false,
22 productionDeployed: false,
23 domains: 0,
24 previewOpened: false,
25 instructions: false,
26 agentAssigned: false,
27};
28
29test("a new project has everything to do, in order", () => {
30 const items = productionChecklist(fresh);
31 assert.deepEqual(
32 items.map((item) => item.key),
33 ["code", "deploy", "domain", "preview", "instructions", "agent"],
34 );
35 assert.deepEqual(progress(items), { done: 0, total: 6, complete: false });
36});
37
38test("each step is done from its own fact", () => {
39 const items = productionChecklist({ ...fresh, hasCode: true, productionDeployed: true, domains: 2 });
40 assert.deepEqual(progress(items), { done: 3, total: 6, complete: false });
41 const all = productionChecklist({
42 ...fresh,
43 hasCode: true,
44 productionDeployed: true,
45 domains: 1,
46 previewOpened: true,
47 instructions: true,
48 agentAssigned: true,
49 });
50 assert.equal(progress(all).complete, true);
51});
52
53test("unknown facts count as not done", () => {
54 const items = productionChecklist({ ...fresh, domains: null, instructions: null });
55 assert.equal(items.find((item) => item.key === "domain")?.done, false);
56 assert.equal(items.find((item) => item.key === "instructions")?.done, false);
57});
58
59test("each step links to where it is done", () => {
60 const off = productionChecklist(fresh);
61 assert.equal(off.find((item) => item.key === "deploy")?.to, "/acme/web/settings/deployments");
62 const on = productionChecklist({ ...fresh, deploysEnabled: true });
63 assert.equal(on.find((item) => item.key === "deploy")?.to, "/acme/web/deployments");
64 assert.equal(on.find((item) => item.key === "domain")?.to, "/acme/web/settings/domains");
65 assert.equal(on.find((item) => item.key === "agent")?.to, "/acme/web/issues/new");
66});
67
68test("instructions are AGENTS.md or CLAUDE.md at the root", () => {
69 assert.equal(hasInstructions(["README.md", "AGENTS.md"]), true);
70 assert.equal(hasInstructions(["claude.md"]), true);
71 assert.equal(hasInstructions(["README.md", "AGENTS.mdx", "docs"]), false);
72});
73
74test("g1t counts as assigned from a run, a pull request or an issue", () => {
75 const none = { runAgents: ["claude-code"], pullAgents: ["claude-code"], issues: [{ assignees: ["ana"], agent: null }] };
76 assert.equal(agentWasAssigned(none), false);
77 assert.equal(agentWasAssigned({ ...none, runAgents: ["g1t"] }), true);
78 assert.equal(agentWasAssigned({ ...none, pullAgents: ["g1t"] }), true);
79 assert.equal(agentWasAssigned({ ...none, issues: [{ assignees: ["G1T"], agent: null }] }), true);
80 assert.equal(agentWasAssigned({ ...none, issues: [{ assignees: [], agent: "g1t" }] }), true);
81});
82
83test("dismissing is remembered per project, and storage that throws is ignored", () => {
84 const map = new Map<string, string>();
85 const store = { getItem: (key: string) => map.get(key) ?? null, setItem: (key: string, value: string) => void map.set(key, value) };
86 assert.equal(isDismissed(() => store, "/acme/web"), false);
87 assert.equal(dismiss(() => store, "/Acme/Web"), true);
88 assert.equal(isDismissed(() => store, "/acme/web"), true);
89 assert.equal(isDismissed(() => store, "/acme/api"), false);
90 assert.equal(dismissKey("/Acme/Web"), "g1t:checklist-dismissed:/acme/web");
91 const blocked = {
92 getItem: () => {
93 throw new Error("blocked");
94 },
95 setItem: () => {
96 throw new Error("blocked");
97 },
98 };
99 assert.equal(isDismissed(() => blocked, "/acme/web"), false);
100 assert.equal(dismiss(() => blocked, "/acme/web"), false);
101});
102
103test("a library's checklist ships a release instead of deploying", () => {
104 const facts = {
105 base: "/flagon-io/php-log",
106 hasCode: true,
107 instructions: false,
108 agentAssigned: false,
109 hasWorkflow: false,
110 released: true,
111 releaseTo: "/flagon-io/-/packages/composer/psr/log",
112 };
113 const items = releaseChecklist(facts);
114 assert.deepEqual(
115 items.map((item) => item.key),
116 ["code", "checks", "release", "instructions", "agent"],
117 );
118 assert.deepEqual(progress(items), { done: 2, total: 5, complete: false });
119 assert.equal(items.find((item) => item.key === "checks")?.to, "/flagon-io/php-log/actions");
120 assert.equal(items.find((item) => item.key === "release")?.to, "/flagon-io/-/packages/composer/psr/log");
121 assert.ok(items.every((item) => !/deploy|production|domain|preview/i.test(item.title)));
122 // An unknown workflow list counts as not done.
123 assert.equal(releaseChecklist({ ...facts, hasWorkflow: null }).find((item) => item.key === "checks")?.done, false);
124});
125
126const start = {
127 base: "/flagon-io/g1t",
128 hasCode: true,
129 instructions: true,
130 agentAssigned: false,
131 hasWorkflow: true,
132 productionUrl: null,
133 hasLinks: false,
134 hasDocsLink: false,
135};
136
137test("only what g1t deploys gets production's steps", () => {
138 assert.deepEqual(checklistPlan({ kind: "app", runs: "g1t" }), { plan: "production", title: "Get to production" });
139 assert.deepEqual(checklistPlan({ kind: "docs", runs: "g1t" }).plan, "production");
140 assert.deepEqual(checklistPlan({ kind: "app", runs: "elsewhere" }), { plan: "elsewhere", title: "Get started" });
141 assert.equal(checklistPlan({ kind: "app", runs: null }).plan, "unknown");
142 assert.deepEqual(checklistPlan({ kind: "tool", runs: null }), { plan: "release", title: "Ship a release" });
143 assert.equal(checklistPlan({ kind: "library", runs: null }).plan, "release");
144 assert.equal(checklistPlan({ kind: "docs", runs: "elsewhere" }).plan, "docs");
145 assert.equal(checklistPlan({ kind: "other", runs: null }).plan, "other");
146});
147
148test("an app deployed elsewhere is never asked to deploy on g1t", () => {
149 const items = startChecklist("elsewhere", start);
150 assert.deepEqual(
151 items.map((item) => item.key),
152 ["code", "production", "checks", "instructions", "agent"],
153 );
154 assert.ok(items.every((item) => !/deploy to|turn on|domain|preview/i.test(`${item.title} ${item.detail}`)));
155 assert.equal(items.find((item) => item.key === "production")?.done, false);
156 assert.equal(startChecklist("elsewhere", { ...start, productionUrl: "https://g1t.sh" }).find((item) => item.key === "production")?.done, true);
157 // Every step can be done.
158 const all = startChecklist("elsewhere", { ...start, productionUrl: "https://g1t.sh", agentAssigned: true });
159 assert.equal(progress(all).complete, true);
160});
161
162test("an app nobody has placed asks where it runs; docs and other ask for links", () => {
163 assert.deepEqual(
164 startChecklist("unknown", start).map((item) => item.key),
165 ["code", "where", "checks", "instructions", "agent"],
166 );
167 assert.equal(startChecklist("unknown", start).find((item) => item.key === "where")?.to, "/flagon-io/g1t/settings#kind");
168 const docs = startChecklist("docs", { ...start, hasDocsLink: true });
169 assert.deepEqual(docs.map((item) => item.key), ["code", "links", "instructions", "agent"]);
170 assert.equal(docs.find((item) => item.key === "links")?.done, true);
171 const other = startChecklist("other", start);
172 assert.equal(other.find((item) => item.key === "links")?.done, false);
173 assert.equal(startChecklist("other", { ...start, hasLinks: true, agentAssigned: true }).every((item) => item.done), true);
174});