fix(plex): a matched episode and a collection member offer Details in their menu
Their titles open the item's page, a pointer-only door; the card menu is the keyboard's.
This commit is contained in:
@@ -21,6 +21,7 @@ vi.mock("./PlexPlayer", () => ({
|
|||||||
vi.mock("./plexViews", async (importOriginal) => ({
|
vi.mock("./plexViews", async (importOriginal) => ({
|
||||||
...(await importOriginal<typeof import("./plexViews")>()),
|
...(await importOriginal<typeof import("./plexViews")>()),
|
||||||
PlexShowView: ({ showId }: { showId: string }) => <div>show page {showId}</div>,
|
PlexShowView: ({ showId }: { showId: string }) => <div>show page {showId}</div>,
|
||||||
|
PlexInfoView: ({ id }: { id: string }) => <div>info page {id}</div>,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
import PlexBrowse from "./PlexBrowse";
|
import PlexBrowse from "./PlexBrowse";
|
||||||
@@ -53,12 +54,12 @@ const show: PlexCard = {
|
|||||||
resumable: true,
|
resumable: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
function mount() {
|
function mount(episodes: PlexCard[] = []) {
|
||||||
vi.spyOn(api, "plexLibrary").mockResolvedValue({
|
vi.spyOn(api, "plexLibrary").mockResolvedValue({
|
||||||
items: [show],
|
items: [show],
|
||||||
total: 1,
|
total: 1,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
episodes: [],
|
episodes,
|
||||||
} as never);
|
} as never);
|
||||||
const next = vi.spyOn(api, "plexShowNext").mockResolvedValue({
|
const next = vi.spyOn(api, "plexShowNext").mockResolvedValue({
|
||||||
next: { id: "e7", type: "episode", title: "Ep 7", thumb: "" },
|
next: { id: "e7", type: "episode", title: "Ep 7", thumb: "" },
|
||||||
@@ -93,6 +94,16 @@ describe("PlexBrowse — a show's card in the grid", () => {
|
|||||||
expect(next).not.toHaveBeenCalled();
|
expect(next).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// A matched episode's title opens its page, a pointer's door: its menu offers the same to the keyboard.
|
||||||
|
it("opens a matched episode's page from its menu, as its title does", async () => {
|
||||||
|
mount([{ id: "ep1", type: "episode", title: "Pilot", thumb: "", show_title: "Grimm" }]);
|
||||||
|
const section = (await screen.findByText("plex.unified.episodes")).parentElement!;
|
||||||
|
fireEvent.click(section.querySelector<HTMLButtonElement>("button[aria-haspopup]")!);
|
||||||
|
const rows = await screen.findAllByRole("menuitem", { hidden: true });
|
||||||
|
fireEvent.click(rows.find((r) => r.textContent === "plex.info.title")!);
|
||||||
|
expect(await screen.findByText("info page ep1")).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
it("opens the show's page from its ⓘ, asking nothing", async () => {
|
it("opens the show's page from its ⓘ, asking nothing", async () => {
|
||||||
const { next } = mount();
|
const { next } = mount();
|
||||||
fireEvent.click(await screen.findByRole("button", { name: "plex.openShow" }));
|
fireEvent.click(await screen.findByRole("button", { name: "plex.openShow" }));
|
||||||
|
|||||||
@@ -392,8 +392,9 @@ export default function PlexBrowse() {
|
|||||||
{ onOpen: onCard, onRestart: onRestartCard, onInfo, onToggleWatched: toggleWatched },
|
{ onOpen: onCard, onRestart: onRestartCard, onInfo, onToggleWatched: toggleWatched },
|
||||||
menu.open,
|
menu.open,
|
||||||
);
|
);
|
||||||
|
// Details too: an episode's title opens its page, and the menu is that door for the keyboard.
|
||||||
const epActions = usePlexCardActions(
|
const epActions = usePlexCardActions(
|
||||||
{ onOpen: onCard, onRestart: onRestartCard, onToggleWatched: toggleWatched },
|
{ onOpen: onCard, onRestart: onRestartCard, onInfo, onToggleWatched: toggleWatched },
|
||||||
epMenu.open,
|
epMenu.open,
|
||||||
);
|
);
|
||||||
// Apply a metadata filter (clicked on an info page / show hero / cast) then show the unified grid.
|
// Apply a metadata filter (clicked on an info page / show hero / cast) then show the unified grid.
|
||||||
|
|||||||
@@ -411,4 +411,18 @@ describe("a collection strip's card", () => {
|
|||||||
fireEvent.click(restart.find((r) => r.textContent === "card.restartTitle")!);
|
fireEvent.click(restart.find((r) => r.textContent === "card.restartTitle")!);
|
||||||
await vi.waitFor(() => expect(onPlayItem).toHaveBeenCalledWith("m2", true));
|
await vi.waitFor(() => expect(onPlayItem).toHaveBeenCalledWith("m2", true));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Its title opens the member's page, a pointer's door: the menu offers the same to the keyboard.
|
||||||
|
it("opens the member's page from its menu, as its title does", async () => {
|
||||||
|
const onOpenInfo = vi.fn();
|
||||||
|
wrap(
|
||||||
|
<PlexInfo detail={withColl} variant="page" onPlayItem={vi.fn()} onOpenInfo={onOpenInfo} />,
|
||||||
|
);
|
||||||
|
const strip = screen.getByRole("heading", { name: "The Collection" }).parentElement!
|
||||||
|
.parentElement!;
|
||||||
|
fireEvent.click(strip.querySelector<HTMLButtonElement>("button[aria-haspopup]")!);
|
||||||
|
const rows = await screen.findAllByRole("menuitem", { hidden: true });
|
||||||
|
fireEvent.click(rows.find((r) => r.textContent === "plex.info.title")!);
|
||||||
|
await vi.waitFor(() => expect(onOpenInfo).toHaveBeenCalledWith("m2"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -285,10 +285,13 @@ export default function PlexInfo({
|
|||||||
qc.invalidateQueries({ queryKey: qk.plexLibrary() });
|
qc.invalidateQueries({ queryKey: qk.plexLibrary() });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
// Details wherever the member's title opens its page (not in the overlay): the menu is that door
|
||||||
|
// for the keyboard.
|
||||||
const colActions = usePlexCardActions(
|
const colActions = usePlexCardActions(
|
||||||
{
|
{
|
||||||
onOpen: (c) => onPlayItem(c.id),
|
onOpen: (c) => onPlayItem(c.id),
|
||||||
onRestart: (c) => onPlayItem(c.id, true),
|
onRestart: (c) => onPlayItem(c.id, true),
|
||||||
|
onInfo: variant !== "overlay" && onOpenInfo ? (c) => onOpenInfo(c.id) : undefined,
|
||||||
onToggleWatched: toggleColWatched,
|
onToggleWatched: toggleColWatched,
|
||||||
},
|
},
|
||||||
colMenu.open,
|
colMenu.open,
|
||||||
|
|||||||
Reference in New Issue
Block a user