Files
com.gregkilmer.www/services/site/test/synced.test.ts
Claude e3b0cf60c5 Phase 6: sync jobs, inquiry and order forms
- Sync scheduler in the content service with a per-job cache (sync_cache),
  sync_runs reporting and Healthchecks pings. Jobs: Archidekt, BoardGameGeek,
  cover art (Open Library, TMDB, AniList), Suwayomi and Kavita reading
  progress, Bambuddy filament and Homebox material stock. A note's own value
  always wins over a synced one.
- PersonalReader: updates only Library notes with a matching anilistId,
  changes to Greg's notes are held for review; Reading series with no note
  show as suggestions on the admin Overview.
- /api/inquiries and /api/orders: Turnstile, rate limits, a saved copy in the
  content service (intake token) plus email over SMTP. Orders are re-checked
  against the live notes: accepted only when the category's ordersOpen is
  true and the line has capacity.
- Admin Inbox for saved submissions. Options' inStock is optional so synced
  stock can fill it. All settings from process.env; .env.example per service.
- Sources could not be reached from the build environment; parsers are tested
  against fixtures labelled as not live.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
2026-10-11 23:50:06 +00:00

39 lines
2.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from "vitest";
import { withSynced, type Note } from "../src/lib/content.ts";
import { gamePlayers, gamePlayTime, type Game } from "../src/lib/library.ts";
import { deckArt, deckColors } from "../src/lib/world.ts";
const note = <T extends Note>(type: string, data: Record<string, unknown>, synced?: Record<string, unknown>) =>
({ path: `${type}/x.md`, type, name: "x", slug: "x", title: "X", body: "", acceptedAt: "", data: { type, ...data }, synced }) as unknown as T;
describe("synced values", () => {
it("sit under the note's own values: the note always wins", () => {
const n = withSynced(note("library-item", { cover: "[[mine.jpg]]", title: "X" }, { cover: "https://x/cover.jpg", year: 2006 }));
expect(n.data).toMatchObject({ cover: "[[mine.jpg]]", year: 2006 });
const bare = withSynced(note("library-item", { title: "X" }, { cover: "https://x/cover.jpg" }));
expect((bare.data as { cover?: string }).cover).toBe("https://x/cover.jpg");
});
it("leave a note with nothing synced exactly as it came", () => {
const n = note("board-game", { bggId: 1, blurb: "b" }, {});
expect(withSynced(n)).toBe(n);
const none = note<Game>("board-game", { bggId: 1, blurb: "b" });
expect(withSynced(none)).toBe(none);
expect([gamePlayers(none), gamePlayTime(none)]).toEqual([undefined, undefined]);
expect(deckArt(note("deck", { game: "[[Magic]]" }))).toBeUndefined();
expect(deckColors(note("deck", { game: "[[Magic]]" }))).toEqual([]);
});
it("give the Shelf players and play time, and the decks art and colors", () => {
const g = withSynced(note<Game>("board-game", { bggId: 1, blurb: "b" }, { minPlayers: 1, maxPlayers: 5, playTime: 70, minPlayTime: 40, maxPlayTime: 70 }));
expect([gamePlayers(g), gamePlayTime(g)]).toEqual(["1–5 players", "40–70 min"]);
const solo = withSynced(note<Game>("board-game", { bggId: 1, blurb: "b" }, { minPlayers: 1, maxPlayers: 1, playTime: 30 }));
expect([gamePlayers(solo), gamePlayTime(solo)]).toEqual(["1 player", "30 min"]);
const d = withSynced(note<Note<"deck">>("deck", { game: "[[Magic]]" }, { commanderArt: "https://cards.scryfall.io/a.jpg", colors: ["W", "U", "G"] }));
expect(deckArt(d)).toBe("https://cards.scryfall.io/a.jpg");
expect(deckColors(d)).toEqual(["White", "Blue", "Green"]);
const own = withSynced(note<Note<"deck">>("deck", { game: "[[Magic]]", cover: "[[deck.jpg]]" }, { commanderArt: "https://cards.scryfall.io/a.jpg" }));
expect(deckArt(own)).toBe("/media/deck.jpg");
});
});