Fix existing get movie & add test

This commit is contained in:
Zoe Roux 2024-12-11 17:01:59 +01:00
parent c263dd770e
commit 9e1afca9ec
No known key found for this signature in database
3 changed files with 106 additions and 17 deletions

View File

@ -2,21 +2,24 @@ import { Elysia, t } from "elysia";
import { Movie, MovieTranslation } from "../models/movie";
import { db } from "../db";
import { shows, showTranslations } from "../db/schema/shows";
import { eq, and, sql, or, inArray } from "drizzle-orm";
import { eq, and, sql, or } from "drizzle-orm";
import { getColumns } from "../db/schema/utils";
import { bubble } from "../models/examples";
import { comment } from "~/utils";
import { processLanguages } from "~/models/utils";
const translations = db
.selectDistinctOn([showTranslations.language])
.selectDistinctOn([showTranslations.pk])
.from(showTranslations)
.where(
or(
inArray(showTranslations.language, sql.placeholder("langs")),
eq(showTranslations.language, shows.originalLanguage),
),
)
// .where(
// or(
// eq(showTranslations.language, sql`any(${sql.placeholder("langs")})`),
// eq(showTranslations.language, shows.originalLanguage),
// ),
// )
.orderBy(
sql`array_position(${showTranslations.language}, ${sql.placeholder("langs")})`,
showTranslations.pk,
sql`array_position(${sql.placeholder("langs")}, ${showTranslations.language})`,
)
.as("t");
@ -26,21 +29,21 @@ const { pk, language, ...translationsCol } = getColumns(translations);
const findMovie = db
.select({
...moviesCol,
...translationsCol,
airDate: startAir,
translations: translationsCol,
})
.from(shows)
.innerJoin(translations, eq(shows.pk, translations.pk))
.where(
and(
eq(shows.kind, "movie"),
or(
eq(shows.id, sql.placeholder("id")),
// or(
// eq(shows.id, sql.placeholder("id")),
eq(shows.slug, sql.placeholder("id")),
),
// ),
),
)
.orderBy()
// .orderBy()
.limit(1)
.prepare("findMovie");
@ -57,12 +60,31 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
examples: [bubble.slug],
}),
}),
headers: t.Object({
"Accept-Language": t.String({
default: "*",
examples: "en-us, ja;q=0.5",
description: comment`
List of languages you want the data in.
This follows the Accept-Language offical specification
(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language)
`,
}),
}),
response: { 200: "movie", 404: "error" },
})
.get(
"/:id",
async ({ params: { id }, error }) => {
const ret = await findMovie.execute({ id });
async ({
params: { id },
headers: { "Accept-Language": languages },
error,
}) => {
const langs = processLanguages(languages);
console.log(langs);
console.log(findMovie.getQuery());
const ret = await findMovie.execute({ id, langs });
console.log(ret);
if (ret.length !== 1) return error(404, {});
return ret[0];
},
@ -71,4 +93,4 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
description: "Get a movie by id or slug",
},
},
);
)

View File

@ -48,3 +48,18 @@ export const Language = (props?: StringProps) =>
error: "Expected a valid (and NORMALIZED) bcp-47 language code.",
...props,
});
export const processLanguages = (languages: string) => {
return languages
.split(",")
.map((x) => {
const [lang, q] = x.trim().split(";q=");
return [lang, q ? Number.parseFloat(q) : 1] as const;
})
.sort(([_, q1], [__, q2]) => q1 - q2)
.flatMap(([lang]) => {
const [base, spec] = lang.split("-");
if (spec) return [lang, base];
return [lang];
});
};

View File

@ -0,0 +1,52 @@
import { afterAll, beforeAll, describe, expect, it } from "bun:test";
import { eq } from "drizzle-orm";
import Elysia from "elysia";
import { base } from "~/base";
import { movies } from "~/controllers/movies";
import { seedMovie } from "~/controllers/seed/movies";
import { db } from "~/db";
import { shows } from "~/db/schema";
import { bubble } from "~/models/examples";
const app = new Elysia().use(base).use(movies);
const getMovie = async (id: string, langs: string) => {
const resp = await app.handle(
new Request(`http://localhost/movies/${id}`, {
method: "GET",
headers: {
"Accept-Language": langs,
},
}),
);
const body = await resp.json();
return [resp, body] as const;
};
function expectStatus(resp: Response, body: object) {
const matcher = expect({ ...body, status: resp.status });
return {
toBe: (status: number) => {
matcher.toMatchObject({ status: status });
},
};
}
describe("Get movie", () => {
it("Retrive by slug", async () => {
const [resp, body] = await getMovie(bubble.slug, "en");
expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({
slug: bubble.slug,
name: bubble.translations.en.name,
});
});
});
beforeAll(async () => {
const ret = await seedMovie(bubble);
console.log("seed bubble", ret);
});
afterAll(async () => {
// await db.delete(shows).where(eq(shows.slug, bubble.slug));
});