mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-31 20:24:27 -04:00
Fix 404 handling for entries
This commit is contained in:
parent
fb7635ef56
commit
4ee6493eb8
@ -74,37 +74,21 @@ const extraSort = Sort(["slug", "name", "runtime", "createdAt"], {
|
|||||||
default: ["slug"],
|
default: ["slug"],
|
||||||
});
|
});
|
||||||
|
|
||||||
async function getEntries(
|
async function getEntries({
|
||||||
serie: string | null,
|
after,
|
||||||
{
|
limit,
|
||||||
after,
|
query,
|
||||||
limit,
|
sort,
|
||||||
query,
|
filter,
|
||||||
sort,
|
languages,
|
||||||
filter,
|
}: {
|
||||||
languages,
|
after: string | undefined;
|
||||||
}: {
|
limit: number;
|
||||||
after: string | undefined;
|
query: string | undefined;
|
||||||
limit: number;
|
sort: StaticDecode<typeof entrySort>;
|
||||||
query: string | undefined;
|
filter: SQL | undefined;
|
||||||
sort: StaticDecode<typeof entrySort>;
|
languages: string[];
|
||||||
filter: SQL | undefined;
|
}): Promise<(Entry | Extra | UnknownEntry)[]> {
|
||||||
languages: string[];
|
|
||||||
},
|
|
||||||
): Promise<(Entry | Extra | UnknownEntry)[]> {
|
|
||||||
const show = db.$with("serie").as(
|
|
||||||
db
|
|
||||||
.select({ pk: shows.pk })
|
|
||||||
.from(shows)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(shows.kind, "serie"),
|
|
||||||
isUuid(serie!) ? eq(shows.id, serie!) : eq(shows.slug, serie!),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.limit(1),
|
|
||||||
);
|
|
||||||
|
|
||||||
const transQ = db
|
const transQ = db
|
||||||
.selectDistinctOn([entryTranslations.pk])
|
.selectDistinctOn([entryTranslations.pk])
|
||||||
.from(entryTranslations)
|
.from(entryTranslations)
|
||||||
@ -125,7 +109,6 @@ async function getEntries(
|
|||||||
...entryCol
|
...entryCol
|
||||||
} = getColumns(entries);
|
} = getColumns(entries);
|
||||||
return await db
|
return await db
|
||||||
.with(...(serie ? [show] : []))
|
|
||||||
.select({
|
.select({
|
||||||
...entryCol,
|
...entryCol,
|
||||||
...transCol,
|
...transCol,
|
||||||
@ -133,10 +116,10 @@ async function getEntries(
|
|||||||
number: sql<number>`${episodeNumber}`.as("order"),
|
number: sql<number>`${episodeNumber}`.as("order"),
|
||||||
|
|
||||||
// merge `extraKind` into `kind`
|
// merge `extraKind` into `kind`
|
||||||
kind: sql<EntryKind>`case when ${kind} = 'extra' then ${extraKind} else ${kind} end`.as(
|
kind: sql<EntryKind>`case when ${kind} = 'extra' then ${extraKind} else ${kind}::text end`.as(
|
||||||
"kind",
|
"kind",
|
||||||
),
|
),
|
||||||
isExtra: sql<boolean>`${kind} = "extra"`.as("isExtra"),
|
isExtra: sql<boolean>`${kind} = 'extra'`.as("isExtra"),
|
||||||
|
|
||||||
// assign more restrained types to make typescript happy.
|
// assign more restrained types to make typescript happy.
|
||||||
externalId: sql<any>`${externalId}`.as("externalId"),
|
externalId: sql<any>`${externalId}`.as("externalId"),
|
||||||
@ -149,7 +132,6 @@ async function getEntries(
|
|||||||
.innerJoin(transQ, eq(entries.pk, transQ.pk))
|
.innerJoin(transQ, eq(entries.pk, transQ.pk))
|
||||||
.where(
|
.where(
|
||||||
and(
|
and(
|
||||||
serie ? eq(entries.showPk, show.pk) : undefined,
|
|
||||||
filter,
|
filter,
|
||||||
query ? sql`${transQ.name} %> ${query}::text` : undefined,
|
query ? sql`${transQ.name} %> ${query}::text` : undefined,
|
||||||
keysetPaginate({ table: entries, after, sort }),
|
keysetPaginate({ table: entries, after, sort }),
|
||||||
@ -184,14 +166,34 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
|||||||
query: { limit, after, query, sort, filter },
|
query: { limit, after, query, sort, filter },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages },
|
||||||
request: { url },
|
request: { url },
|
||||||
|
error,
|
||||||
}) => {
|
}) => {
|
||||||
|
const [serie] = await db
|
||||||
|
.select({ pk: shows.pk })
|
||||||
|
.from(shows)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(shows.kind, "serie"),
|
||||||
|
isUuid(id) ? eq(shows.id, id) : eq(shows.slug, id),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (!serie) {
|
||||||
|
return error(404, {
|
||||||
|
status: 404,
|
||||||
|
message: `No serie with the id or slug: '${id}'.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const langs = processLanguages(languages);
|
const langs = processLanguages(languages);
|
||||||
const items = (await getEntries(id, {
|
const items = (await getEntries({
|
||||||
limit,
|
limit,
|
||||||
after,
|
after,
|
||||||
query,
|
query,
|
||||||
sort,
|
sort,
|
||||||
filter: and(
|
filter: and(
|
||||||
|
eq(entries.showPk, serie.pk),
|
||||||
ne(entries.kind, "extra"),
|
ne(entries.kind, "extra"),
|
||||||
ne(entries.kind, "unknown"),
|
ne(entries.kind, "unknown"),
|
||||||
filter,
|
filter,
|
||||||
@ -226,6 +228,10 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: Page(Entry),
|
200: Page(Entry),
|
||||||
|
404: {
|
||||||
|
...KError,
|
||||||
|
description: "No serie found with the given id or slug.",
|
||||||
|
},
|
||||||
422: KError,
|
422: KError,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -236,13 +242,36 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
|||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter },
|
query: { limit, after, query, sort, filter },
|
||||||
request: { url },
|
request: { url },
|
||||||
|
error,
|
||||||
}) => {
|
}) => {
|
||||||
const items = (await getEntries(id, {
|
const [serie] = await db
|
||||||
|
.select({ pk: shows.pk })
|
||||||
|
.from(shows)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(shows.kind, "serie"),
|
||||||
|
isUuid(id) ? eq(shows.id, id) : eq(shows.slug, id),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (!serie) {
|
||||||
|
return error(404, {
|
||||||
|
status: 404,
|
||||||
|
message: `No serie with the id or slug: '${id}'.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = (await getEntries({
|
||||||
limit,
|
limit,
|
||||||
after,
|
after,
|
||||||
query,
|
query,
|
||||||
sort: sort as any,
|
sort: sort as any,
|
||||||
filter: and(eq(entries.kind, "extra"), filter),
|
filter: and(
|
||||||
|
eq(entries.showPk, serie.pk),
|
||||||
|
eq(entries.kind, "extra"),
|
||||||
|
filter,
|
||||||
|
),
|
||||||
languages: ["extra"],
|
languages: ["extra"],
|
||||||
})) as Extra[];
|
})) as Extra[];
|
||||||
|
|
||||||
@ -270,6 +299,10 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: Page(Extra),
|
200: Page(Extra),
|
||||||
|
404: {
|
||||||
|
...KError,
|
||||||
|
description: "No serie found with the given id or slug.",
|
||||||
|
},
|
||||||
422: KError,
|
422: KError,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -280,7 +313,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
|||||||
query: { limit, after, query, sort, filter },
|
query: { limit, after, query, sort, filter },
|
||||||
request: { url },
|
request: { url },
|
||||||
}) => {
|
}) => {
|
||||||
const items = (await getEntries(null, {
|
const items = (await getEntries({
|
||||||
limit,
|
limit,
|
||||||
after,
|
after,
|
||||||
query,
|
query,
|
||||||
|
30
api/tests/entries/get-entries.test.ts
Normal file
30
api/tests/entries/get-entries.test.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { beforeAll, describe, expect, it } from "bun:test";
|
||||||
|
import { getEntries } from "tests/helpers";
|
||||||
|
import { expectStatus } from "tests/utils";
|
||||||
|
import { seedSerie } from "~/controllers/seed/series";
|
||||||
|
import { madeInAbyss } from "~/models/examples";
|
||||||
|
|
||||||
|
let miaId = "";
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const ret = await seedSerie(madeInAbyss);
|
||||||
|
if (!("status" in ret)) miaId = ret.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Get entries", () => {
|
||||||
|
it("Invalid slug", async () => {
|
||||||
|
const [resp, body] = await getEntries("sotneuhn", { langs: "en" });
|
||||||
|
|
||||||
|
expectStatus(resp, body).toBe(404);
|
||||||
|
expect(body).toMatchObject({
|
||||||
|
status: 404,
|
||||||
|
message: expect.any(String),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Default sort order", async () => {
|
||||||
|
const [resp, body] = await getEntries(madeInAbyss.slug, { langs: "en" });
|
||||||
|
|
||||||
|
expectStatus(resp, body).toBe(200);
|
||||||
|
expect(body.items).toBeArrayOfSize(madeInAbyss.entries.length);
|
||||||
|
});
|
||||||
|
});
|
@ -1,413 +0,0 @@
|
|||||||
import { beforeAll, describe, expect, it } from "bun:test";
|
|
||||||
import { eq } from "drizzle-orm";
|
|
||||||
import { expectStatus } from "tests/utils";
|
|
||||||
import { db } from "~/db";
|
|
||||||
import { showTranslations, shows, videos } from "~/db/schema";
|
|
||||||
import { bubble } from "~/models/examples";
|
|
||||||
import { dune, duneVideo } from "~/models/examples/dune-2021";
|
|
||||||
import { createMovie, createVideo } from "../helpers";
|
|
||||||
|
|
||||||
describe("Movie seeding", () => {
|
|
||||||
it("Can create a movie", async () => {
|
|
||||||
// create video beforehand to test linking
|
|
||||||
await db.insert(videos).values(duneVideo);
|
|
||||||
|
|
||||||
const [resp, body] = await createMovie(dune);
|
|
||||||
expectStatus(resp, body).toBe(201);
|
|
||||||
expect(body.id).toBeString();
|
|
||||||
expect(body.slug).toBe("dune");
|
|
||||||
expect(body.videos).toContainEqual({ slug: "dune" });
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Update existing movie", async () => {
|
|
||||||
// confirm that db is in the correct state (from previous tests)
|
|
||||||
const [existing] = await db
|
|
||||||
.select()
|
|
||||||
.from(shows)
|
|
||||||
.where(eq(shows.slug, dune.slug))
|
|
||||||
.limit(1);
|
|
||||||
expect(existing).toMatchObject({ slug: dune.slug, startAir: dune.airDate });
|
|
||||||
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
...dune,
|
|
||||||
runtime: 200_000,
|
|
||||||
translations: {
|
|
||||||
...dune.translations,
|
|
||||||
en: { ...dune.translations.en, description: "edited translation" },
|
|
||||||
fr: {
|
|
||||||
name: "dune-but-in-french",
|
|
||||||
description: null,
|
|
||||||
tagline: null,
|
|
||||||
aliases: [],
|
|
||||||
tags: [],
|
|
||||||
poster: null,
|
|
||||||
thumbnail: null,
|
|
||||||
banner: null,
|
|
||||||
logo: null,
|
|
||||||
trailerUrl: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const [edited] = await db
|
|
||||||
.select()
|
|
||||||
.from(shows)
|
|
||||||
.where(eq(shows.slug, dune.slug))
|
|
||||||
.limit(1);
|
|
||||||
const translations = await db
|
|
||||||
.select()
|
|
||||||
.from(showTranslations)
|
|
||||||
.where(eq(showTranslations.pk, edited.pk));
|
|
||||||
|
|
||||||
expectStatus(resp, body).toBe(200);
|
|
||||||
expect(body.id).toBeString();
|
|
||||||
expect(body.slug).toBe("dune");
|
|
||||||
expect(body.videos).toBeArrayOfSize(0);
|
|
||||||
expect(edited.runtime).toBe(200_000);
|
|
||||||
expect(edited.status).toBe(dune.status);
|
|
||||||
expect(translations.find((x) => x.language === "en")).toMatchObject({
|
|
||||||
name: dune.translations.en.name,
|
|
||||||
description: "edited translation",
|
|
||||||
});
|
|
||||||
expect(translations.find((x) => x.language === "fr")).toMatchObject({
|
|
||||||
name: "dune-but-in-french",
|
|
||||||
description: null,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Conflicting slug auto-correct", async () => {
|
|
||||||
// confirm that db is in the correct state (from previous tests)
|
|
||||||
const [existing] = await db
|
|
||||||
.select()
|
|
||||||
.from(shows)
|
|
||||||
.where(eq(shows.slug, dune.slug))
|
|
||||||
.limit(1);
|
|
||||||
expect(existing).toMatchObject({ slug: dune.slug, startAir: dune.airDate });
|
|
||||||
|
|
||||||
const [resp, body] = await createMovie({ ...dune, airDate: "2158-12-13" });
|
|
||||||
expectStatus(resp, body).toBe(201);
|
|
||||||
expect(body.id).toBeString();
|
|
||||||
expect(body.slug).toBe("dune-2158");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Conflict in slug w/out year fails", async () => {
|
|
||||||
// confirm that db is in the correct state (from conflict auto-correct test)
|
|
||||||
const [existing] = await db
|
|
||||||
.select()
|
|
||||||
.from(shows)
|
|
||||||
.where(eq(shows.slug, dune.slug))
|
|
||||||
.limit(1);
|
|
||||||
expect(existing).toMatchObject({ slug: dune.slug, startAir: dune.airDate });
|
|
||||||
|
|
||||||
const [resp, body] = await createMovie({ ...dune, airDate: null });
|
|
||||||
expectStatus(resp, body).toBe(409);
|
|
||||||
expect(body.id).toBe(existing.id);
|
|
||||||
expect(body.slug).toBe(existing.slug);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Missing videos send info", async () => {
|
|
||||||
const vid = "a0ddf0ce-3258-4452-a670-aff36c76d524";
|
|
||||||
const [existing] = await db
|
|
||||||
.select()
|
|
||||||
.from(videos)
|
|
||||||
.where(eq(videos.id, vid))
|
|
||||||
.limit(1);
|
|
||||||
expect(existing).toBeUndefined();
|
|
||||||
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
...dune,
|
|
||||||
videos: [vid],
|
|
||||||
});
|
|
||||||
|
|
||||||
expectStatus(resp, body).toBe(200);
|
|
||||||
expect(body.videos).toBeArrayOfSize(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Schema error (missing fields)", async () => {
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
name: "dune",
|
|
||||||
} as any);
|
|
||||||
|
|
||||||
expectStatus(resp, body).toBe(422);
|
|
||||||
expect(body.status).toBe(422);
|
|
||||||
expect(body.message).toBeString();
|
|
||||||
expect(body.details).toBeObject();
|
|
||||||
// TODO: handle additional fields too
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Invalid translation name", async () => {
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
...dune,
|
|
||||||
translations: {
|
|
||||||
...dune.translations,
|
|
||||||
test: {
|
|
||||||
name: "foo",
|
|
||||||
description: "bar",
|
|
||||||
tags: [],
|
|
||||||
aliases: [],
|
|
||||||
tagline: "toto",
|
|
||||||
banner: null,
|
|
||||||
poster: null,
|
|
||||||
thumbnail: null,
|
|
||||||
logo: null,
|
|
||||||
trailerUrl: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expectStatus(resp, body).toBe(422);
|
|
||||||
expect(body.status).toBe(422);
|
|
||||||
expect(body.message).toBe("Invalid translation name: 'test'.");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Correct translations casing.", async () => {
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
...bubble,
|
|
||||||
slug: "casing-test",
|
|
||||||
originalLanguage: "jp-jp",
|
|
||||||
translations: {
|
|
||||||
"en-us": {
|
|
||||||
name: "foo",
|
|
||||||
description: "bar",
|
|
||||||
tags: [],
|
|
||||||
aliases: [],
|
|
||||||
tagline: "toto",
|
|
||||||
banner: null,
|
|
||||||
poster: null,
|
|
||||||
thumbnail: null,
|
|
||||||
logo: null,
|
|
||||||
trailerUrl: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(resp.status).toBeWithin(200, 299);
|
|
||||||
expect(body.id).toBeString();
|
|
||||||
const ret = await db.query.shows.findFirst({
|
|
||||||
where: eq(shows.id, body.id),
|
|
||||||
with: { translations: true },
|
|
||||||
});
|
|
||||||
expect(ret!.originalLanguage).toBe("jp-JP");
|
|
||||||
expect(ret!.translations).toBeArrayOfSize(2);
|
|
||||||
expect(ret!.translations).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
language: "en-US",
|
|
||||||
name: "foo",
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
expect(ret!.translations).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
language: "en",
|
|
||||||
name: "foo",
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Refuses random as a slug", async () => {
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
...bubble,
|
|
||||||
slug: "random",
|
|
||||||
airDate: null,
|
|
||||||
});
|
|
||||||
expectStatus(resp, body).toBe(422);
|
|
||||||
});
|
|
||||||
it("Refuses random as a slug but fallback w/ airDate", async () => {
|
|
||||||
const [resp, body] = await createMovie({ ...bubble, slug: "random" });
|
|
||||||
expectStatus(resp, body).toBe(201);
|
|
||||||
expect(body.slug).toBe("random-2022");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Handle fallback translations", async () => {
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
...bubble,
|
|
||||||
slug: "bubble-translation-test",
|
|
||||||
translations: { "en-us": bubble.translations.en },
|
|
||||||
});
|
|
||||||
expectStatus(resp, body).toBe(201);
|
|
||||||
|
|
||||||
const ret = await db.query.shows.findFirst({
|
|
||||||
where: eq(shows.id, body.id),
|
|
||||||
with: { translations: true },
|
|
||||||
});
|
|
||||||
expect(ret!.translations).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
name: bubble.translations.en.name,
|
|
||||||
language: "en",
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
expect(ret!.translations).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
name: bubble.translations.en.name,
|
|
||||||
language: "en-US",
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it("No fallback if explicit", async () => {
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
...bubble,
|
|
||||||
slug: "bubble-translation-test-2",
|
|
||||||
translations: {
|
|
||||||
"en-us": bubble.translations.en,
|
|
||||||
"en-au": { ...bubble.translations.en, name: "australian thing" },
|
|
||||||
en: { ...bubble.translations.en, name: "Generic" },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
expectStatus(resp, body).toBe(201);
|
|
||||||
|
|
||||||
const ret = await db.query.shows.findFirst({
|
|
||||||
where: eq(shows.id, body.id),
|
|
||||||
with: { translations: true },
|
|
||||||
});
|
|
||||||
expect(ret!.translations).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
name: bubble.translations.en.name,
|
|
||||||
language: "en-US",
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
expect(ret!.translations).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
name: "australian thing",
|
|
||||||
description: bubble.translations.en.description,
|
|
||||||
language: "en-AU",
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
expect(ret!.translations).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
name: "Generic",
|
|
||||||
description: bubble.translations.en.description,
|
|
||||||
language: "en",
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Create correct video slug", async () => {
|
|
||||||
const [vresp, video] = await createVideo({
|
|
||||||
path: "/video/bubble.mkv",
|
|
||||||
part: null,
|
|
||||||
version: 1,
|
|
||||||
rendering: "oeunhtoeuth",
|
|
||||||
});
|
|
||||||
expectStatus(vresp, video).toBe(201);
|
|
||||||
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
...bubble,
|
|
||||||
slug: "video-slug-test1",
|
|
||||||
videos: [video[0].id],
|
|
||||||
});
|
|
||||||
expectStatus(resp, body).toBe(201);
|
|
||||||
|
|
||||||
const ret = await db.query.videos.findFirst({
|
|
||||||
where: eq(videos.id, video[0].id),
|
|
||||||
with: { evj: { with: { entry: true } } },
|
|
||||||
});
|
|
||||||
expect(ret).not.toBe(undefined);
|
|
||||||
expect(ret!.evj).toBeArrayOfSize(1);
|
|
||||||
expect(ret!.evj[0].slug).toBe("video-slug-test1");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Create correct video slug (version)", async () => {
|
|
||||||
const [vresp, video] = await createVideo({
|
|
||||||
path: "/video/bubble2.mkv",
|
|
||||||
part: null,
|
|
||||||
version: 2,
|
|
||||||
rendering: "oeunhtoeuth",
|
|
||||||
});
|
|
||||||
expectStatus(vresp, video).toBe(201);
|
|
||||||
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
...bubble,
|
|
||||||
slug: "bubble-vtest",
|
|
||||||
videos: [video[0].id],
|
|
||||||
});
|
|
||||||
expectStatus(resp, body).toBe(201);
|
|
||||||
|
|
||||||
const ret = await db.query.videos.findFirst({
|
|
||||||
where: eq(videos.id, video[0].id),
|
|
||||||
with: { evj: { with: { entry: true } } },
|
|
||||||
});
|
|
||||||
expect(ret).not.toBe(undefined);
|
|
||||||
expect(ret!.evj).toBeArrayOfSize(1);
|
|
||||||
expect(ret!.evj[0].slug).toBe("bubble-vtest-v2");
|
|
||||||
});
|
|
||||||
it("Create correct video slug (part)", async () => {
|
|
||||||
const [vresp, video] = await createVideo({
|
|
||||||
path: "/video/bubble5.mkv",
|
|
||||||
part: 1,
|
|
||||||
version: 2,
|
|
||||||
rendering: "oaoeueunhtoeuth",
|
|
||||||
});
|
|
||||||
expectStatus(vresp, video).toBe(201);
|
|
||||||
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
...bubble,
|
|
||||||
slug: "bubble-ptest",
|
|
||||||
videos: [video[0].id],
|
|
||||||
});
|
|
||||||
expectStatus(resp, body).toBe(201);
|
|
||||||
|
|
||||||
const ret = await db.query.videos.findFirst({
|
|
||||||
where: eq(videos.id, video[0].id),
|
|
||||||
with: { evj: { with: { entry: true } } },
|
|
||||||
});
|
|
||||||
expect(ret).not.toBe(undefined);
|
|
||||||
expect(ret!.evj).toBeArrayOfSize(1);
|
|
||||||
expect(ret!.evj[0].slug).toBe("bubble-ptest-p1-v2");
|
|
||||||
});
|
|
||||||
it("Create correct video slug (rendering)", async () => {
|
|
||||||
const [vresp, video] = await createVideo([
|
|
||||||
{
|
|
||||||
path: "/video/bubble3.mkv",
|
|
||||||
part: null,
|
|
||||||
version: 1,
|
|
||||||
rendering: "oeunhtoeuth",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/video/bubble4.mkv",
|
|
||||||
part: null,
|
|
||||||
version: 1,
|
|
||||||
rendering: "aoeuaoeu",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
expectStatus(vresp, video).toBe(201);
|
|
||||||
|
|
||||||
const [resp, body] = await createMovie({
|
|
||||||
...bubble,
|
|
||||||
slug: "bubble-rtest",
|
|
||||||
videos: [video[0].id, video[1].id],
|
|
||||||
});
|
|
||||||
expectStatus(resp, body).toBe(201);
|
|
||||||
|
|
||||||
const ret = await db.query.shows.findFirst({
|
|
||||||
where: eq(shows.id, body.id),
|
|
||||||
with: { entries: { with: { evj: { with: { entry: true } } } } },
|
|
||||||
});
|
|
||||||
expect(ret).not.toBe(undefined);
|
|
||||||
expect(ret!.entries).toBeArrayOfSize(1);
|
|
||||||
expect(ret!.entries[0].slug).toBe("bubble-rtest");
|
|
||||||
expect(ret!.entries[0].evj).toBeArrayOfSize(2);
|
|
||||||
expect(ret!.entries[0].evj).toContainValues([
|
|
||||||
expect.objectContaining({ slug: "bubble-rtest" }),
|
|
||||||
expect.objectContaining({ slug: "bubble-rtest-aoeuaoeu" }),
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const cleanup = async () => {
|
|
||||||
await db.delete(shows);
|
|
||||||
await db.delete(videos);
|
|
||||||
};
|
|
||||||
// cleanup db beforehand to unsure tests are consistent
|
|
||||||
beforeAll(cleanup);
|
|
@ -15,3 +15,32 @@ export const createSerie = async (serie: SeedSerie) => {
|
|||||||
const body = await resp.json();
|
const body = await resp.json();
|
||||||
return [resp, body] as const;
|
return [resp, body] as const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getEntries = async (
|
||||||
|
serie: string,
|
||||||
|
{
|
||||||
|
langs,
|
||||||
|
...opts
|
||||||
|
}: {
|
||||||
|
filter?: string;
|
||||||
|
limit?: number;
|
||||||
|
after?: string;
|
||||||
|
sort?: string | string[];
|
||||||
|
query?: string;
|
||||||
|
langs?: string;
|
||||||
|
preferOriginal?: boolean;
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
const resp = await app.handle(
|
||||||
|
new Request(buildUrl(`series/${serie}/entries`, opts), {
|
||||||
|
method: "GET",
|
||||||
|
headers: langs
|
||||||
|
? {
|
||||||
|
"Accept-Language": langs,
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const body = await resp.json();
|
||||||
|
return [resp, body] as const;
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user