Public: anyone can read this; the crew can change it.
A test pins that a thought is read back only by its author: newest first, `since` respected, text exactly as kept #6728
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/6715-a-test-pins-that-a-thought-is-read-back → main 1 commit fork
1 file
changed +50
−0
test/thoughts-read.test.ts added +50
| @@ -0,0 +1,50 @@ | ||
| 1 | import { beforeEach, describe, expect, test } from "bun:test"; | |
| 2 | import { Database } from "bun:sqlite"; | |
| 3 | import migration from "../src/core/migrations/0081-thoughts.ts"; | |
| 4 | import { recentThoughts, thoughtOf } from "../src/core/thoughts.ts"; | |
| 5 | ||
| 6 | let db: Database; | |
| 7 | ||
| 8 | function keep(id: string, author: string, text: string, receivedAt: string): void { | |
| 9 | db.query("INSERT INTO thought (id, author, text, source, received_at) VALUES (?1, ?2, ?3, 'api', ?4)").run( | |
| 10 | id, | |
| 11 | author, | |
| 12 | text, | |
| 13 | receivedAt, | |
| 14 | ); | |
| 15 | } | |
| 16 | ||
| 17 | beforeEach(() => { | |
| 18 | db = new Database(":memory:"); | |
| 19 | db.exec(migration); | |
| 20 | }); | |
| 21 | ||
| 22 | describe("reading thoughts back", () => { | |
| 23 | test("newest first, cut at limit, and only at or after since", () => { | |
| 24 | keep("t1", "ann", "one", "2026-01-01T00:00:01.000Z"); | |
| 25 | keep("t2", "ann", "two", "2026-01-01T00:00:02.000Z"); | |
| 26 | keep("t3", "ann", "three", "2026-01-01T00:00:03.000Z"); | |
| 27 | keep("t4", "ann", "four", "2026-01-01T00:00:04.000Z"); | |
| 28 | expect(recentThoughts(db, "ann", 10).map((t) => t.id)).toEqual(["t4", "t3", "t2", "t1"]); | |
| 29 | expect(recentThoughts(db, "ann", 2).map((t) => t.id)).toEqual(["t4", "t3"]); | |
| 30 | expect(recentThoughts(db, "ann", 10, "2026-01-01T00:00:03.000Z").map((t) => t.id)).toEqual(["t4", "t3"]); | |
| 31 | expect(recentThoughts(db, "ann", 10, "2027-01-01T00:00:00.000Z")).toEqual([]); | |
| 32 | }); | |
| 33 | ||
| 34 | test("another person gets none of them, and thoughtOf with the wrong author is undefined", () => { | |
| 35 | keep("t1", "ann", "mine", "2026-01-01T00:00:01.000Z"); | |
| 36 | keep("t2", "bob", "his", "2026-01-01T00:00:02.000Z"); | |
| 37 | expect(recentThoughts(db, "bob", 10).map((t) => t.id)).toEqual(["t2"]); | |
| 38 | expect(recentThoughts(db, "cy", 10)).toEqual([]); | |
| 39 | expect(thoughtOf(db, "bob", "t1")).toBeUndefined(); | |
| 40 | expect(thoughtOf(db, "ann", "t1")?.text).toBe("mine"); | |
| 41 | expect(thoughtOf(db, "ann", "nope")).toBeUndefined(); | |
| 42 | }); | |
| 43 | ||
| 44 | test("text with markup, emoji and newlines comes back byte for byte", () => { | |
| 45 | const text = " <script>alert(\"x\")</script> & 🚀 é\r\nline two\n\n\ttabbed "; | |
| 46 | keep("t1", "ann", text, "2026-01-01T00:00:01.000Z"); | |
| 47 | expect(recentThoughts(db, "ann", 1)[0]!.text).toBe(text); | |
| 48 | expect(thoughtOf(db, "ann", "t1")!.text).toBe(text); | |
| 49 | }); | |
| 50 | }); |
new above
offline