fix(ui): review round 2 — reveal floor, failed next page, count states, row Play

- DataTable: the reveal floor holds only in the view it was made for (Channels
  never clears its follow, so every later sort mounted rows up to it)
- Feed + Plex browse: a failed next page stops the read-ahead and shows a row
  that retries, instead of re-requesting it once a round-trip
- the YouTube Load more click uses nextPageOnClick; a contract pins NEXT_PAGE
  to the read-aheads and the click sites to nextPageOnClick
- ItemCount: a failed count says so; a stale one says updating to a screen reader
- the narrow-picture Play lift applies only where a hover row is there to clear
- PlayerModal: one description ladder for the popover and the panel, both tested
- plexImage contract reads every img src, any attribute order
- Tabs comment names who persists the sub-tab
This commit is contained in:
2026-10-03 02:25:15 +02:00
parent c4c442bc5b
commit b40440b825
17 changed files with 360 additions and 63 deletions
@@ -95,4 +95,21 @@ describe("Feed — the count while a new search's count loads", () => {
await waitFor(() => expect(pill().getAttribute("title")).toBe("178,991"));
expect(pill().getAttribute("aria-busy")).toBeNull();
});
it("says the count failed instead of showing the empty box of a first load", async () => {
vi.spyOn(api, "feed").mockResolvedValue({ items: [], next_cursor: null } as never);
vi.spyOn(api, "feedSummary").mockImplementation(((f: FeedFilters) =>
f.q === "kitchen"
? Promise.resolve({ count: 1937, facets: {} })
: Promise.reject(new Error("boom"))) as never);
const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
qc.setQueryData(qk.me(), { id: 1, can_write: true, prefs: {} });
const pill = () => screen.getByTestId("item-count");
const view = render(feed("kitchen", qc));
await waitFor(() => expect(pill().getAttribute("title")).toBe("1,937"));
view.rerender(feed("a", qc));
await waitFor(() => expect(pill().getAttribute("title")).toBe("common.countFailed"));
expect(pill().getAttribute("aria-busy")).toBeNull();
});
});