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

j/k, enter, esc and ? on telemetry, with test/keys-<page>.test.ts #10809

Merged opened this

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

Merged

mason/forge:mason/10798-j-k-enter-esc-and-on-telemetry-with-test → main 1 commit fork 1 thread · 1 unresolved

  • Merged. mason/10798-j-k-enter-esc-and-on-telemetry-with-test was merged into main as f92c9ae.

Review

Sign in to review this change.
1 file changed +80 −0
test/keys-telemetry.test.ts added +80
@@ -0,0 +1,80 @@
1 /**
2 * The real /settings/telemetry page and the shell's keys. Its j/k rows are the
3 * settings sections (chrome `settingsLayout`); an agent's grant row holds only a
4 * form (Grant/Revoke) and a read row is a log line, so neither has anywhere to open.
5 * Telemetry is a tab of the Usage section, so the current row is Usage (/settings/spend).
6 */
7 import { afterAll, beforeAll, expect, test } from "bun:test";
8 import { mkdtemp, rm } from "node:fs/promises";
9 import { tmpdir } from "node:os";
10 import { join } from "node:path";
11 import { createApp, type App } from "../src/app.ts";
12 import { serve, type Servers } from "../src/http/server.ts";
13 import { adminCookie } from "./helpers/admin.ts";
14 import { quietLogs } from "./helpers/globals.ts";
15 import { mainOf, shellPage } from "./helpers/shell-page.ts";
16
17 quietLogs();
18
19 let dir = "";
20 let app: App;
21 let servers: Servers;
22 let html = "";
23
24 beforeAll(async () => {
25 dir = await mkdtemp(join(tmpdir(), "forge-keys-telemetry-"));
26 app = createApp({ dataDir: dir, port: 0 });
27 servers = await serve(app);
28 const cookie = await adminCookie(app, { username: "alice", email: "[email protected]", password: "correct-horse-battery" });
29 app.db.query("INSERT INTO user (id, username, email, is_agent, password_hash) VALUES ('ag1', 'scout', '[email protected]', 1, '')").run();
30 const res = await fetch(`${servers.url}/settings/telemetry`, { headers: { cookie } });
31 html = mainOf(await res.text());
32 });
33 afterAll(async () => {
34 servers.stop();
35 app.close();
36 await rm(dir, { recursive: true, force: true });
37 });
38
39 test("the page draws the agent's grant form; the sections are the only rows", () => {
40 expect(html).toContain("scout");
41 expect(html).toContain('action="/settings/telemetry"');
42 const grants = html.slice(html.indexOf('class="list setting-list"'));
43 expect(grants).not.toContain("data-nav");
44 expect(html).toContain("data-nav");
45 });
46

Computing the expected row as rows[min(at+1, len-1)] mirrors the implementation. Pin the literal next href instead.

47 test("j/k walk the sections from the current one, Enter opens, Esc leaves nothing behind, fields keep their keys", async () => {
48 const p = await shellPage("/settings/telemetry", html + "<input id=f>");
49 const rows = [...p.doc.querySelectorAll("[data-nav]")] as any[];
50 const at = rows.findIndex((r) => r.getAttribute("aria-current") === "page");
51 expect(at).toBeGreaterThanOrEqual(0);
52 expect(rows[at].getAttribute("href")).toBe("/settings/spend"); // the Usage section holds the Telemetry tab
53
54 p.key("j");
55 expect(p.doc.activeElement).toBe(rows[Math.min(at + 1, rows.length - 1)]);
56 const target = p.doc.activeElement.getAttribute("href");
57 p.key("k");
58 expect(p.doc.activeElement).toBe(rows[Math.max(at, 0)]);
59 p.key("j");
60 p.key("Enter");
61 expect(p.clicks).toEqual([target]);
62 expect(JSON.parse(p.win.sessionStorage.getItem("nav-from")!)).toMatchObject({ list: "/settings/telemetry", href: target });
63
64 const f = p.doc.getElementById("f") as any;
65 f.focus();
66 const before = p.clicks.length;
67 p.key("j", f);
68 p.key("Enter", f);
69 expect(p.doc.activeElement).toBe(f);
70 expect(p.clicks.length).toBe(before);
71
72 const same = await shellPage("/settings/telemetry", html, { "nav-from": JSON.stringify({ list: "/settings/telemetry", to: "/settings/telemetry", href: target }) });
73 same.key("Escape");
74 expect(same.assigned).toEqual([]);
75 });
76
77 test("`?` opens the help from this page", async () => {
78 const p = await shellPage("/settings/telemetry", html);
79 expect(p.key("?").defaultPrevented).toBe(true);
80 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs