Files
STTracker/packages/core/test/suggestions.test.ts
T
Lucas WintherandClaude Opus 5.5 13b81b1cd5 feat(core): entries, user history and match suggestion accept/reject
Entries carry per-field field_sources, write user_history diffs, resolve
aliased/merged works, and support quick add, per-user moves (with alias and
draft tombstone) and keyset-paginated library listing with child rollups.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 19:34:47 +01:00

51 lines
2.3 KiB
TypeScript

import { expect, test } from "bun:test";
import type { Db } from "@sttracker/db/db";
import { newId, nowIso } from "@sttracker/db/ids";
import { forEachDialect } from "@sttracker/db/testing";
import { acceptSuggestion, getEntry, quickAdd, rejectSuggestion } from "../src/entries.ts";
import { NotFoundError } from "../src/errors.ts";
import { makeUser, makeWork } from "./user-layer-fixtures.ts";
async function suggest(db: Db, userId: string, workId: string, candidateWorkId: string): Promise<string> {
const id = newId();
await db.k
.insertInto("match_suggestions")
.values({ id, user_id: userId, work_id: workId, candidate_work_id: candidateWorkId, score: 0.9, status: "pending", created_at: nowIso() })
.execute();
return id;
}
async function statusOf(db: Db, id: string): Promise<string> {
return (await db.k.selectFrom("match_suggestions").select("status").where("id", "=", id).executeTakeFirstOrThrow()).status;
}
forEachDialect("suggestions", (getDb) => {
test("acceptSuggestion moves the entry and rejects the other pending suggestions", async () => {
const db = getDb();
const userId = await makeUser(db);
const draft = await quickAdd(db, userId, { title: "Dune??", mediaType: "book" });
const good = await makeWork(db, { title: "Dune", externalIds: { isbn13: "1" } });
const other = await makeWork(db, { title: "Dune Messiah" });
const s1 = await suggest(db, userId, draft.workId, good);
const s2 = await suggest(db, userId, draft.workId, other);
await acceptSuggestion(db, userId, s1);
expect(await statusOf(db, s1)).toBe("accepted");
expect(await statusOf(db, s2)).toBe("rejected");
const view = await getEntry(db, userId, draft.id);
expect(view.workId).toBe(good);
expect(view.draft).toBe(false);
});
test("rejectSuggestion; other users get NotFoundError", async () => {
const db = getDb();
const ada = await makeUser(db);
const bob = await makeUser(db, "bob");
const s = await suggest(db, ada, await makeWork(db), await makeWork(db));
await expect(acceptSuggestion(db, bob, s)).rejects.toThrow(NotFoundError);
await expect(rejectSuggestion(db, bob, s)).rejects.toThrow(NotFoundError);
expect(await statusOf(db, s)).toBe("pending");
await rejectSuggestion(db, ada, s);
expect(await statusOf(db, s)).toBe("rejected");
});
});