Public: anyone can read this; the crew can change it.

A test pins the terminal palette's entries, in order, for each kind of session #7735

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

mason/forge:mason/7730-a-test-pins-the-terminal-palette-s-entri → main 1 commit fork

  • Merged. mason/7730-a-test-pins-the-terminal-palette-s-entri was merged into main as 26db2fc.

Review

Sign in to review this change.
1 file changed +209 −0
test/palette-roster.test.ts added +209
@@ -0,0 +1,209 @@
1 import { afterAll, beforeAll, expect, test } from "bun:test";
2 import { mkdtemp, rm } from "node:fs/promises";
3 import { tmpdir } from "node:os";
4 import { join } from "node:path";
5 import { createApp, type App } from "../src/app.ts";
6 import { createUser, type User } from "../src/core/users.ts";
7 import { forgeCommands, Session } from "../src/tui/forge.ts";
8 import { quietLogs } from "./helpers/globals.ts";
9
10 quietLogs();
11
12 let dir: string;
13 let app: App;
14 let admin: User;
15 let member: User;
16
17 const identity = (user?: User) => ({
18 sshUsername: user?.username ?? "git",
19 remoteAddress: "127.0.0.1",
20 fingerprint: "SHA256:test",
21 user,
22 });
23 const roster = (user?: User) =>
24 forgeCommands(new Session(app, identity(user)))({} as never).map((c) => [c.id, c.title, c.hint]);
25
26 beforeAll(async () => {
27 dir = await mkdtemp(join(tmpdir(), "forge-palette-roster-"));
28 app = createApp({ dataDir: dir, url: "https://forge.test", port: 0 });
29 const mk = async (username: string, isAdmin: boolean) => {
30 const r = await createUser(app.db, {
31 origin: "seed",
32 trusted: true, username, email: `${username}@forge.local`, password: "a-good-passphrase", isAdmin,
33 });
34 if (!r.ok) throw new Error(r.error);
35 return r.value;
36 };
37 admin = await mk("alice", true);
38 member = await mk("bob", false);
39 });
40 afterAll(async () => {
41 app.db.close();
42 await rm(dir, { recursive: true, force: true });
43 });
44
45 // The palette's entries as main has them: id, title, hint, in order, for each kind of session.
46 test("a site-admin person is offered the whole roster", () => {
47 expect(roster(admin)).toEqual([
48 ["home", "Home", "your repositories"],
49 ["explore", "Explore", "on the web"],
50 ["profile", "Open a profile", "username or org"],
51 ["repo", "Open a repository", "owner/name"],
52 ["issues", "Issues in a repository", "owner/name"],
53 ["pulls", "Pull requests in a repository", "owner/name"],
54 ["milestones", "Milestones in a repository", "owner/name"],
55 ["repo-usage", "Usage of a repository", "owner/name"],
56 ["new-issue", "New issue", "owner/name"],
57 ["new-pull", "New pull request", "owner/name"],
58 ["settings", "Repository settings", "owner/name"],
59 ["new-repo", "New repository", undefined],
60 ["new-org", "New organization", "an organization you own, for a client's apps"],
61 ["migrate", "Migrate a repository", "bring one in from an origin or a URL, pick its branch, put a crew on it"],
62 ["new-forge", "New forge", "spawn a client's forge and get its claim link"],
63 ["asked", "Asked", "your thoughts and what became of them"],
64 ["decider", "Decider", "what it closed, deferred and asked you about today"],
65 ["notify", "Phone notifications", "where the crew reaches your phone; s sets, x turns off"],
66 ["ssh-keys", "SSH keys", "list, add and remove the keys that sign in as you"],
67 ["account", "Account settings", undefined],
68 ["signins", "Signed in", "your browsers and tokens; d signs a browser out"],
69 ["sentinel", "Sentinel", "the forge's open faults"],
70 ["boards", "Boards", "the forge's boards and their panels"],
71 ["system-memory", "System memory", "RSS beside the JS heap, hourly for 24 h"],
72 ["flow", "Flow", "the pipeline's bottleneck and throughput"],
73 ["system", "System", "the machine now: CPU, memory, disks, processes"],
74 ["telemetry", "Telemetry", "which agents may read flow and system; enter flips the grant"],
75 ["capacity", "Capacity", "concurrency and guards, live; e changes a settable one"],
76 ["resilience", "Resilience", "where snapshots go and the mirror; each protection green, red or untested"],
77 ["api", "API", "the forge's endpoints; run a GET"],
78 ["changelog", "Changelog", "the last 30 releases and their pulls"],
79 ["releases", "Releases", "the live release and the kept ones"],
80 ["stalled", "Stalled steps", "pulls whose check is red or was never asked for; enter re-runs"],
81 ["file-holds", "Held files", "hold new work on a file, release it, or list the holds"],
82 ["access", "Access", "what outside agents tried"],
83 ["flags", "Flags", "declared flags and their live values"],
84 ["secrets", "Secrets", "sealed secrets by name; set or remove one"],
85 ["trusted-hosts", "Trusted hosts", "internal hosts an origin may reach"],
86 ["usage", "Usage", "every route, unused ones first"],
87 ["crew-scorecard", "Crew scorecard", "agent runs per model and per prompt version"],
88 ["crew-handover", "Crew hand-overs", "issues parked twice, and the last restore drill"],
89 ["scorecard", "Crew scorecard per agent", "each agent's pulls landed, review rounds, red checks, reverts, time to land"],
90 ["proposal-tokens", "Proposal tokens", "mint, list and revoke what a child proposes with"],
91 ["model", "Model budget", "what your crew may spend, and add your own subscription"],
92 ["model-grant", "Model grant", "give an account dollars a month, or take it back"],
93 ["model-ceiling", "Model ceiling", "set an account's dollars a day and a run"],
94 ["can", "What I can do", "your role and what it allows here"],
95 ["people", "People", "who is a guest, a member or an admin; promote or demote"],
96 ["quotas", "Account quotas", "what one account may own, and who changed it"],
97 ["limits", "Limits", "what the forge caps, with default and bounds; change one"],
98 ["teams", "Crew teams", "each team's charter, dial and members"],
99 ["invites", "Invite links", "make a single-use link, see which are open, revoke one"],
100 ["subscriptions", "Crew subscriptions", "each account's budget and rest; wake one, set its budget, add or remove one"],
101 ["cloud", "Cloud accounts", "provider tokens, what they are used for, today's calls"],
102 ["domains", "Failure domains", "failure domains and their last drill"],
103 ["owner", "Owner's needs", "what needs the owner, snapshots, failure domains"],
104 ["forges", "Forges you sent", "each forge sent, claimed or not, and its apps"],
105 ["family", "Family", "the forge that sent this one, and the forges it sent"],
106 ["chain", "Chain", "the forges this forge's code descends from, root first"],
107 ["quit", "Quit", "disconnect"],
108 ]);
109 });
110
111 test("a site-admin agent is offered the roster without the person-only entries", () => {
112 expect(roster({ ...admin, kind: "agent" })).toEqual([
113 ["home", "Home", "your repositories"],
114 ["explore", "Explore", "on the web"],
115 ["profile", "Open a profile", "username or org"],
116 ["repo", "Open a repository", "owner/name"],
117 ["issues", "Issues in a repository", "owner/name"],
118 ["pulls", "Pull requests in a repository", "owner/name"],
119 ["milestones", "Milestones in a repository", "owner/name"],
120 ["repo-usage", "Usage of a repository", "owner/name"],
121 ["new-issue", "New issue", "owner/name"],
122 ["new-pull", "New pull request", "owner/name"],
123 ["settings", "Repository settings", "owner/name"],
124 ["new-repo", "New repository", undefined],
125 ["migrate", "Migrate a repository", "bring one in from an origin or a URL, pick its branch, put a crew on it"],
126 ["new-forge", "New forge", "spawn a client's forge and get its claim link"],
127 ["asked", "Asked", "your thoughts and what became of them"],
128 ["decider", "Decider", "what it closed, deferred and asked you about today"],
129 ["ssh-keys", "SSH keys", "list, add and remove the keys that sign in as you"],
130 ["account", "Account settings", undefined],
131 ["signins", "Signed in", "your browsers and tokens; d signs a browser out"],
132 ["sentinel", "Sentinel", "the forge's open faults"],
133 ["resilience", "Resilience", "where snapshots go and the mirror; each protection green, red or untested"],
134 ["api", "API", "the forge's endpoints; run a GET"],
135 ["changelog", "Changelog", "the last 30 releases and their pulls"],
136 ["releases", "Releases", "the live release and the kept ones"],
137 ["stalled", "Stalled steps", "pulls whose check is red or was never asked for; enter re-runs"],
138 ["file-holds", "Held files", "hold new work on a file, release it, or list the holds"],
139 ["secrets", "Secrets", "sealed secrets by name; set or remove one"],
140 ["crew-scorecard", "Crew scorecard", "agent runs per model and per prompt version"],
141 ["crew-handover", "Crew hand-overs", "issues parked twice, and the last restore drill"],
142 ["scorecard", "Crew scorecard per agent", "each agent's pulls landed, review rounds, red checks, reverts, time to land"],
143 ["proposal-tokens", "Proposal tokens", "mint, list and revoke what a child proposes with"],
144 ["can", "What I can do", "your role and what it allows here"],
145 ["cloud", "Cloud accounts", "provider tokens, what they are used for, today's calls"],
146 ["forges", "Forges you sent", "each forge sent, claimed or not, and its apps"],
147 ["family", "Family", "the forge that sent this one, and the forges it sent"],
148 ["chain", "Chain", "the forges this forge's code descends from, root first"],
149 ["quit", "Quit", "disconnect"],
150 ]);
151 });
152
153 test("a member person is offered the signed-in roster without the admin entries", () => {
154 expect(roster(member)).toEqual([
155 ["home", "Home", "your repositories"],
156 ["explore", "Explore", "on the web"],
157 ["profile", "Open a profile", "username or org"],
158 ["repo", "Open a repository", "owner/name"],
159 ["issues", "Issues in a repository", "owner/name"],
160 ["pulls", "Pull requests in a repository", "owner/name"],
161 ["milestones", "Milestones in a repository", "owner/name"],
162 ["repo-usage", "Usage of a repository", "owner/name"],
163 ["new-issue", "New issue", "owner/name"],
164 ["new-pull", "New pull request", "owner/name"],
165 ["settings", "Repository settings", "owner/name"],
166 ["new-repo", "New repository", undefined],
167 ["new-org", "New organization", "an organization you own, for a client's apps"],
168 ["migrate", "Migrate a repository", "bring one in from an origin or a URL, pick its branch, put a crew on it"],
169 ["new-forge", "New forge", "spawn a client's forge and get its claim link"],
170 ["asked", "Asked", "your thoughts and what became of them"],
171 ["decider", "Decider", "what it closed, deferred and asked you about today"],
172 ["notify", "Phone notifications", "where the crew reaches your phone; s sets, x turns off"],
173 ["ssh-keys", "SSH keys", "list, add and remove the keys that sign in as you"],
174 ["account", "Account settings", undefined],
175 ["signins", "Signed in", "your browsers and tokens; d signs a browser out"],
176 ["api", "API", "the forge's endpoints; run a GET"],
177 ["changelog", "Changelog", "the last 30 releases and their pulls"],
178 ["stalled", "Stalled steps", "pulls whose check is red or was never asked for; enter re-runs"],
179 ["file-holds", "Held files", "hold new work on a file, release it, or list the holds"],
180 ["proposal-tokens", "Proposal tokens", "mint, list and revoke what a child proposes with"],
181 ["model", "Model budget", "what your crew may spend, and add your own subscription"],
182 ["can", "What I can do", "your role and what it allows here"],
183 ["family", "Family", "the forge that sent this one, and the forges it sent"],
184 ["chain", "Chain", "the forges this forge's code descends from, root first"],
185 ["quit", "Quit", "disconnect"],
186 ]);
187 });
188
189 test("signed out, the palette offers sign-in and the public entries", () => {
190 expect(roster()).toEqual([
191 ["home", "Home", "your repositories"],
192 ["explore", "Explore", "on the web"],
193 ["profile", "Open a profile", "username or org"],
194 ["repo", "Open a repository", "owner/name"],
195 ["issues", "Issues in a repository", "owner/name"],
196 ["pulls", "Pull requests in a repository", "owner/name"],
197 ["milestones", "Milestones in a repository", "owner/name"],
198 ["repo-usage", "Usage of a repository", "owner/name"],
199 ["new-issue", "New issue", "owner/name"],
200 ["new-pull", "New pull request", "owner/name"],
201 ["settings", "Repository settings", "owner/name"],
202 ["signin", "Sign in", undefined],
203 ["api", "API", "the forge's endpoints; run a GET"],
204 ["changelog", "Changelog", "the last 30 releases and their pulls"],
205 ["family", "Family", "the forge that sent this one, and the forges it sent"],
206 ["chain", "Chain", "the forges this forge's code descends from, root first"],
207 ["quit", "Quit", "disconnect"],
208 ]);
209 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs