Engagements store partial dates as value + precision and track field_sources; lists (list/grouping/thread, grouping-only rating/review) keep dense item order and snapshot items in history; copies store price in cents. All three restore through restoreVersion. Co-Authored-By: Claude Opus 5.5 <[email protected]>
77 lines
3.8 KiB
TypeScript
77 lines
3.8 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { forEachDialect } from "@sttracker/db/testing";
|
|
import { createCopy, listCopies, softDeleteCopy, updateCopy } from "../src/copies.ts";
|
|
import { defineCustomField } from "../src/custom-fields.ts";
|
|
import { NotFoundError, ValidationError } from "../src/errors.ts";
|
|
import { getHistory, restoreVersion } from "../src/history.ts";
|
|
import { makeUser, makeWork } from "./user-layer-fixtures.ts";
|
|
|
|
forEachDialect("copies", (getDb) => {
|
|
test("createCopy stores price in cents and partial acquired date", async () => {
|
|
const db = getDb();
|
|
const userId = await makeUser(db);
|
|
const workId = await makeWork(db);
|
|
const c = await createCopy(db, userId, {
|
|
workId,
|
|
format: "hardback",
|
|
acquiredFrom: "Waterstones",
|
|
acquiredAt: { value: "2019-03", precision: "month" },
|
|
priceCents: 1299,
|
|
currency: "GBP",
|
|
});
|
|
expect(c.priceCents).toBe(1299);
|
|
expect(c.acquiredAt).toEqual({ value: "2019-03", precision: "month" });
|
|
const row = await db.k.selectFrom("copies").selectAll().where("id", "=", c.id).executeTakeFirstOrThrow();
|
|
expect(row.price_cents).toBe(1299);
|
|
expect(row.acquired_precision).toBe("month");
|
|
|
|
await expect(createCopy(db, userId, { workId, priceCents: 12.5 })).rejects.toThrow(ValidationError);
|
|
await expect(createCopy(db, userId, { workId, currency: "pounds" })).rejects.toThrow(ValidationError);
|
|
await expect(createCopy(db, userId, {})).rejects.toThrow(ValidationError);
|
|
});
|
|
|
|
test("unmatched copy keeps its title hint; listCopies filters by work", async () => {
|
|
const db = getDb();
|
|
const userId = await makeUser(db);
|
|
const workId = await makeWork(db);
|
|
const steam = await createCopy(db, userId, { titleHint: "HALF-LIFE 2", format: "Steam", sourceRef: "steam:220" }, "plugin:steam:c1");
|
|
const book = await createCopy(db, userId, { workId });
|
|
expect(steam.workId).toBeNull();
|
|
expect(steam.titleHint).toBe("HALF-LIFE 2");
|
|
expect((await listCopies(db, userId, {})).map((c) => c.id).sort()).toEqual([steam.id, book.id].sort());
|
|
expect((await listCopies(db, userId, { workId })).map((c) => c.id)).toEqual([book.id]);
|
|
});
|
|
|
|
test("updateCopy writes history; soft delete and restore", async () => {
|
|
const db = getDb();
|
|
const userId = await makeUser(db);
|
|
const def = await defineCustomField(db, userId, { name: "Signed", type: "boolean", level: "copy" });
|
|
const c = await createCopy(db, userId, { workId: await makeWork(db), notes: "shelf 3" });
|
|
const up = await updateCopy(db, userId, c.id, { notes: "shelf 4", customFields: { [def.id]: true } });
|
|
expect(up.notes).toBe("shelf 4");
|
|
expect(up.customFields).toEqual({ [def.id]: true });
|
|
await expect(updateCopy(db, userId, c.id, { customFields: { [def.id]: "yes" } })).rejects.toThrow(ValidationError);
|
|
const [h] = await getHistory(db, userId, "copy", c.id);
|
|
expect(h!.before).toEqual({ notes: "shelf 3", customFields: {} });
|
|
|
|
await softDeleteCopy(db, userId, c.id);
|
|
expect(await listCopies(db, userId, {})).toEqual([]);
|
|
const [del] = await getHistory(db, userId, "copy", c.id);
|
|
await restoreVersion(db, userId, del!.id);
|
|
expect((await listCopies(db, userId, {})).map((x) => x.id)).toEqual([c.id]);
|
|
});
|
|
|
|
test("another user's copies are not found", async () => {
|
|
const db = getDb();
|
|
const ada = await makeUser(db);
|
|
const bob = await makeUser(db, "bob");
|
|
const c = await createCopy(db, ada, { titleHint: "x" });
|
|
await expect(updateCopy(db, bob, c.id, { notes: "y" })).rejects.toThrow(NotFoundError);
|
|
await expect(softDeleteCopy(db, bob, c.id)).rejects.toThrow(NotFoundError);
|
|
expect(await listCopies(db, bob, {})).toEqual([]);
|
|
await expect(createCopy(db, bob, { workId: await makeWork(db, { ownerUserId: ada }) })).rejects.toThrow(
|
|
NotFoundError,
|
|
);
|
|
});
|
|
});
|