Public: anyone can read this; the crew can change it.
A test pins the asks ledger's measure: raised, acted, dismissed and expired since a time, per viewer #6636
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/6625-a-test-pins-the-asks-ledger-s-measure-ra → main 1 commit fork 1 thread · 1 unresolved
1 file
changed +104
−0
test/ask-ledger.test.ts added +104
| @@ -0,0 +1,104 @@ | ||
| 1 | /** | |
| 2 | * The asks ledger's measure (#6625): raised, acted, dismissed and expired | |
| 3 | * since a time, per viewer; and a repository's recent ends, newest first. | |
| 4 | */ | |
| 5 | ||
| 6 | import { beforeEach, describe, expect, test } from "bun:test"; | |
| 7 | import { Database } from "bun:sqlite"; | |
| 8 | import ledgerSql from "../src/core/migrations/0049-the-asks-ledger.ts"; | |
| 9 | import { askMeasure, recentEnds } from "../src/core/ask_ledger.ts"; | |
| 10 | ||
| 11 | let db: Database; | |
| 12 | ||
| 13 | beforeEach(() => { | |
| 14 | db = new Database(":memory:"); | |
| 15 | db.run(ledgerSql); | |
| 16 | }); | |
| 17 | ||
| 18 | let n = 0; | |
| 19 | function row( | |
| 20 | viewer: string, | |
| 21 | raisedAt: string, | |
| 22 | end?: [string, "acted" | "dismissed" | "expired"], | |
| 23 | repo = "r1", | |
| 24 | kind = "review", | |
| 25 | ): void { | |
| 26 | db.run( | |
| 27 | "INSERT INTO ask_ledger (id, viewer_id, ask_id, repo_id, kind, raised_at, ended_at, ended_how) VALUES (?,?,?,?,?,?,?,?)", | |
| 28 | [`row${++n}`, viewer, `ask${n}`, repo, kind, raisedAt, end?.[0] ?? null, end?.[1] ?? null], | |
| 29 | ); | |
| 30 | } | |
| 31 | ||
| 32 | describe("askMeasure", () => { | |
| 33 | test("counts only the asking viewer's rows", () => { | |
| 34 | row("a", "2026-10-10T00:00:00Z", ["2026-10-11T00:00:00Z", "acted"]); | |
| 35 | row("b", "2026-10-10T00:00:00Z", ["2026-10-11T00:00:00Z", "dismissed"]); | |
| 36 | row("b", "2026-10-10T00:00:00Z"); | |
| 37 | expect(askMeasure(db, "a", "2026-10-01T00:00:00Z")).toEqual({ | |
| 38 | raised: 1, | |
| 39 | acted: 1, | |
| 40 | dismissed: 0, | |
| 41 | expired: 0, | |
| 42 | }); | |
| 43 | expect(askMeasure(db, "b", "2026-10-01T00:00:00Z")).toEqual({ | |
| 44 | raised: 2, | |
| 45 | acted: 0, | |
| 46 | dismissed: 1, | |
| 47 | expired: 0, | |
| 48 | }); | |
| 49 | expect(askMeasure(db, "nobody", "2026-10-01T00:00:00Z")).toEqual({ | |
| 50 | raised: 0, | |
| 51 | acted: 0, | |
| 52 | dismissed: 0, | |
| 53 | expired: 0, | |
| 54 | }); | |
| 55 | }); | |
| 56 | ||
| 57 | test("raised counts asks raised at or after since", () => { | |
| 58 | row("a", "2026-10-09T23:59:59Z"); | |
| 59 | row("a", "2026-10-10T00:00:00Z"); | |
| 60 | row("a", "2026-10-11T00:00:00Z"); | |
| 61 | expect(askMeasure(db, "a", "2026-10-10T00:00:00Z").raised).toBe(2); | |
| 62 | }); | |
| 63 | ||
| 64 | test("ends count by when they ended, even if raised before since", () => { | |
| 65 | const old = "2026-09-01T00:00:00Z"; | |
| 66 | row("a", old, ["2026-10-10T00:00:00Z", "acted"]); | |
| 67 | row("a", old, ["2026-10-12T00:00:00Z", "dismissed"]); | |
| 68 | row("a", old, ["2026-10-13T00:00:00Z", "expired"]); | |
| 69 | row("a", old, ["2026-10-09T23:59:59Z", "expired"]); | |
| 70 | expect(askMeasure(db, "a", "2026-10-10T00:00:00Z")).toEqual({ | |
| 71 | raised: 0, | |
| 72 | acted: 1, | |
| 73 | dismissed: 1, | |
| 74 | expired: 1, | |
| 75 | }); | |
| 76 | }); | |
| 77 | ||
| 78 | test("an open ask counts as raised and nothing else", () => { | |
| 79 | row("a", "2026-10-10T00:00:00Z"); | |
| 80 | expect(askMeasure(db, "a", "2026-10-01T00:00:00Z")).toEqual({ | |
| 81 | raised: 1, | |
| 82 | acted: 0, | |
| 83 | dismissed: 0, | |
| 84 | expired: 0, | |
| 85 | }); | |
| 86 | }); | |
| 87 | }); | |
| 88 | ||
| 89 | describe("recentEnds", () => { | |
| 90 | test("lists one repository's ends newest first, for that viewer", () => { | |
| 91 | row("a", "2026-10-01T00:00:00Z", ["2026-10-02T00:00:00Z", "acted"], "r1", "k1"); | |
| 92 | row("a", "2026-10-01T00:00:00Z", ["2026-10-04T00:00:00Z", "expired"], "r1", "k2"); | |
| 93 | row("a", "2026-10-01T00:00:00Z", ["2026-10-03T00:00:00Z", "dismissed"], "r1", "k3"); | |
| 94 | row("a", "2026-10-01T00:00:00Z", ["2026-10-05T00:00:00Z", "acted"], "r2", "other"); | |
| 95 | row("b", "2026-10-01T00:00:00Z", ["2026-10-06T00:00:00Z", "acted"], "r1", "theirs"); | |
| 96 | row("a", "2026-10-01T00:00:00Z", undefined, "r1", "open"); | |
| 97 | expect(recentEnds(db, "a", "r1")).toEqual([ | |
| 98 | { kind: "k2", how: "expired", at: "2026-10-04T00:00:00Z" }, | |
| 99 | { kind: "k3", how: "dismissed", at: "2026-10-03T00:00:00Z" }, | |
| 100 | { kind: "k1", how: "acted", at: "2026-10-02T00:00:00Z" }, | |
| 101 | ]); | |
| 102 | expect(recentEnds(db, "a", "r1", 2).map((e) => e.kind)).toEqual(["k2", "k3"]); | |
| 103 | }); | |
| 104 | }); |
new above
offline
Boundary is pinned for raised (>= since) but not for ended_at. Add an end exactly at
sinceso a switch to > fails. The ids are row1, row2 and so on, so a same-timestamp pair would also pin theid DESCtie-break in recentEnds.