Files
siftlode/frontend/src/components/plexCards.lang.dom.test.tsx
T
peter 632e39d458 feat(plex): every card rail in the reader's language; an episode in a poster rail stands as its show (E30 S1b)
The grid served Hungarian titles, but every other card surface (Discover rails, the
show page's episodes, search, collections, the person page, playlists, Home's resume
rail, hero and comfort shelf) served English. The card serializers now take a
required keyword-only lang (a forgotten call site fails instead of going English), and
each of those reads takes ?lang=hu, with the language in its query key. A Hungarian
search finds an episode by its Hungarian title too.

An episode on a poster rail showed its 16:9 still cropped into a poster, titled only
with the episode name; it now shows the show's poster and name, with S·E · title under
it (option A). Plex's generic season names (Season 1, Specials) are rebuilt from the
number in the reader's language; a season with a name of its own keeps it.

Home's comfort-shelf move wrote its optimistic order to the key without the language,
which nothing read any more; it writes the query's own key.
2026-09-29 02:12:32 +02:00

72 lines
2.7 KiB
TypeScript

// @vitest-environment jsdom
//
// E30: what a Plex card says, in the reader's language. An episode in a poster rail stands as its show
// (the show's poster and name, the episode on the line under it), and a season Plex named generically
// ("Season 1", "Specials") is named from its number instead. i18n here echoes the key AND its values,
// so an assertion can see which words went into the line.
import { describe, it, expect, afterEach, vi } from "vitest";
import { render, screen, cleanup } from "@testing-library/react";
vi.mock("react-i18next", async (importOriginal) => {
const actual = await importOriginal<typeof import("react-i18next")>();
const t = (key: string, o?: Record<string, unknown>) =>
o ? `${key}(${Object.values(o).join("|")})` : key;
return { ...actual, useTranslation: () => ({ t }) };
});
import { PlexPosterCard, SeasonCard } from "./plexCards";
import type { PlexCard, PlexSeasonDetail } from "../lib/api";
afterEach(cleanup);
const watchedEpisode: PlexCard = {
id: "e5",
type: "episode",
title: "Visszaszámlálás",
thumb: "/api/plex/image/e5",
season_number: 2,
episode_number: 5,
show_title: "A 3-test-probléma",
show_id: "s9",
};
describe("an episode in a poster rail", () => {
it("stands as its show: the show's poster and name, the episode under it", () => {
render(<PlexPosterCard card={watchedEpisode} onOpen={vi.fn()} shelf />);
const img = document.querySelector("img");
expect(img?.getAttribute("src")).toBe("/api/plex/image/s9");
expect(screen.getByText("A 3-test-probléma")).toBeTruthy();
expect(screen.getByText("plex.episodeLine(2|5|Visszaszámlálás)")).toBeTruthy();
});
it("keeps its own landscape still where the rail is landscape, or the show is unknown", () => {
const { unmount } = render(<PlexPosterCard card={watchedEpisode} onOpen={vi.fn()} wide />);
expect(document.querySelector("img")?.getAttribute("src")).toBe("/api/plex/image/e5");
unmount();
render(<PlexPosterCard card={{ ...watchedEpisode, show_id: null }} onOpen={vi.fn()} />);
expect(document.querySelector("img")?.getAttribute("src")).toBe("/api/plex/image/e5");
expect(screen.getByText("Visszaszámlálás")).toBeTruthy();
});
});
const season = (title: string, n: number | null): PlexSeasonDetail => ({
id: "se",
season_number: n,
title,
thumb: "",
episode_count: 3,
status: "new",
episodes: [],
});
describe("a season's name", () => {
it.each([
["Season 1", 1, "plex.seasonTitle(1)"],
["Specials", 0, "plex.specials"],
["Book One: Water", 1, "Book One: Water"],
])("Plex's %j (season %s) reads %j", (title, n, shown) => {
render(<SeasonCard se={season(title, n)} onOpen={vi.fn()} />);
expect(screen.getByText(shown)).toBeTruthy();
});
});