feat(filters): pick one year from a decade grid, in the feed and in Plex
A shared YearPicker: the recent years as chips with their counts, and a More dialog that lays every year out by decade (sortable by count), so a ninety-year library fits on one screen. The feed's scrolling popover gives way to it; the Plex rail gets it above its range fields, a pick setting both ends. The Plex facets now count titles per year, the year filter left out.
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
// @vitest-environment jsdom
|
||||
import { describe, it, expect, vi, afterEach } from "vitest";
|
||||
import { render, screen, fireEvent, cleanup, within } from "@testing-library/react";
|
||||
|
||||
vi.mock("react-i18next", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("react-i18next")>();
|
||||
return {
|
||||
...actual,
|
||||
useTranslation: () => ({
|
||||
t: (k: string, o?: Record<string, unknown>) =>
|
||||
o && "from" in o ? `${k}:${String(o.from)}-${String(o.to)}` : k,
|
||||
}),
|
||||
};
|
||||
});
|
||||
vi.mock("../../lib/history", () => ({ useBackToClose: () => {} }));
|
||||
|
||||
import YearPicker from "./YearPicker";
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
// Eight years over three decades, 1987 and 2014 without titles.
|
||||
const YEARS = [
|
||||
{ year: 2026, count: 3 },
|
||||
{ year: 2024, count: 9 },
|
||||
{ year: 2023, count: 1 },
|
||||
{ year: 2021, count: 4 },
|
||||
{ year: 2020, count: 2 },
|
||||
{ year: 2015, count: 5 },
|
||||
{ year: 2013, count: 7 },
|
||||
{ year: 1985, count: 6 },
|
||||
];
|
||||
|
||||
const open = () => fireEvent.click(screen.getByRole("button", { name: /sidebar\.year\.more/ }));
|
||||
|
||||
describe("YearPicker", () => {
|
||||
it("shows the six newest years as chips, the selected one kept beside them", () => {
|
||||
render(<YearPicker years={YEARS} selected={1985} onPick={() => {}} />);
|
||||
const chips = screen.getAllByRole("button", { pressed: false }).map((b) => b.textContent);
|
||||
expect(chips.slice(0, 6)).toEqual(["20263", "20249", "20231", "20214", "20202", "20155"]);
|
||||
expect(screen.getByRole("button", { pressed: true }).textContent).toBe("19856");
|
||||
});
|
||||
|
||||
it("lays every year out by decade in the dialog; a year without titles is not a choice", () => {
|
||||
render(<YearPicker years={YEARS} onPick={() => {}} />);
|
||||
open();
|
||||
const dialog = screen.getByRole("dialog");
|
||||
const rows = within(dialog).getAllByRole("group", { name: /sidebar\.year\.decade/ });
|
||||
expect(rows.map((r) => r.getAttribute("aria-label"))).toEqual([
|
||||
"sidebar.year.decade:2020-2029",
|
||||
"sidebar.year.decade:2010-2019",
|
||||
"sidebar.year.decade:1980-1989",
|
||||
]);
|
||||
const in1980s = within(rows[2]!)
|
||||
.getAllByRole("button")
|
||||
.map((b) => b.dataset.year);
|
||||
expect(in1980s).toEqual(["1985"]);
|
||||
expect(rows[1]!.querySelector('[data-year="2014"]')).toBeNull();
|
||||
});
|
||||
|
||||
it("sorted by count, the busiest year comes first", () => {
|
||||
render(<YearPicker years={YEARS} onPick={() => {}} />);
|
||||
open();
|
||||
fireEvent.click(screen.getByRole("button", { name: "sidebar.year.sortCount" }));
|
||||
const order = within(screen.getByRole("dialog"))
|
||||
.getAllByRole("button")
|
||||
.map((b) => b.dataset.year)
|
||||
.filter(Boolean);
|
||||
expect(order.slice(0, 3)).toEqual(["2024", "2013", "1985"]);
|
||||
});
|
||||
|
||||
it("a pick in the dialog names the year and closes it; the selected year again clears it", () => {
|
||||
const onPick = vi.fn();
|
||||
const { rerender } = render(<YearPicker years={YEARS} onPick={onPick} />);
|
||||
open();
|
||||
fireEvent.click(screen.getByRole("dialog").querySelector('[data-year="1985"]')!);
|
||||
expect(onPick).toHaveBeenLastCalledWith(1985);
|
||||
expect(screen.queryByRole("dialog")).toBeNull();
|
||||
|
||||
rerender(<YearPicker years={YEARS} selected={2024} onPick={onPick} />);
|
||||
fireEvent.click(screen.getByRole("button", { pressed: true }));
|
||||
expect(onPick).toHaveBeenLastCalledWith(undefined);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user