import { describe, expect, test } from "bun:test"; import type { SubmissionImage } from "../src/core/mangabaka/types"; import type { SourceSeries } from "../src/core/model"; import { SeedError, buildCoverSeed, manualEntryText, withHostedUrls, type CoverChoice } from "../src/core/seed/covers"; import { inspected } from "./helpers/covers"; const series = { language: "en", canonicalUrl: "https://www.webtoons.com/en/fantasy/tower-of-god/list?title_no=95" } as SourceSeries; const old: SubmissionImage = { id: 7193, series_id: 9999, work_id: null, url: "https://example.org/old.jpg", index: "0.1", index_numeric: 0.1, language: "ko", type: "volume", note: "Season Cover 3", content_rating: "safe", is_default: true, }; const choice = (overrides: Partial = {}): CoverChoice => { const cover = inspected(); return { cover, url: cover.candidate.url, type: "volume", note: "WEBTOON poster (current)", contentRating: "safe", ...overrides }; }; const base = { seriesId: 9999, series, sourceName: "WEBTOON", existing: [old] }; describe("buildCoverSeed", () => { test("keeps every existing image and adds the new ones (images replaces the whole set)", () => { const a = choice(); const seed = buildCoverSeed({ ...base, added: [a], makeDefault: null }); expect(seed.userNote).toBe("Add WEBTOON covers from https://www.webtoons.com/en/fantasy/tower-of-god/list?title_no=95"); expect(seed.images).toEqual([old, { id: null, series_id: 9999, work_id: null, url: a.url, index: null, index_numeric: null, language: "en", type: "volume", note: "WEBTOON poster (current)", content_rating: "safe", is_default: false, }]); }); test("a new default takes over: exactly one is_default", () => { const a = choice(); const seed = buildCoverSeed({ ...base, added: [a], makeDefault: { kind: "new", sha256: a.cover.sha256 } }); expect(seed.images.map((i) => i.is_default)).toEqual([false, true]); }); test("an already-present cover can be made the default", () => { const other = { ...old, id: 8000, is_default: false, url: "https://example.org/other.jpg" }; const seed = buildCoverSeed({ ...base, existing: [old, other], added: [choice()], makeDefault: { kind: "existing", id: 8000 } }); expect(seed.images.map((i) => i.is_default)).toEqual([false, true, false]); }); test("a default that was deselected is ignored; existing defaults stay", () => { const seed = buildCoverSeed({ ...base, added: [choice()], makeDefault: { kind: "new", sha256: "0".repeat(64) } }); expect(seed.images.map((i) => i.is_default)).toEqual([true, false]); }); test("refuses a set without exactly one default", () => { expect(() => buildCoverSeed({ ...base, existing: [{ ...old, is_default: false }], added: [choice()], makeDefault: null })) .toThrow(SeedError); }); }); test("withHostedUrls swaps in rehosted URLs for new images only", () => { const a = choice(); const b = choice(); const seed = buildCoverSeed({ ...base, added: [a, b], makeDefault: null }); const hosted = withHostedUrls(seed, new Map([[a.cover.sha256, "https://litter.catbox.moe/abc.jpg"]])); expect(hosted.images.map((i) => i.url)).toEqual([old.url, "https://litter.catbox.moe/abc.jpg", b.url]); expect(hosted.added[0]!.url).toBe("https://litter.catbox.moe/abc.jpg"); }); test("manualEntryText: one block per cover, ready to paste into the form", () => { const a = choice({ url: "https://files.catbox.moe/a.jpg" }); const b = choice({ url: "https://files.catbox.moe/b.png", type: "banner", note: "WEBTOON banner, seen 2019-03", contentRating: "suggestive" }); expect(manualEntryText([a, b], "en", a.cover.sha256)).toBe([ "https://files.catbox.moe/a.jpg", "type: volume · language: en · rating: safe · main cover", "note: WEBTOON poster (current)", "", "https://files.catbox.moe/b.png", "type: banner · language: en · rating: suggestive", "note: WEBTOON banner, seen 2019-03", ].join("\n")); });