wren/glyph Public Public: anyone can read this; nobody can change it.
forked from apps/glyph
workbenchthis machine
Files acd87b6b6146da11e0c9272c92a02a8e707adf4a
| 1 | import { expect, test } from "bun:test"; |
| 2 | import { mkdtempSync } from "node:fs"; |
| 3 | import { tmpdir } from "node:os"; |
| 4 | import { join } from "node:path"; |
| 5 | import { addNote, deleteNote, listNotes } from "./actions.ts"; |
| 6 | import { openDb } from "./db.ts"; |
| 7 | import type { Who } from "./who.ts"; |
| 8 | |
| 9 | const db = openDb(mkdtempSync(join(tmpdir(), "app-actions-"))); |
| 10 | const anon: Who = { role: "anon" }; |
| 11 | const alice: Who = { role: "user", id: "u1", name: "alice" }; |
| 12 | const bob: Who = { role: "user", id: "u2", name: "bob" }; |
| 13 | const root: Who = { role: "admin", id: "u0", name: "root" }; |
| 14 | |
| 15 | test("anyone reads; only a signed-in person adds, as themselves", () => { |
| 16 | expect(listNotes(db, anon)).toEqual({ ok: true, value: [] }); |
| 17 | const refused = addNote(db, anon, { body: "hello" }); |
| 18 | expect(refused.ok).toBe(false); |
| 19 | if (!refused.ok) expect(refused.error).toBe("signin_required"); |
| 20 | const added = addNote(db, alice, { body: " hello " }); |
| 21 | expect(added.ok).toBe(true); |
| 22 | if (!added.ok) return; |
| 23 | expect(added.value.body).toBe("hello"); |
| 24 | expect(added.value.author_id).toBe("u1"); |
| 25 | expect(added.value.author_name).toBe("alice"); |
| 26 | const all = listNotes(db, anon); |
| 27 | expect(all.ok && all.value.length).toBe(1); |
| 28 | }); |
| 29 | |
| 30 | test("a note is one to five hundred characters", () => { |
| 31 | for (const body of ["", " ", "x".repeat(501)]) { |
| 32 | const r = addNote(db, alice, { body }); |
| 33 | expect(r.ok).toBe(false); |
| 34 | if (!r.ok) expect(r.error).toBe("invalid"); |
| 35 | } |
| 36 | }); |
| 37 | |
| 38 | test("only the author or an admin removes a note", () => { |
| 39 | const mine = addNote(db, alice, { body: "mine" }); |
| 40 | if (!mine.ok) throw new Error(mine.message); |
| 41 | const byBob = deleteNote(db, bob, { id: mine.value.id }); |
| 42 | expect(byBob.ok).toBe(false); |
| 43 | if (!byBob.ok) expect(byBob.error).toBe("forbidden"); |
| 44 | const byAnon = deleteNote(db, anon, { id: mine.value.id }); |
| 45 | expect(byAnon.ok).toBe(false); |
| 46 | if (!byAnon.ok) expect(byAnon.error).toBe("signin_required"); |
| 47 | expect(deleteNote(db, alice, { id: mine.value.id }).ok).toBe(true); |
| 48 | const gone = deleteNote(db, alice, { id: mine.value.id }); |
| 49 | expect(gone.ok).toBe(false); |
| 50 | if (!gone.ok) expect(gone.error).toBe("not_found"); |
| 51 | |
| 52 | const bobs = addNote(db, bob, { body: "bob's" }); |
| 53 | if (!bobs.ok) throw new Error(bobs.message); |
| 54 | expect(deleteNote(db, root, { id: bobs.value.id }).ok).toBe(true); |
| 55 | const odd = deleteNote(db, root, { id: 1.5 }); |
| 56 | expect(odd.ok).toBe(false); |
| 57 | if (!odd.ok) expect(odd.error).toBe("invalid"); |
| 58 | }); |