diff --git a/frontend/src/components/PlexDiscover.dom.test.tsx b/frontend/src/components/PlexDiscover.dom.test.tsx index f0a4fdca..da3f557e 100644 --- a/frontend/src/components/PlexDiscover.dom.test.tsx +++ b/frontend/src/components/PlexDiscover.dom.test.tsx @@ -7,7 +7,7 @@ // synchronously. The rails scroll inside a Carousel (useHScroll → ResizeObserver), stubbed for jsdom. import { describe, it, expect, afterEach, beforeAll, vi } from "vitest"; import { act, render, screen, fireEvent, cleanup, waitFor } from "@testing-library/react"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { focusManager, QueryClient, QueryClientProvider } from "@tanstack/react-query"; beforeAll(() => { class Stub { @@ -223,6 +223,37 @@ describe("PlexDiscover", () => { expect(plexSurprise.mock.calls[1]?.[4]).toEqual(["sp1"]); }); + // Back from a card's player or page remounts the surface: the draw it left must still be there. + it("keeps its draw across a remount and a return to the window; only ↻ redraws", async () => { + plexDiscover.mockResolvedValue(fullPayload); + plexSurprise.mockResolvedValue({ scope: "both", items: [card("sp1", "Random Pick")] }); + const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } }); + const ui = ( + + {}} + onInfoCard={noop} + onGenre={noop} + onSeeAllRecent={noop} + /> + + ); + const first = render(ui); + await screen.findByText("Random Pick"); + first.unmount(); + render(ui); + await screen.findByText("Random Pick"); + act(() => { + focusManager.setFocused(false); + focusManager.setFocused(true); + }); + await new Promise((r) => setTimeout(r, 20)); + expect(plexSurprise).toHaveBeenCalledTimes(1); + focusManager.setFocused(undefined); + }); + it("shows the empty message when every rail is empty", async () => { plexDiscover.mockResolvedValue({ scope: "both", diff --git a/frontend/src/components/PlexDiscover.tsx b/frontend/src/components/PlexDiscover.tsx index a00c2a7e..ba27bf0c 100644 --- a/frontend/src/components/PlexDiscover.tsx +++ b/frontend/src/components/PlexDiscover.tsx @@ -134,7 +134,10 @@ export default function PlexDiscover({ shown.map((c) => c.id), ); }, - staleTime: 0, + // A draw stands until ↻ (or another scope, language or filter) asks for a new one. A stale one was + // redrawn on every remount — Back from the player or a show page — and on a return to the window, + // so the card just looked at was gone from the rail it came from. + staleTime: Infinity, }); // Watched toggle over BOTH this surface's cache (so a rail card flips instantly) and the surprise