Files
UHD_Media_Tool/packages/adapters/src/tmdb/episode-groups.test.ts
T

116 lines
4.0 KiB
TypeScript

import { createMockTmdb, type MockTmdb, SPLIT_COUR_FIXTURE, TMDB_FIXTURES } from "@umt/testkit";
import { afterEach, describe, expect, it } from "vitest";
import { createTmdbClient, fetchEpisodeGroup, fetchEpisodeGroups, groupSeasonAsRichSeason } from "./index.ts";
let mock: MockTmdb | null = null;
afterEach(async () => {
await mock?.close();
mock = null;
});
async function setup() {
mock = await createMockTmdb({ fixtures: [...TMDB_FIXTURES, SPLIT_COUR_FIXTURE] });
const tmdb = createTmdbClient({ baseUrl: `${mock.url}/3`, apiKey: "test-tmdb-key", retries: 0, timeoutMs: 1000 });
return { mock, tmdb };
}
describe("TMDB 剧集组", () => {
it("列表:id、名称、类型、组数、集数、播出平台", async () => {
const { tmdb } = await setup();
const groups = await fetchEpisodeGroups(tmdb, 990001, "zh-CN");
expect(groups).toEqual([
{
id: "grp-production",
name: "制作季",
type: 6,
description: null,
groupCount: 2,
episodeCount: 25,
network: "TOKYO MX",
},
{
id: "grp-aired",
name: "播出顺序",
type: 1,
description: null,
groupCount: 1,
episodeCount: 25,
network: null,
},
]);
});
it("详情:组序号 = 季号,组内顺序从 1 编集号,保留 TMDB 默认季集号、标题、播出日期", async () => {
const { tmdb } = await setup();
const g = await fetchEpisodeGroup(tmdb, "grp-production", "zh-CN");
expect(g.name).toBe("制作季");
expect(g.seasons.map((s) => [s.seasonNumber, s.name, s.episodes.length, s.airDate])).toEqual([
[1, "第一部", 12, "2024-01-07"],
[2, "第二部", 13, "2024-07-07"],
]);
const s2e1 = g.seasons[1]!.episodes[0]!;
expect(s2e1).toMatchObject({
seasonNumber: 2,
episodeNumber: 1,
tmdbSeason: 1,
tmdbEpisode: 13,
name: "下篇第1话",
nameLanguage: "zh-CN",
airDate: "2024-07-07",
});
expect(g.seasons[1]!.episodes.at(-1)).toMatchObject({ episodeNumber: 13, tmdbEpisode: 25 });
});
it("组内按 order 排序;重复的组序号顺延;占位名按无标题处理", async () => {
const calls: string[] = [];
const client = {
getJson: async <T>(path: string) => {
calls.push(path);
return {
id: "x",
name: "X",
type: 3,
groups: [
{
id: "b",
name: "B",
order: 1,
episodes: [{ order: 0, season_number: 2, episode_number: 1, name: "Opening", air_date: "2020-01-01" }],
},
{
id: "a",
name: "A",
order: 1,
episodes: [
{ order: 1, season_number: 1, episode_number: 5, name: "第 5 集", air_date: "2019-02-01" },
{ order: 0, season_number: 1, episode_number: 9, name: "Nine", air_date: "2019-01-01" },
],
},
],
} as T;
},
};
const g = await fetchEpisodeGroup(client, "x", "zh-CN");
expect(calls).toEqual(["/tv/episode_group/x"]);
expect(g.seasons.map((s) => [s.seasonNumber, s.name])).toEqual([
[1, "B"],
[2, "A"],
]);
expect(g.seasons[1]!.episodes.map((e) => [e.episodeNumber, e.tmdbSeason, e.tmdbEpisode, e.name])).toEqual([
[1, 1, 9, "Nine"],
[2, 1, 5, null],
]);
const rich = groupSeasonAsRichSeason(42, g.seasons[1]!, "zh-CN", "/p.jpg");
expect(rich).toMatchObject({ tvId: "42", seasonNumber: 2, name: "A", posterPath: "/p.jpg", airDate: "2019-01-01" });
});
it("剧集组不存在抛 notfound;请求走缓存", async () => {
const { tmdb, mock } = await setup();
await expect(fetchEpisodeGroup(tmdb, "nope")).rejects.toMatchObject({ kind: "notfound" });
await fetchEpisodeGroups(tmdb, 990001, "zh-CN");
const before = mock.calls.length;
await fetchEpisodeGroups(tmdb, 990001, "zh-CN");
expect(mock.calls.length).toBe(before);
});
});