fix(plex): address S3 review nits — tests + narrow-header wrap
- Add PlexScopeToggle.dom.test.tsx (renders the three scopes, current one pressed, click writes scope back to the provider) and usePlexActiveFilters.dom.test.tsx (emits filter + watch-state chips but never a sort chip, even with a non-default sort active) — the S3 relocation was untested. - Narrow-width header: make the header row flex-wrap so the scope toggle drops to a second line instead of crowding the flex-1 search box to zero width, and let the field-scope pill shrink/truncate. Desktop stays a single line (verified: 1280px header unchanged, search 237px, no wrap). The removed one-click sort-reset chip is intended (sort is an always-visible control now, like the Feed) — no change. FE suite 174 green; typecheck + eslint clean.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
// @vitest-environment jsdom
|
||||
//
|
||||
// Contract of the header library-scope toggle (S3 relocation): it renders the three scopes, marks
|
||||
// the current one, and writes the picked scope back to the provider. i18n is key-passthrough and the
|
||||
// provider is mocked so the test drives scope directly; SegmentedToggle is a plain button group (no
|
||||
// floating-ui), so no observer stubs are needed.
|
||||
import { describe, it, expect, afterEach, beforeEach, vi } from "vitest";
|
||||
import { render, screen, fireEvent, cleanup } from "@testing-library/react";
|
||||
|
||||
vi.mock("react-i18next", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("react-i18next")>();
|
||||
return { ...actual, useTranslation: () => ({ t: (key: string) => key }) };
|
||||
});
|
||||
|
||||
const plexState = { scope: "both" } as { scope: string };
|
||||
const setScope = vi.fn();
|
||||
vi.mock("./PlexProvider", () => ({
|
||||
usePlex: () => plexState,
|
||||
usePlexActions: () => ({ setScope }),
|
||||
}));
|
||||
|
||||
import PlexScopeToggle from "./PlexScopeToggle";
|
||||
|
||||
beforeEach(() => {
|
||||
plexState.scope = "both";
|
||||
setScope.mockReset();
|
||||
});
|
||||
afterEach(cleanup);
|
||||
|
||||
describe("PlexScopeToggle", () => {
|
||||
it("renders the three library scopes, current one pressed", () => {
|
||||
plexState.scope = "movie";
|
||||
render(<PlexScopeToggle />);
|
||||
const group = screen.getByRole("group", { name: "plex.filter.scope" });
|
||||
const btns = [...group.querySelectorAll("button")];
|
||||
expect(btns.map((b) => b.textContent)).toEqual([
|
||||
"plex.filter.scopeOpt.both",
|
||||
"plex.filter.scopeOpt.movie",
|
||||
"plex.filter.scopeOpt.show",
|
||||
]);
|
||||
const pressed = btns.filter((b) => b.getAttribute("aria-pressed") === "true");
|
||||
expect(pressed.map((b) => b.textContent)).toEqual(["plex.filter.scopeOpt.movie"]);
|
||||
});
|
||||
|
||||
it("writes the picked scope back to the provider", () => {
|
||||
render(<PlexScopeToggle />);
|
||||
fireEvent.click(screen.getByRole("button", { name: "plex.filter.scopeOpt.show" }));
|
||||
expect(setScope).toHaveBeenCalledWith("show");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user