fix(ui): the Plex detail poster keeps its 2:3, and a long crew shows its first names
The hero's grid row is as tall as the crew column beside the text, and the poster, a flex child, stretched to it: a 2:3 picture drawn ~175x590 and cropped. It now aligns to the top, and a wide hero gives the movie and show poster a bigger rung (w-56). The crew, the hero's tallest part, shows its first 6 names and a 'Show N more' toggle; a list of 8 or fewer shows whole.
This commit is contained in:
@@ -27,6 +27,7 @@ vi.mock("react-i18next", async (importOriginal) => {
|
||||
});
|
||||
|
||||
import PlexInfo from "./PlexInfo";
|
||||
import { CREW_SHOWN } from "./plexDetailAside";
|
||||
import type { PlexItemDetail } from "../lib/api";
|
||||
|
||||
afterEach(cleanup);
|
||||
@@ -250,6 +251,55 @@ describe("PlexInfo — the hero's second column (page)", () => {
|
||||
expect(document.querySelector(`[class*="${TWO_COLUMNS}"]`)).toBeNull();
|
||||
expect(follows(heading("Test Movie"), kw)).toBe(true);
|
||||
});
|
||||
|
||||
// E31: the hero's grid row is as tall as its taller column — the crew, beside the text — and the poster,
|
||||
// a flex child, stretched to it: a 2:3 picture drawn ~175×590 and cropped. It keeps its own ratio.
|
||||
it("keeps the poster at its own height, not stretched to the row", () => {
|
||||
wrap(<PlexInfo onPlayItem={noop} detail={full} variant="page" />);
|
||||
const poster = document.querySelector<HTMLImageElement>(`img[src="${detail.thumb}"]`)!;
|
||||
expect(poster.className).toContain("aspect-2/3");
|
||||
expect(poster.className.split(/\s+/)).toContain("self-start");
|
||||
});
|
||||
|
||||
// E31 (the owner's call): twelve names ran the column ~170px past the text. The first CREW_SHOWN show,
|
||||
// the rest behind "Show N more"; a list barely longer shows whole.
|
||||
it("shows the first crew names and opens the rest on demand", () => {
|
||||
const crew = Array.from({ length: 12 }, (_, i) => ({ name: `Person ${i}`, job: "Producer" }));
|
||||
wrap(
|
||||
<PlexInfo
|
||||
onPlayItem={noop}
|
||||
detail={{ ...full, tmdb: { ...full.tmdb!, crew } }}
|
||||
variant="page"
|
||||
/>,
|
||||
);
|
||||
const aside = screen.getByTestId("detail-aside");
|
||||
expect(aside.textContent).toContain(`Person ${CREW_SHOWN - 1}`);
|
||||
expect(aside.textContent).not.toContain(`Person ${CREW_SHOWN}`);
|
||||
const more = screen.getByRole("button", { name: "plex.info.crewMore" });
|
||||
expect(more.getAttribute("aria-expanded")).toBe("false");
|
||||
fireEvent.click(more);
|
||||
expect(aside.textContent).toContain("Person 11");
|
||||
const less = screen.getByRole("button", { name: "plex.info.crewLess" });
|
||||
expect(less.getAttribute("aria-expanded")).toBe("true");
|
||||
fireEvent.click(less);
|
||||
expect(aside.textContent).not.toContain(`Person ${CREW_SHOWN}`);
|
||||
});
|
||||
|
||||
it("shows a crew only a little longer than that whole, with no toggle", () => {
|
||||
const crew = Array.from({ length: CREW_SHOWN + 2 }, (_, i) => ({
|
||||
name: `Person ${i}`,
|
||||
job: "Producer",
|
||||
}));
|
||||
wrap(
|
||||
<PlexInfo
|
||||
onPlayItem={noop}
|
||||
detail={{ ...full, tmdb: { ...full.tmdb!, crew } }}
|
||||
variant="page"
|
||||
/>,
|
||||
);
|
||||
expect(screen.getByTestId("detail-aside").textContent).toContain(`Person ${CREW_SHOWN + 1}`);
|
||||
expect(screen.queryByRole("button", { name: "plex.info.crewMore" })).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
// E28 review D1 + D2: a collection sibling is a Plex card like any other — its "…" menu, its watched
|
||||
|
||||
Reference in New Issue
Block a user