Add tests for video linking

This commit is contained in:
2025-06-06 13:16:11 +02:00
parent 6e2743a4be
commit 489336c77a
8 changed files with 164 additions and 38 deletions
+5 -2
View File
@@ -515,10 +515,13 @@ export const videosH = new Elysia({ prefix: "/videos", tags: ["videos"] })
201: t.Array(
t.Object({
id: t.String({ format: "uuid" }),
path: t.String(),
path: t.String({ examples: ["/video/made in abyss s1e13.mkv"] }),
entries: t.Array(
t.Object({
slug: t.String({ format: "slug" }),
slug: t.String({
format: "slug",
examples: ["made-in-abyss-s1e13"],
}),
}),
),
}),
+1 -1
View File
@@ -58,7 +58,7 @@ export const toDrizzle = (expr: Expression, config: FilterDef): SQL => {
{ in: where },
);
}
expr.value = { type: "bool", value: expr.value.value === "true" }
expr.value = { type: "bool", value: expr.value.value === "true" };
}
if (prop.type !== expr.value.type) {
throw new KErrorT(
+17
View File
@@ -43,3 +43,20 @@ export const deleteVideo = async (paths: string[]) => {
const body = await resp.json();
return [resp, body] as const;
};
export const linkVideos = async (
links: { id: string; for: SeedVideo["for"] }[],
) => {
const resp = await handlers.handle(
new Request(buildUrl("videos/link"), {
method: "POST",
body: JSON.stringify(links),
headers: {
"Content-Type": "application/json",
...(await getJwtHeaders()),
},
}),
);
const body = await resp.json();
return [resp, body] as const;
};
+19 -10
View File
@@ -9,6 +9,7 @@ let bubbleId = "";
beforeAll(async () => {
await db.delete(shows);
await db.delete(videos);
await db.insert(videos).values(bubbleVideo);
const [ret, body] = await createMovie(bubble);
expect(ret.status).toBe(201);
@@ -66,21 +67,29 @@ describe("Get movie", () => {
const [resp, body] = await getMovie(bubble.slug, { langs: "fr,pr,*" });
expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({
slug: bubble.slug,
name: bubble.translations.en.name,
});
expect(resp.headers.get("Content-Language")).toBe("en");
expect(body.slug).toBe(bubble.slug);
const lang = resp.headers.get("Content-Language");
if (lang === "en") {
expect(body.name).toBe(bubble.translations.en.name);
} else if (lang === "ja") {
expect(body.name).toBe(bubble.translations.ja.name);
} else {
expect(lang).toBe("en");
}
});
it("Works without accept-language header", async () => {
const [resp, body] = await getMovie(bubble.slug, { langs: undefined });
expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({
slug: bubble.slug,
name: bubble.translations.en.name,
});
expect(resp.headers.get("Content-Language")).toBe("en");
expect(body.slug).toBe(bubble.slug);
const lang = resp.headers.get("Content-Language");
if (lang === "en") {
expect(body.name).toBe(bubble.translations.en.name);
} else if (lang === "ja") {
expect(body.name).toBe(bubble.translations.ja.name);
} else {
expect(lang).toBe("en");
}
});
it("Fallback if translations does not exist", async () => {
const [resp, body] = await getMovie(bubble.slug, { langs: "en-au" });
+96 -4
View File
@@ -6,10 +6,11 @@ import {
createVideo,
deleteVideo,
getVideos,
linkVideos,
} from "tests/helpers";
import { expectStatus } from "tests/utils";
import { db } from "~/db";
import { entries, shows, videos } from "~/db/schema";
import { entries, entryVideoJoin, shows, videos } from "~/db/schema";
import { bubble, madeInAbyss } from "~/models/examples";
beforeAll(async () => {
@@ -57,12 +58,35 @@ beforeAll(async () => {
version: 1,
for: [{ movie: bubble.slug }],
},
{
guess: {
title: "mia",
episodes: [{ season: 1, episode: 1 }], // Different episode for unlinked
from: "test",
history: [],
},
part: null,
path: "/video/mia-unlinked.mkv",
rendering: "sha-unlinked-1",
version: 1,
// No 'for' initially
},
{
guess: { title: "bubble", from: "test", history: [] },
part: null,
path: "/video/bubble-unlinked.mkv",
rendering: "sha-unlinked-2",
version: 1,
// No 'for' initially
},
]);
expectStatus(ret, body).toBe(201);
expect(body).toBeArrayOfSize(3);
expect(body).toBeArrayOfSize(5);
expect(body[0].entries).toBeArrayOfSize(1);
expect(body[1].entries).toBeArrayOfSize(1);
expect(body[2].entries).toBeArrayOfSize(1);
expect(body[3].entries).toBeArrayOfSize(0); // Unlinked
expect(body[4].entries).toBeArrayOfSize(0); // Unlinked
const items = await db.query.shows.findMany();
expect(items.find((x) => x.slug === "bubble")!.availableCount).toBe(1);
@@ -141,8 +165,10 @@ describe("Video get/deletion", () => {
},
},
});
expect(body.unmatched).toBeArrayOfSize(1);
expect(body.unmatched[0]).toBe("/video/mia s1e13 unknown test.mkv");
expect(body.unmatched).toBeArrayOfSize(3);
expect(body.unmatched).toContain("/video/mia s1e13 unknown test.mkv");
expect(body.unmatched).toContain("/video/mia-unlinked.mkv");
expect(body.unmatched).toContain("/video/bubble-unlinked.mkv");
});
it("Mismatch title guess", async () => {
@@ -249,3 +275,69 @@ describe("Video get/deletion", () => {
expect(body[0]).toBe("/video/mia s1e13 unknown test.mkv");
});
});
describe("Video linking", () => {
it("Should link videos to entries", async () => {
const allVideos = await db
.select({
id: videos.id,
path: videos.path,
rendering: videos.rendering,
})
.from(videos);
const miaUnlinkedVideo = allVideos.find(
(v) => v.rendering === "sha-unlinked-1",
);
const bubbleUnlinkedVideo = allVideos.find(
(v) => v.rendering === "sha-unlinked-2",
);
expect(miaUnlinkedVideo).toBeDefined();
expect(bubbleUnlinkedVideo).toBeDefined();
const [resp, body] = await linkVideos([
{
id: miaUnlinkedVideo!.id,
for: [{ slug: `${madeInAbyss.slug}-s1e13` }],
},
{
id: bubbleUnlinkedVideo!.id,
for: [{ movie: bubble.slug }],
},
]);
expectStatus(resp, body).toBe(201);
expect(body).toBeArrayOfSize(2);
expect(body[0]).toMatchObject({
id: miaUnlinkedVideo!.id,
path: "/video/mia-unlinked.mkv",
entries: [
{
slug: expect.stringContaining(`${madeInAbyss.slug}-s1e13`),
},
],
});
expect(body[1]).toMatchObject({
id: bubbleUnlinkedVideo!.id,
path: "/video/bubble-unlinked.mkv",
entries: [
{
slug: expect.stringContaining(bubble.slug),
},
],
});
const miaShow = await db.query.shows.findFirst({
where: eq(shows.slug, madeInAbyss.slug),
});
expect(miaShow!.availableCount).toBe(1);
const bubbleShow = await db.query.shows.findFirst({
where: eq(shows.slug, bubble.slug),
});
expect(bubbleShow!.availableCount).toBe(1);
});
});