Test & Fix prefer original for /movies/{id}

This commit is contained in:
Zoe Roux 2025-01-17 18:34:53 +01:00
parent 7047304ae5
commit a558f47558
5 changed files with 69 additions and 26 deletions

View File

@ -109,12 +109,16 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
});
}
set.headers["content-language"] = translation.language;
const ot = ret.originalTranslation;
return {
...ret,
...translation,
...(ret.originalTranslation?.preferOriginal
? ret.originalTranslation
: {}),
...(ot?.preferOriginal && {
...(ot.poster && { poster: ot.poster }),
...(ot.thumbnail && { thumbnail: ot.thumbnail }),
...(ot.banner && { banner: ot.banner }),
...(ot.logo && { logo: ot.logo }),
}),
};
},
{

View File

@ -26,10 +26,10 @@ export const bubble: SeedMovie = {
thumbnail:
"https://image.tmdb.org/t/p/original/a8Q2g0g7XzAF6gcB8qgn37ccb9Y.jpg",
banner: null,
logo: null,
logo: "https://image.tmdb.org/t/p/original/ihIs7fayAmZieMlMQbs6TWM77uf.png",
trailerUrl: "https://www.youtube.com/watch?v=vs7zsyIZkMM",
},
jp: {
ja: {
name: "バブル2022",
tagline: null,
description: null,
@ -37,10 +37,9 @@ export const bubble: SeedMovie = {
tags: ["アニメ"],
poster:
"https://image.tmdb.org/t/p/original/65dad96VE8FJPEdrAkhdsuWMWH9.jpg",
thumbnail:
"https://image.tmdb.org/t/p/original/a8Q2g0g7XzAF6gcB8qgn37ccb9Y.jpg",
thumbnail: "https://image.tmdb.org/t/p/original/jp.jpg",
banner: null,
logo: "https://image.tmdb.org/t/p/original/ihIs7fayAmZieMlMQbs6TWM77uf.png",
logo: null,
trailerUrl: "https://www.youtube.com/watch?v=vs7zsyIZkMM",
},
},

View File

@ -12,8 +12,17 @@ beforeAll(async () => {
});
describe("Get movie", () => {
it("Invalid slug", async () => {
const [resp, body] = await getMovie("sotneuhn", { langs: "en" });
expectStatus(resp, body).toBe(404);
expect(body).toMatchObject({
status: 404,
message: "Movie not found",
});
});
it("Retrive by slug", async () => {
const [resp, body] = await getMovie(bubble.slug, "en");
const [resp, body] = await getMovie(bubble.slug, { langs: "en" });
expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({
@ -22,7 +31,7 @@ describe("Get movie", () => {
});
});
it("Retrive by id", async () => {
const [resp, body] = await getMovie(bubbleId, "en");
const [resp, body] = await getMovie(bubbleId, { langs: "en" });
expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({
@ -32,7 +41,7 @@ describe("Get movie", () => {
});
});
it("Get non available translation", async () => {
const [resp, body] = await getMovie(bubble.slug, "fr");
const [resp, body] = await getMovie(bubble.slug, { langs: "fr" });
expectStatus(resp, body).toBe(422);
expect(body).toMatchObject({
@ -40,7 +49,7 @@ describe("Get movie", () => {
});
});
it("Get first available language", async () => {
const [resp, body] = await getMovie(bubble.slug, "fr,en");
const [resp, body] = await getMovie(bubble.slug, { langs: "fr,en" });
expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({
@ -50,7 +59,7 @@ describe("Get movie", () => {
expect(resp.headers.get("Content-Language")).toBe("en");
});
it("Use language fallback", async () => {
const [resp, body] = await getMovie(bubble.slug, "fr,ja,*");
const [resp, body] = await getMovie(bubble.slug, { langs: "fr,pr,*" });
expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({
@ -60,7 +69,7 @@ describe("Get movie", () => {
expect(resp.headers.get("Content-Language")).toBe("en");
});
it("Works without accept-language header", async () => {
const [resp, body] = await getMovie(bubble.slug, undefined);
const [resp, body] = await getMovie(bubble.slug, { langs: undefined });
expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({
@ -70,7 +79,7 @@ describe("Get movie", () => {
expect(resp.headers.get("Content-Language")).toBe("en");
});
it("Fallback if translations does not exist", async () => {
const [resp, body] = await getMovie(bubble.slug, "en-au");
const [resp, body] = await getMovie(bubble.slug, { langs: "en-au" });
expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({
@ -79,4 +88,29 @@ describe("Get movie", () => {
});
expect(resp.headers.get("Content-Language")).toBe("en");
});
it("Prefer original", async () => {
expect(bubble.translations.ja.logo).toBe(null);
expect(bubble.translations.en.logo).not.toBe(null);
const [resp, body] = await getMovie(bubble.slug, {
langs: "en-au",
preferOriginal: true,
});
expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({
slug: bubble.slug,
name: bubble.translations.en.name,
poster: ({
source: bubble.translations.ja.poster,
}),
thumbnail: ({
source: bubble.translations.ja.thumbnail,
}),
banner: null,
// we fallback to the translated value when the original is null.
logo: ({ source: bubble.translations.en.logo }),
});
expect(resp.headers.get("Content-Language")).toBe("en");
});
});

View File

@ -7,9 +7,12 @@ import type { SeedMovie } from "~/models/movie";
export const movieApp = new Elysia().use(base).use(movies).use(seed);
export const getMovie = async (id: string, langs?: string) => {
export const getMovie = async (
id: string,
{ langs, ...query }: { langs?: string; preferOriginal?: boolean },
) => {
const resp = await movieApp.handle(
new Request(`http://localhost/movies/${id}`, {
new Request(buildUrl(`movies/${id}`, query), {
method: "GET",
headers: langs
? {
@ -48,7 +51,7 @@ export const getMovies = async ({
export const createMovie = async (movie: SeedMovie) => {
const resp = await movieApp.handle(
new Request("http://localhost/movies", {
new Request(buildUrl("movies"), {
method: "POST",
body: JSON.stringify(movie),
headers: {

View File

@ -1,5 +1,4 @@
import { expect } from "bun:test";
import Elysia from "elysia";
export function expectStatus(resp: Response, body: object) {
const matcher = expect({ ...body, status: resp.status });
@ -10,14 +9,18 @@ export function expectStatus(resp: Response, body: object) {
};
}
export const buildUrl = (route: string, query: Record<string, any>) => {
export const buildUrl = (route: string, query?: Record<string, any>) => {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(query)) {
if (!Array.isArray(value)) {
params.append(key, value.toString());
continue;
if (query) {
for (const [key, value] of Object.entries(query)) {
if (!Array.isArray(value)) {
params.append(key, value.toString());
continue;
}
for (const v of value) params.append(key, v.toString());
}
for (const v of value) params.append(key, v.toString());
}
return `http://localhost/${route}?${params}`;
return params.size
? `http://localhost/${route}?${params}`
: `http://localhost/${route}`;
};