fix(home): shelf honours the Plex gate; hero unpins its origin; palette asks for a surprise
- A13: with Plex off, the Home shelf and the hero's comfort tier go YouTube-only like the rails beside them (owner's call: hide the tiles). The pins are kept; GET /pins still lists them. - Reorder deals the listed pins into the slots they already hold, so a partial list (hidden Plex pins, a stale tab) no longer puts two pins on one position; repeats are ignored. - A21: a comfort hero carries `pinned_from`, the shelf entry it was resolved from; its menu acts on that pin, so a pinned show's next episode offers "Unpin" instead of creating a second pin. - B12: the palette's "Meglepetés" asks for the surprise tier (the next press leading with it); the rotation carries on from there. - B13: the surprise token names the history entry it was requested for (minted by setPage's new `then`, after the push) and is dropped on any other entry, so a navigation that never mounted Home cannot replay it later.
This commit is contained in:
@@ -52,6 +52,7 @@ vi.mock("../lib/api", () => ({
|
||||
downloadIndex: () => Promise.resolve({}), // the cards' download buttons read it
|
||||
},
|
||||
DISCOVER_BUDGETS: ["short", "medium", "long", "any"],
|
||||
HERO_TIERS: ["resume", "comfort", "surprise"],
|
||||
discoverCardKey: (c: { source: string; id: string }) => `${c.source}:${c.id}`,
|
||||
}));
|
||||
|
||||
@@ -609,8 +610,38 @@ describe("Home", () => {
|
||||
);
|
||||
expect(await screen.findByText("Rerolled")).toBeTruthy();
|
||||
expect(discoverPick).toHaveBeenCalledTimes(1);
|
||||
// …and on the press count the server reads as "which tier answers first".
|
||||
expect(discoverPick).toHaveBeenCalledWith("any", expect.any(Number), [], 1);
|
||||
// …and on the press count the server reads as "which tier answers first": 2 leads with the
|
||||
// SURPRISE tier, which is what a command labelled "Meglepetés" promised. A plain next press (1)
|
||||
// led with the shelf, so anyone with one got "A polcodról" instead (owner's call, 2026-09-19).
|
||||
expect(discoverPick).toHaveBeenCalledWith("any", expect.any(Number), [], 2);
|
||||
});
|
||||
|
||||
// The rotation carries on from the requested tier: the page's own button after a palette surprise
|
||||
// is the NEXT tier (resume), not a second surprise and not a jump back to press 1.
|
||||
it("lets the button's next press carry the rotation on from the requested tier", async () => {
|
||||
discoverPick.mockResolvedValue({
|
||||
budget: "any",
|
||||
hero: { tier: "surprise", card: ytCard("v9", "Rerolled") },
|
||||
});
|
||||
requestSurprise();
|
||||
mount();
|
||||
expect(await screen.findByText("Rerolled")).toBeTruthy();
|
||||
fireEvent.click(screen.getByText("home.hero.reroll"));
|
||||
await waitFor(() => expect(discoverPick).toHaveBeenCalledTimes(2));
|
||||
expect(discoverPick.mock.lastCall?.[3]).toBe(3);
|
||||
});
|
||||
|
||||
// A token minted for a navigation that never mounted Home (a failed lazy chunk, a Back before
|
||||
// the module arrived) must not replay on the NEXT visit: it names the history entry it was
|
||||
// requested for, and Home mounting on any other entry drops it.
|
||||
it("drops a surprise request that was made for another history entry", async () => {
|
||||
requestSurprise();
|
||||
window.history.pushState(null, "");
|
||||
mount();
|
||||
await screen.findByText("Hero v1");
|
||||
expect(discoverPick).not.toHaveBeenCalled();
|
||||
// …and it is spent, not merely skipped: the entry it named does not revive it either.
|
||||
expect(takeSurprise()).toBe(false);
|
||||
});
|
||||
|
||||
it("says the shelf is empty rather than hiding it", async () => {
|
||||
|
||||
Reference in New Issue
Block a user