mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Test POST /videos
This commit is contained in:
parent
1369da1845
commit
39dcfb4418
@ -7,11 +7,10 @@ import {
|
|||||||
conflictUpdateAllExcept,
|
conflictUpdateAllExcept,
|
||||||
jsonbBuildObject,
|
jsonbBuildObject,
|
||||||
jsonbObjectAgg,
|
jsonbObjectAgg,
|
||||||
sqlarr,
|
|
||||||
values,
|
values,
|
||||||
} from "~/db/utils";
|
} from "~/db/utils";
|
||||||
import { bubbleVideo } from "~/models/examples";
|
import { bubbleVideo } from "~/models/examples";
|
||||||
import { Page, isUuid } from "~/models/utils";
|
import { isUuid } from "~/models/utils";
|
||||||
import { Guesses, SeedVideo, Video } from "~/models/video";
|
import { Guesses, SeedVideo, Video } from "~/models/video";
|
||||||
import { comment } from "~/utils";
|
import { comment } from "~/utils";
|
||||||
import { computeVideoSlug } from "./seed/insert/entries";
|
import { computeVideoSlug } from "./seed/insert/entries";
|
||||||
@ -138,10 +137,11 @@ export const videosH = new Elysia({ prefix: "/videos", tags: ["videos"] })
|
|||||||
})
|
})
|
||||||
.from(
|
.from(
|
||||||
values(
|
values(
|
||||||
body.flatMap((x) =>
|
body.flatMap((x) => {
|
||||||
x.for.map((e) => ({
|
if (!x.for) return [];
|
||||||
|
return x.for.map((e) => ({
|
||||||
path: x.path,
|
path: x.path,
|
||||||
needRendering: x.for.length > 1,
|
needRendering: x.for!.length > 1,
|
||||||
entry: {
|
entry: {
|
||||||
...e,
|
...e,
|
||||||
movie:
|
movie:
|
||||||
@ -157,8 +157,8 @@ export const videosH = new Elysia({ prefix: "/videos", tags: ["videos"] })
|
|||||||
: { slug: e.serie }
|
: { slug: e.serie }
|
||||||
: undefined,
|
: undefined,
|
||||||
},
|
},
|
||||||
})),
|
}));
|
||||||
),
|
}),
|
||||||
).as("j"),
|
).as("j"),
|
||||||
)
|
)
|
||||||
.innerJoin(vidsI, eq(vidsI.path, sql`j.path`))
|
.innerJoin(vidsI, eq(vidsI.path, sql`j.path`))
|
||||||
|
@ -103,7 +103,10 @@ export const nullif = <T>(val: SQL<T> | Column, eq: SQL<T>) => {
|
|||||||
return sql<T>`nullif(${val}, ${eq})`;
|
return sql<T>`nullif(${val}, ${eq})`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const jsonbObjectAgg = <T>(key: SQLWrapper, value: SQL<T> | SQLWrapper) => {
|
export const jsonbObjectAgg = <T>(
|
||||||
|
key: SQLWrapper,
|
||||||
|
value: SQL<T> | SQLWrapper,
|
||||||
|
) => {
|
||||||
return sql<
|
return sql<
|
||||||
Record<string, T>
|
Record<string, T>
|
||||||
>`jsonb_object_agg(${sql.join([key, value], sql.raw(","))})`;
|
>`jsonb_object_agg(${sql.join([key, value], sql.raw(","))})`;
|
||||||
|
@ -68,44 +68,47 @@ export const SeedVideo = t.Object({
|
|||||||
|
|
||||||
guess: Guess,
|
guess: Guess,
|
||||||
|
|
||||||
for: t.Array(
|
for: t.Optional(
|
||||||
t.Union([
|
t.Array(
|
||||||
t.Object({
|
t.Union([
|
||||||
slug: t.String({
|
|
||||||
format: "slug",
|
|
||||||
examples: ["made-in-abyss-dawn-of-the-deep-soul"],
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
t.Object({
|
|
||||||
externalId: t.Optional(t.Union([EpisodeId, ExternalId()])),
|
|
||||||
}),
|
|
||||||
t.Object({
|
|
||||||
movie: t.Union([
|
|
||||||
t.String({ format: "uuid" }),
|
|
||||||
t.String({ format: "slug", examples: ["bubble"] }),
|
|
||||||
]),
|
|
||||||
}),
|
|
||||||
t.Intersect([
|
|
||||||
t.Object({
|
t.Object({
|
||||||
serie: t.Union([
|
slug: t.String({
|
||||||
|
format: "slug",
|
||||||
|
examples: ["made-in-abyss-dawn-of-the-deep-soul"],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
t.Object({
|
||||||
|
externalId: t.Optional(t.Union([EpisodeId, ExternalId()])),
|
||||||
|
}),
|
||||||
|
t.Object({
|
||||||
|
movie: t.Union([
|
||||||
t.String({ format: "uuid" }),
|
t.String({ format: "uuid" }),
|
||||||
t.String({ format: "slug", examples: ["made-in-abyss"] }),
|
t.String({ format: "slug", examples: ["bubble"] }),
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
t.Union([
|
t.Intersect([
|
||||||
t.Object({
|
t.Object({
|
||||||
season: t.Integer({ minimum: 1 }),
|
serie: t.Union([
|
||||||
episode: t.Integer(),
|
t.String({ format: "uuid" }),
|
||||||
}),
|
t.String({ format: "slug", examples: ["made-in-abyss"] }),
|
||||||
t.Object({
|
]),
|
||||||
order: t.Number(),
|
|
||||||
}),
|
|
||||||
t.Object({
|
|
||||||
special: t.Integer(),
|
|
||||||
}),
|
}),
|
||||||
|
t.Union([
|
||||||
|
t.Object({
|
||||||
|
season: t.Integer({ minimum: 1 }),
|
||||||
|
episode: t.Integer(),
|
||||||
|
}),
|
||||||
|
t.Object({
|
||||||
|
order: t.Number(),
|
||||||
|
}),
|
||||||
|
t.Object({
|
||||||
|
special: t.Integer(),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
]),
|
{ default: [] },
|
||||||
|
),
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
export type SeedVideo = Prettify<typeof SeedVideo.static>;
|
export type SeedVideo = Prettify<typeof SeedVideo.static>;
|
||||||
|
50
api/tests/videos/scanner.test.ts
Normal file
50
api/tests/videos/scanner.test.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { beforeAll, describe, expect, it } from "bun:test";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
import { createVideo } from "tests/helpers";
|
||||||
|
import { expectStatus } from "tests/utils";
|
||||||
|
import { db } from "~/db";
|
||||||
|
import { entries, shows, videos } from "~/db/schema";
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await db.delete(shows);
|
||||||
|
await db.delete(entries);
|
||||||
|
await db.delete(videos);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Video seeding", () => {
|
||||||
|
it("Can create a video without entry", async () => {
|
||||||
|
const [resp, body] = await createVideo({
|
||||||
|
guess: { title: "mia", from: "test" },
|
||||||
|
part: null,
|
||||||
|
path: "/video/mia s1e13.mkv",
|
||||||
|
rendering: "sha",
|
||||||
|
version: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
expectStatus(resp, body).toBe(201);
|
||||||
|
expect(body).toBeArrayOfSize(1);
|
||||||
|
expect(body[0].id).toBeString();
|
||||||
|
|
||||||
|
const vid = await db.query.videos.findFirst({
|
||||||
|
where: eq(videos.id, body[0].id),
|
||||||
|
with: {
|
||||||
|
evj: { with: { entry: true } },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(vid).not.toBeNil();
|
||||||
|
expect(vid!.path).toBe("/video/mia s1e13.mkv");
|
||||||
|
expect(vid!.guess).toBe({ title: "mia", from: "test" });
|
||||||
|
|
||||||
|
expect(body[0].slug).toBe("mia");
|
||||||
|
// videos created without entries should create an /unknown entry.
|
||||||
|
expect(vid!.evj).toBeArrayOfSize(1);
|
||||||
|
expect(vid!.evj[0].slug).toBe("mia");
|
||||||
|
expect(vid!.evj[0].entry).toMatchObject({
|
||||||
|
kind: "unknown",
|
||||||
|
name: "mia",
|
||||||
|
// should we store the video path in the unknown entry?
|
||||||
|
// in db it would be the `description` field
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user