From 2d7863d9cc9c05624537f962a0f37c4d152b3f09 Mon Sep 17 00:00:00 2001 From: Julien Calixte Date: Sun, 7 Jun 2026 22:17:23 +0200 Subject: [PATCH] test(db): cover note CRUD, pagination, and webhook helpers --- tests/db_test.ts | 133 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 tests/db_test.ts diff --git a/tests/db_test.ts b/tests/db_test.ts new file mode 100644 index 0000000..1aa666e --- /dev/null +++ b/tests/db_test.ts @@ -0,0 +1,133 @@ +import { assertEquals, assertFalse } from "@std/assert"; +import { + addWebhookSubscription, + deleteWebhookById, + getNotes, + getNotesByDids, + getWebhooksByDidAndVerb, + listWebhooksByDid, + upsertNote, +} from "../src/data/db.ts"; +import { seedNote, seedWebhook, withTestDb } from "./_helpers/db.ts"; + +Deno.test( + "upsertNote inserts then updates on (did, rkey) conflict", + withTestDb(() => { + upsertNote({ + did: "did:plc:user", + rkey: "rkey1", + title: "First", + publishedAt: "2026-01-01T00:00:00.000Z", + createdAt: "2026-01-01T00:00:00.000Z", + }); + upsertNote({ + did: "did:plc:user", + rkey: "rkey1", + title: "Second", + publishedAt: "2026-02-01T00:00:00.000Z", + createdAt: "2026-01-01T00:00:00.000Z", + }); + + const { notes } = getNotes(undefined, 10); + assertEquals(notes.length, 1); + assertEquals(notes[0].title, "Second"); + assertEquals(notes[0].publishedAt, "2026-02-01T00:00:00.000Z"); + }), +); + +Deno.test( + "upsertNote treats undefined discoverable as 1 and false as 0", + withTestDb(() => { + upsertNote({ + did: "did:plc:user", + rkey: "default", + title: "Default", + publishedAt: "2026-01-01T00:00:00.000Z", + createdAt: "2026-01-01T00:00:00.000Z", + }); + upsertNote({ + did: "did:plc:user", + rkey: "hidden", + title: "Hidden", + publishedAt: "2026-01-01T00:00:00.000Z", + createdAt: "2026-01-01T00:00:00.000Z", + discoverable: false, + }); + + const { notes } = getNotes(undefined, 10); + const rkeys = notes.map((n) => n.rkey); + assertEquals(rkeys, ["default"]); + }), +); + +Deno.test( + "getNotes paginates rkey desc and returns cursor only when page is full", + withTestDb(() => { + for (const rkey of ["a", "b", "c", "d", "e"]) { + seedNote({ rkey }); + } + + const firstPage = getNotes(undefined, 3); + assertEquals(firstPage.notes.map((n) => n.rkey), ["e", "d", "c"]); + assertEquals(firstPage.cursor, "c"); + + const secondPage = getNotes(firstPage.cursor, 3); + assertEquals(secondPage.notes.map((n) => n.rkey), ["b", "a"]); + assertEquals(secondPage.cursor, undefined); + }), +); + +Deno.test( + "getNotesByDids returns empty without running SQL on empty did list", + withTestDb(() => { + seedNote({ did: "did:plc:alice", rkey: "a" }); + const result = getNotesByDids([], undefined, 10); + assertEquals(result, { notes: [] }); + }), +); + +Deno.test( + "webhook CRUD: add omits token, list orders desc, delete by id reports hit", + withTestDb(() => { + const created = addWebhookSubscription({ + did: "did:plc:user", + method: "POST", + url: "https://example.com/a", + token: "secret", + verb: "create", + }); + assertEquals(created.token, undefined); + assertEquals(created.url, "https://example.com/a"); + + seedWebhook({ url: "https://example.com/b", verb: "create" }); + seedWebhook({ url: "https://example.com/c", verb: "delete" }); + + const list = listWebhooksByDid("did:plc:user"); + assertEquals(list.length, 3); + const ids = list.map((w) => w.id); + assertEquals(ids, [...ids].sort((a, b) => b - a)); + + assertFalse(deleteWebhookById({ did: "did:plc:user", id: 9999 })); + const deleted = deleteWebhookById({ did: "did:plc:user", id: created.id }); + assertEquals(deleted, true); + assertEquals(listWebhooksByDid("did:plc:user").length, 2); + }), +); + +Deno.test( + "getWebhooksByDidAndVerb filters by verb and caps at 10", + withTestDb(() => { + for (let i = 0; i < 12; i++) { + seedWebhook({ url: `https://example.com/c${i}`, verb: "create" }); + } + seedWebhook({ url: "https://example.com/d", verb: "delete" }); + + const creates = getWebhooksByDidAndVerb("did:plc:test", "create"); + assertEquals(creates.length, 10); + for (const row of creates) assertEquals(row.verb, "create"); + + const deletes = getWebhooksByDidAndVerb("did:plc:test", "delete"); + assertEquals(deletes.length, 1); + assertEquals(deletes[0].verb, "delete"); + }), +);