import { expect, test } from "bun:test"; import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { addNote, deleteNote, listNotes } from "./actions.ts"; import { openDb } from "./db.ts"; import type { Who } from "./who.ts"; const db = openDb(mkdtempSync(join(tmpdir(), "app-actions-"))); const anon: Who = { role: "anon" }; const alice: Who = { role: "user", id: "u1", name: "alice" }; const bob: Who = { role: "user", id: "u2", name: "bob" }; const root: Who = { role: "admin", id: "u0", name: "root" }; test("anyone reads; only a signed-in person adds, as themselves", () => { expect(listNotes(db, anon)).toEqual({ ok: true, value: [] }); const refused = addNote(db, anon, { body: "hello" }); expect(refused.ok).toBe(false); if (!refused.ok) expect(refused.error).toBe("signin_required"); const added = addNote(db, alice, { body: " hello " }); expect(added.ok).toBe(true); if (!added.ok) return; expect(added.value.body).toBe("hello"); expect(added.value.author_id).toBe("u1"); expect(added.value.author_name).toBe("alice"); const all = listNotes(db, anon); expect(all.ok && all.value.length).toBe(1); }); test("a note is one to five hundred characters", () => { for (const body of ["", " ", "x".repeat(501)]) { const r = addNote(db, alice, { body }); expect(r.ok).toBe(false); if (!r.ok) expect(r.error).toBe("invalid"); } }); test("only the author or an admin removes a note", () => { const mine = addNote(db, alice, { body: "mine" }); if (!mine.ok) throw new Error(mine.message); const byBob = deleteNote(db, bob, { id: mine.value.id }); expect(byBob.ok).toBe(false); if (!byBob.ok) expect(byBob.error).toBe("forbidden"); const byAnon = deleteNote(db, anon, { id: mine.value.id }); expect(byAnon.ok).toBe(false); if (!byAnon.ok) expect(byAnon.error).toBe("signin_required"); expect(deleteNote(db, alice, { id: mine.value.id }).ok).toBe(true); const gone = deleteNote(db, alice, { id: mine.value.id }); expect(gone.ok).toBe(false); if (!gone.ok) expect(gone.error).toBe("not_found"); const bobs = addNote(db, bob, { body: "bob's" }); if (!bobs.ok) throw new Error(bobs.message); expect(deleteNote(db, root, { id: bobs.value.id }).ok).toBe(true); const odd = deleteNote(db, root, { id: 1.5 }); expect(odd.ok).toBe(false); if (!odd.ok) expect(odd.error).toBe("invalid"); });