75 lines
3.7 KiB
TypeScript
75 lines
3.7 KiB
TypeScript
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);
|
||
});
|
||
});
|