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

Each test in test/releases-page.test.ts stands alone: no test leaves the repository public or the fixture half-built for the next #4710

Merged opened this

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

Merged

scout/forge:scout/4694-each-test-in-test-releases-page-test-ts → main 1 commit fork

  • Merged. scout/4694-each-test-in-test-releases-page-test-ts was merged into main as 536c504.

Review

Sign in to review this change.
1 file changed +34 −40
test/releases-page.test.ts +34 −40
@@ -11,13 +11,13 @@ import { tmpdir } from "node:os";
1111 import { join } from "node:path";
1212 import { createRepo } from "../src/actions/repos.ts";
1313 import { createApp, type App } from "../src/app.ts";
14 import { markVerified } from "../src/core/verify.ts";
1415 import { createSession } from "../src/core/sessions.ts";
15 import { createUser } from "../src/core/users.ts";
1616 import { migrations } from "../src/core/schema.ts";
1717 import { serve, type Servers } from "../src/http/server.ts";
1818 import { releaseDir } from "../src/release/checkout.ts";
19 import { beginSwap, endSwap } from "../src/release/swap.ts";
1920 import { recordRelease } from "../src/release/record.ts";
20 import { proveAll } from "./helpers/verified.ts";
2121 import { quietLogs } from "./helpers/globals.ts";
2222
2323 quietLogs();
@@ -41,6 +41,15 @@ describe("the releases page", () => {
4141 const u = app.db.query<{ id: string }, [string]>("SELECT id FROM user WHERE username = ?").get(username)!;
4242 return `forge_session=${createSession(app.db, u.id).token}`;
4343 };
44 // Accounts inserted directly: no password hash is made, and none of these tests signs in with one.
45 const addUser = (username: string, isAdmin: boolean) => {
46 const id = `u-${username}`;
47 app.db
48 .query("INSERT INTO user (id, username, email, password_hash, is_admin) VALUES (?1, ?2, ?3, 'x', ?4)")
49 .run(id, username, `${username}@forge.local`, isAdmin ? 1 : 0);
50 markVerified(app.db, id, new Date().toISOString());
51 return id;
52 };
4453 const post = (path: string, cookie: string, origin: string) =>
4554 fetch(`${servers.url}${path}`, {
4655 method: "POST",
@@ -52,23 +61,9 @@ describe("the releases page", () => {
5261 process.env["FORGE_COMMIT"] = LIVE;
5362 root = mkdtempSync(join(tmpdir(), "forge-releases-"));
5463 app = createApp({ dataDir: root, port: 0, forgeRepo: "alice/forge" });
55 for (const [username, password, adminIfFirst] of [
56 ["alice", "a-good-passphrase", true],
57 ["bob", "another-good-passphrase", false],
58 ] as const) {
59 const u = await createUser(app.db, {
60 origin: "seed",
61 trusted: true,
62 username,
63 email: `${username}@forge.local`,
64 password,
65 adminIfFirst,
66 });
67 if (!u.ok) throw new Error(u.error);
68 }
69 proveAll(app);
70 const alice = app.db.query<{ id: string }, []>("SELECT id FROM user WHERE username='alice'").get()!;
71 const made = await createRepo(app, { id: alice.id, username: "alice" } as never, { name: "forge" });
64 addUser("alice", true);
65 addUser("bob", false);
66 const made = await createRepo(app, { id: "u-alice", username: "alice" } as never, { name: "forge" });
7267 if (!made.ok) throw new Error(made.error);
7368 const repoId = app.db.query<{ id: string }, []>("SELECT id FROM repo WHERE name='forge'").get()!.id;
7469 for (const [s, pull, line] of [
@@ -119,30 +114,25 @@ describe("the releases page", () => {
119114 expect(home).not.toContain("aaaaaaa");
120115 expect((await post(`/releases/${KEPT}/rollback`, cookie, servers.url)).status).toBe(403);
121116
122 app.db.query("UPDATE repo SET visibility = 'public' WHERE name = 'forge'").run();
123 const refused = await get("/releases");
124 expect(refused.status).toBe(403);
125 const body = await refused.text();
126 expect(body).not.toContain("bbbbbbb");
127 expect(body).not.toContain("/rollback");
128 expect((await post(`/releases/${KEPT}/rollback`, cookie, servers.url)).status).toBe(403);
129 expect((await post(`/releases/${KEPT}/rollback`, "", servers.url)).status).toBe(403);
130 expect(await (await get("/")).text()).not.toContain("live-release");
131 app.db.query("UPDATE repo SET visibility = 'private' WHERE name = 'forge'").run();
117 try {
118 app.db.query("UPDATE repo SET visibility = 'public' WHERE name = 'forge'").run();
119 const refused = await get("/releases");
120 expect(refused.status).toBe(403);
121 const body = await refused.text();
122 expect(body).not.toContain("bbbbbbb");
123 expect(body).not.toContain("/rollback");
124 expect((await post(`/releases/${KEPT}/rollback`, cookie, servers.url)).status).toBe(403);
125 expect((await post(`/releases/${KEPT}/rollback`, "", servers.url)).status).toBe(403);
126 expect(await (await get("/")).text()).not.toContain("live-release");
127 } finally {
128 app.db.query("UPDATE repo SET visibility = 'private' WHERE name = 'forge'").run();
129 }
132130 });
133131
134132 test("an agent that can write the repository gets no button and a 403", async () => {
135 const u = await createUser(app.db, {
136 origin: "seed",
137 trusted: true,
138 username: "crew1",
139 email: "[email protected]",
140 password: "crew-good-passphrase",
141 adminIfFirst: false,
142 });
143 if (!u.ok) throw new Error(u.error);
144 app.db.query("UPDATE user SET is_agent = 1, is_admin = 1 WHERE username = 'crew1'").run();
145 const cookie = `forge_session=${createSession(app.db, u.value.id).token}`;
133 const id = addUser("crew1", true);
134 app.db.query("UPDATE user SET is_agent = 1 WHERE id = ?").run(id);
135 const cookie = `forge_session=${createSession(app.db, id).token}`;
146136 const body = await (await fetch(`${servers.url}/releases`, { headers: { cookie } })).text();
147137 expect(body).toContain("bbbbbbb");
148138 expect(body).not.toContain("/rollback");
@@ -162,6 +152,10 @@ describe("the releases page", () => {
162152 const flash = (res.headers.getSetCookie() ?? []).map((c) => c.split(";")[0]).join("; ");
163153 const shown = await (await fetch(`${servers.url}/releases`, { headers: { cookie: `${cookie}; ${flash}` } })).text();
164154 expect(shown).toContain("FORGE_SELF_SWAP is off");
155 // No swap began: the one turn this process may take is still free.
156 const turn = beginSwap();
157 if (turn.ok) endSwap(false);
158 else expect(turn.line).not.toContain("already under way");
165159 });
166160
167161 test("the home links the live release", async () => {

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs