Public: anyone can read this; the crew can change it.
/resilience shows the nightly drill's output as plain lines, not a boxed card #9981
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/9974-resilience-shows-the-nightly-drill-s-out → main 2 commits fork
2 files
changed +24
−3
src/web/pages/resilience.ts +8 −2
| @@ -58,10 +58,16 @@ export function nightlyOutputPage(ctx: Ctx): Response { | ||
| 58 | 58 | </div> |
| 59 | 59 | ${output === undefined |
| 60 | 60 | ? html`<p id="nightly-output" class="muted">No output here yet: it has not run on this forge.</p>` |
| 61 | : html`<pre id="nightly-output" class="card mono" tabindex="0" aria-label="Output">${output}</pre>`}`; | |
| 62 | return page({ ctx, title: `${job.name} · Resilience`, body }); | |
| 61 | : html`<pre id="nightly-output" class="muted mono" tabindex="0" aria-label="Output">${output}</pre>`}`; | |
| 62 | return page({ ctx, title: `${job.name} · Resilience`, body, styleCss: NIGHTLY_OUTPUT_CSS }); | |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | /** | |
| 66 | * A night's output is plain muted lines, no card (#9974): a long line | |
| 67 | * scrolls sideways inside the `pre`, never the page, at 390 px. | |
| 68 | */ | |
| 69 | export const NIGHTLY_OUTPUT_CSS = `pre-output { max-width: 100%; overflow-x: auto; scrollbar-width: thin; margin: 0; }`; | |
| 70 | ||
| 65 | 71 | /** |
| 66 | 72 | * A protection is a sentence from THREATS.md and its test a path, so inside |
| 67 | 73 | * `[data-resilience]` (an attribute, not a class) a row's title and meta wrap |
test/resilience-language.test.ts +16 −1
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | /** /resilience speaks the home page's language (#9877): one heading, the protections a plain section, no card. */ |
| 2 | 2 | import { afterAll, beforeAll, expect, test } from "bun:test"; |
| 3 | import { mkdtemp, rm } from "node:fs/promises"; | |
| 3 | import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"; | |
| 4 | 4 | import { tmpdir } from "node:os"; |
| 5 | 5 | import { join } from "node:path"; |
| 6 | 6 | import type { Row } from "../src/checks/resilience.ts"; |
| @@ -52,3 +52,18 @@ test("a cited file the last gate did not run reads untested, never green", () => | ||
| 52 | 52 | expect(out).not.toContain("success"); |
| 53 | 53 | expect(out).not.toContain('class="card'); |
| 54 | 54 | }); |
| 55 | ||
| 56 | test("a night's output on /resilience/nightly/:job is plain lines, no card, scrolling inside itself (#9974)", async () => { | |
| 57 | await mkdir(join(dir, "nightly"), { recursive: true }); | |
| 58 | await writeFile(join(dir, "nightly", "flake-hunt.log"), `a very long line ${"x".repeat(400)}\n`); | |
| 59 | const res = await fetch(`${servers.url}/resilience/nightly/flake-hunt`, { headers: { cookie } }); | |
| 60 | expect(res.status).toBe(200); | |
| 61 | const body = await res.text(); | |
| 62 | const page = main(body); | |
| 63 | expect(page).not.toContain('class="card'); | |
| 64 | const pre = page.match(/<pre id="nightly-output"[^>]*>/)?.[0] ?? ""; | |
| 65 | expect(pre).toContain('tabindex="0"'); | |
| 66 | expect(pre).toContain('aria-label="Output"'); | |
| 67 | expect(pre).not.toContain("card"); | |
| 68 | expect(body).toMatch(/pre#nightly-output \{[^}]*overflow-x: auto/); | |
| 69 | }); |