import { describe, expect, test } from "bun:test"; import { coverNote, dedupeByHash, mergeByUrl, pickDefault, splitExisting } from "../src/core/covers"; import { inspected } from "./helpers/covers"; describe("mergeByUrl", () => { test("merges current and historical sightings of one URL", () => { const url = "https://swebtoon-phinf.pstatic.net/a.jpg"; const merged = mergeByUrl([ { url, role: "poster", current: false, seenAt: "20190301000000", lastSeenAt: "20190301000000", archivedUrl: "A" }, { url, role: "poster", current: true }, { url, role: "poster", current: false, seenAt: "20210101000000", lastSeenAt: "20210101000000", archivedUrl: "B" }, { url: "https://swebtoon-phinf.pstatic.net/b.jpg", role: "banner", current: true }, ]); expect(merged).toHaveLength(2); expect(merged[0]).toEqual({ url, role: "poster", current: true, seenAt: "20190301000000", lastSeenAt: "20210101000000", archivedUrl: "A", }); }); }); describe("dedupeByHash", () => { test("same bytes under two URLs become one cover; the live, current one is kept", () => { const sha = "f".repeat(64); const archivedOnly = inspected({ sha256: sha, live: false, candidate: { url: "https://x/old.jpg", current: false, seenAt: "20150101000000" } }); const current = inspected({ sha256: sha, candidate: { url: "https://x/new.jpg", current: true } }); const out = dedupeByHash([archivedOnly, current]); expect(out).toHaveLength(1); expect(out[0]!.candidate).toMatchObject({ url: "https://x/new.jpg", current: true, seenAt: "20150101000000" }); expect(out[0]!.live).toBe(true); }); }); test("splitExisting drops what MangaBaka already has, by sha256", () => { const a = inspected(); const b = inspected(); const { fresh, present } = splitExisting([a, b], [ { id: 7193, sha256: b.sha256.toUpperCase(), language: "en", type: "volume" }, { id: 1, sha256: null, language: "ko", type: "volume" }, ]); expect(fresh).toEqual([a]); expect(present).toEqual([{ cover: b, existing: { id: 7193, sha256: b.sha256.toUpperCase(), language: "en", type: "volume" } }]); }); describe("pickDefault", () => { test("current live poster", () => { const square = inspected({ candidate: { role: "square" }, shape: "square" }); const poster = inspected({ candidate: { role: "poster" } }); expect(pickDefault([square, poster])).toBe(poster); }); test("canvas: current live square when there is no poster", () => { const square = inspected({ candidate: { role: "square" }, shape: "square" }); expect(pickDefault([square])).toBe(square); }); test("never landing-page art, a historical cover, or an archive-only copy", () => { expect(pickDefault([ inspected({ shape: "tall" }), inspected({ candidate: { current: false } }), inspected({ live: false }), ])).toBeNull(); }); }); describe("coverNote", () => { test.each([ [{ current: true }, "portrait", "WEBTOON poster (current)"], [{ current: false, seenAt: "20190318000000", lastSeenAt: "20210127000000" }, "portrait", "WEBTOON poster, seen 2019-03 – 2021-01"], [{ current: false, seenAt: "20190318000000", lastSeenAt: "20190330000000" }, "portrait", "WEBTOON poster, seen 2019-03"], [{ current: true, seenAt: "20230401000000" }, "portrait", "WEBTOON poster (current; archived since 2023-04)"], [{ current: false, seenAt: "20230401000000", role: "poster" as const }, "tall", "WEBTOON poster (landing-page art), seen 2023-04"], [{ current: true, role: "foreground" as const }, "wide", "WEBTOON foreground art (current)"], ] as const)("%o", (candidate, shape, note) => { expect(coverNote(inspected({ candidate, shape }), "WEBTOON")).toBe(note); }); });