Public: anyone can read this; the crew can change it.
A failed check's one-line summary names up to three failing tests and how many more, not only the first #6275
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/6271-a-failed-check-s-one-line-summary-names → main 1 commit fork
2 files
changed +36
−3
src/checks/summary.ts +12 −2
| @@ -55,9 +55,19 @@ export function summariseCheckFailure( | ||
| 55 | 55 | const detail = parseBunTestFailure(lines); |
| 56 | 56 | if (detail !== undefined) { |
| 57 | 57 | const total = detail.passed + detail.failed; |
| 58 | const name = detail.names[0] ?? ""; | |
| 58 | const names = [...new Set(detail.names)].slice(0, 3); | |
| 59 | const quoted = names.map((n) => `"${n}"`); | |
| 60 | const more = detail.failed - names.length; | |
| 61 | const list = | |
| 62 | names.length === 0 | |
| 63 | ? '""' | |
| 64 | : more > 0 | |
| 65 | ? `${quoted.join(", ")} and ${more} more` | |
| 66 | : quoted.length > 1 | |
| 67 | ? `${quoted.slice(0, -1).join(", ")} and ${quoted.at(-1)}` | |
| 68 | : quoted[0]!; | |
| 59 | 69 | return { |
| 60 | summary: truncate(`${detail.failed} of ${total} tests — "${name}"`), | |
| 70 | summary: truncate(`${detail.failed} of ${total} tests — ${list}`), | |
| 61 | 71 | detail, |
| 62 | 72 | }; |
| 63 | 73 | } |
test/checks.test.ts +24 −1
| @@ -230,6 +230,29 @@ describe("summariseCheckFailure: what a failed check's summary says first", () = | ||
| 230 | 230 | }); |
| 231 | 231 | }); |
| 232 | 232 | |
| 233 | const failing = (n: number) => [ | |
| 234 | ...Array.from({ length: n }, (_, i) => `(fail) t${i + 1} [1.00ms]`), | |
| 235 | " 5 pass", | |
| 236 | ` ${n} fail`, | |
| 237 | ]; | |
| 238 | ||
| 239 | test("three failures name all three; five name three and how many more", () => { | |
| 240 | expect(summariseCheckFailure(failing(3), "x").summary).toBe( | |
| 241 | '3 of 8 tests — "t1", "t2" and "t3"', | |
| 242 | ); | |
| 243 | expect(summariseCheckFailure(failing(5), "x").summary).toBe( | |
| 244 | '5 of 10 tests — "t1", "t2", "t3" and 2 more', | |
| 245 | ); | |
| 246 | }); | |
| 247 | ||
| 248 | test("a name list longer than the limit is still bounded to one line", () => { | |
| 249 | const long = "y".repeat(100); | |
| 250 | const lines = ["a", "b", "c", "d"].map((c) => `(fail) ${c}${long} [1.00ms]`); | |
| 251 | const { summary } = summariseCheckFailure([...lines, " 0 pass", " 4 fail"], "x"); | |
| 252 | expect(summary.length).toBe(200); | |
| 253 | expect(summary.endsWith("…")).toBe(true); | |
| 254 | }); | |
| 255 | ||
| 233 | 256 | test("a very long name is bounded to one line", () => { |
| 234 | 257 | const long = "x".repeat(500); |
| 235 | 258 | const lines = [`(fail) ${long} [1.00ms]`, " 0 pass", " 1 fail"]; |
| @@ -549,7 +572,7 @@ describe("checks", () => { | ||
| 549 | 572 | names: ["first failing test", "second failing test"], |
| 550 | 573 | }); |
| 551 | 574 | expect(failed.summary).toBe( |
| 552 | 'check failed: 2 of 3 tests — "first failing test"', | |
| 575 | 'check failed: 2 of 3 tests — "first failing test" and "second failing test"', | |
| 553 | 576 | ); |
| 554 | 577 | }, 30_000); |
| 555 | 578 |
new above
offline