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

A new forge's admin is asked for an everyday account in one plain block on home, not a boxed card #10002

Merged opened this

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

Merged

mason/forge:mason/9957-a-new-forge-s-admin-is-asked-for-an-ever → main 2 commits fork 1 thread · 1 unresolved

  • Merged. mason/9957-a-new-forge-s-admin-is-asked-for-an-ever was merged into main as db18847.

Review

Sign in to review this change.
2 files changed +68 −2
src/web/pages/everyday.ts +6 −2
@@ -43,10 +43,14 @@ function suggestedName(ctx: Ctx, admin: User): string {
4343 return getUserByName(ctx.app.db, name) === undefined ? name : "";
4444 }
4545
46 /** The card, for an admin with no everyday account and no recorded choice. */
46 /** The home section, for an admin with no everyday account and no recorded choice. */
4747 export function everydayCard(ctx: Ctx, user: User): Html | null {
4848 if (!askForEveryday(ctx.app.db, user)) return null;
49 return html`<div class="mb">${everydayForm(ctx, user, true)}</div>`;
49 return html`<section class="settings-block" id="everyday">
50 <h2>Make your everyday account</h2>

Principle 1: this h2 and the EVERYDAY_WHY sentence repeat what everydayForm writes for the boxed card. Share one helper. Also update the file header, which still says card.

51 <p>${EVERYDAY_WHY}</p>
52 ${everydayFields(ctx, user, true)}
53 </section>`;
5054 }
5155
5256 /**
test/everyday-language.test.ts added +62
@@ -0,0 +1,62 @@
1 /** The everyday-account ask on home speaks the home page's language: a block, not a card (#9957). */
2 import { afterAll, beforeAll, expect, test } from "bun:test";
3 import { mkdtemp, rm } from "node:fs/promises";
4 import { tmpdir } from "node:os";
5 import { join } from "node:path";
6 import { createApp, type App } from "../src/app.ts";
7 import { getUserByName } from "../src/core/users.ts";
8 import { createSession } from "../src/core/sessions.ts";
9 import { serve, type Servers } from "../src/http/server.ts";
10 import { EVERYDAY_WHY } from "../src/core/everyday.ts";
11 import { seedAdmin } from "./helpers/admin.ts";
12
13 let dataDir = "";
14 let app: App, servers: Servers;
15 let admin = "";
16
17 beforeAll(async () => {
18 dataDir = await mkdtemp(join(tmpdir(), "forge-everyday-lang-"));
19 app = createApp({ dataDir, port: 0 });
20 servers = await serve(app);
21 const a = await seedAdmin(app, { username: "alice", email: "[email protected]", password: "correct-horse-battery" });
22 if (!a.ok) throw new Error(a.error);
23 admin = `forge_session=${createSession(app.db, getUserByName(app.db, "alice")!.id).token}`;
24 });
25 afterAll(async () => {
26 servers.stop();
27 app.close();
28 await rm(dataDir, { recursive: true, force: true });
29 });
30
31 const main = (page: string) => page.slice(page.indexOf("<main"), page.indexOf("</main>"));
32 const home = async () => main(await (await fetch(`${servers.url}/`, { headers: { cookie: admin } })).text());
33
34 test("home asks for an everyday account in a plain section, no card", async () => {
35 const m = await home();
36 const at = m.indexOf('id="everyday"');
37 expect(at).toBeGreaterThan(0);
38 const block = m.slice(m.lastIndexOf("<section", at), m.indexOf("</section>", at));
39 expect(block).toContain('class="settings-block"');
40 expect(block).toMatch(/<h2>Make your everyday account<\/h2>/);
41 expect(block).toContain(EVERYDAY_WHY);
42 expect(block).not.toContain('class="card');
43 expect(block).toContain('action="/settings/everyday"');
44 expect(block).toContain('action="/settings/everyday/keep"');
45 });
46
47 test("dismissing is a same-origin POST, and home stops asking", async () => {
48 const cross = await fetch(`${servers.url}/settings/everyday/keep`, {
49 method: "POST",
50 headers: { cookie: admin, origin: "https://evil.example", "content-type": "application/x-www-form-urlencoded" },
51 redirect: "manual",
52 });
53 expect(cross.status).toBe(403);
54 expect(await home()).toContain('id="everyday"');
55 const ok = await fetch(`${servers.url}/settings/everyday/keep`, {
56 method: "POST",
57 headers: { cookie: admin, origin: servers.url, "content-type": "application/x-www-form-urlencoded" },
58 redirect: "manual",
59 });
60 expect(ok.status).toBeLessThan(400);
61 expect(await home()).not.toContain('id="everyday"');
62 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs