Files
sofa/lib/services/credits.test.ts
T
jakeandClaude Opus 4.6 8a3717cea7 Remove tmdbImageUrl mocks to fix cross-file mock poisoning in CI
bun's mock.module persists across test files in the same process,
causing image.test.ts to receive the stub instead of the real
tmdbImageUrl. Since tmdbImageUrl has no heavy runtime dependencies,
service tests work fine with the real implementation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:51:55 -05:00

90 lines
2.5 KiB
TypeScript

import { beforeEach, describe, expect, mock, test } from "bun:test";
import { persons, titleCast } from "@/lib/db/schema";
import { clearAllTables, insertTitle, testDb } from "@/lib/test-utils";
mock.module("./image-cache", () => ({
imageCacheEnabled: () => false,
cacheProfilePhotos: async () => {},
}));
import { getCastForTitle } from "./credits";
beforeEach(() => {
clearAllTables();
});
function insertPerson(
id: string,
tmdbId: number,
name: string,
profilePath: string | null = null,
) {
testDb.insert(persons).values({ id, tmdbId, name, profilePath }).run();
return id;
}
function insertCastEntry(
titleId: string,
personId: string,
overrides: {
character?: string | null;
department?: string;
job?: string | null;
displayOrder?: number;
episodeCount?: number | null;
} = {},
) {
testDb
.insert(titleCast)
.values({
titleId,
personId,
character: overrides.character ?? "Character",
department: overrides.department ?? "Acting",
job: overrides.job ?? null,
displayOrder: overrides.displayOrder ?? 0,
episodeCount: overrides.episodeCount ?? null,
lastFetchedAt: new Date(),
})
.run();
}
describe("getCastForTitle", () => {
test("returns cast members ordered by displayOrder", () => {
insertTitle({ id: "m1", tmdbId: 1 });
insertPerson("p1", 100, "Actor One", "/path1.jpg");
insertPerson("p2", 200, "Actor Two", "/path2.jpg");
insertCastEntry("m1", "p1", { character: "Hero", displayOrder: 0 });
insertCastEntry("m1", "p2", { character: "Villain", displayOrder: 1 });
const cast = getCastForTitle("m1");
expect(cast).toHaveLength(2);
expect(cast[0].name).toBe("Actor One");
expect(cast[0].character).toBe("Hero");
expect(cast[0].profilePath).toBe("/api/images/profiles/path1.jpg");
expect(cast[1].name).toBe("Actor Two");
});
test("includes crew members", () => {
insertTitle({ id: "m1", tmdbId: 1 });
insertPerson("p1", 100, "Director Person");
insertCastEntry("m1", "p1", {
character: null,
department: "Directing",
job: "Director",
displayOrder: 100,
});
const cast = getCastForTitle("m1");
expect(cast).toHaveLength(1);
expect(cast[0].department).toBe("Directing");
expect(cast[0].job).toBe("Director");
});
test("returns empty array for title with no cast", () => {
insertTitle({ id: "m1", tmdbId: 1 });
const cast = getCastForTitle("m1");
expect(cast).toHaveLength(0);
});
});