A show card's picture opened the show page everywhere but Home, whose shelves carried the
resolved `next`. Now every Plex picture plays: a show asks `GET /api/plex/show/{id}/next`
(the in-progress episode, else the first unwatched, else S1·E1 — the rule Home and the show
page's Resume follow) on the click, fresh each time. A started show shows Continue + Restart;
its title, an ⓘ and the menu's "Open show" row open its page; one with no episodes opens there.
The question is asked per show, never carried on every card: three probes a show would cost a
grid page up to 180 queries. The hover preview asks it once it opens and names the episode
("Next: S6·E16 — Title"). Related shows on a show page play the same way.
82 lines
3.2 KiB
TypeScript
82 lines
3.2 KiB
TypeScript
// @vitest-environment jsdom
|
|
//
|
|
// 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 as rtlRender, screen, cleanup } from "@testing-library/react";
|
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
import type { ReactElement } from "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: () => ({ i18n: { language: "en" }, t }) };
|
|
});
|
|
|
|
import { PlexPosterCard, SeasonCard } from "./plexCards";
|
|
import type { PlexCard, PlexSeasonDetail } from "../lib/api";
|
|
|
|
// A show card asks the server which episode it would play once its preview is up: a query client.
|
|
const render = (ui: ReactElement) =>
|
|
rtlRender(ui, {
|
|
wrapper: ({ children }) => (
|
|
<QueryClientProvider client={new QueryClient()}>{children}</QueryClientProvider>
|
|
),
|
|
});
|
|
|
|
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();
|
|
});
|
|
});
|