Files
siftlode/frontend/src/components/ui/DataTable.cards.dom.test.tsx
T
peter c910cf2f20 fix: review round 1 — row press after a rename, related reset, dead items on removal, honest Prev/Next
- A press that begins while a field in the row is edited only ends the editing (rowOpen latches it
  at pointerdown); the card layout's row press is now tested.
- A related video reset in the player forgets the session's stored position.
- Removing the playing video passes over known-dead items and steps the way it went.
- Prev/Next off only because of dead items stay focusable and say why (HU/EN).
- The docked bar's scroller leaves room for focus rings.
- A focus-opened About card is not closed by its own scroll into view.
- EN "Clear watch progress" for the video reset, distinct from a page's "Reset view".
- The signed-out title read goes to the page yt-dlp read; the retitle writes are conditional.
- Tests: the cap of three errors, the bar's own Fullscreen, the group glyph, the backfill's reads.
2026-11-01 05:36:59 +01:00

64 lines
2.2 KiB
TypeScript

// @vitest-environment jsdom
//
// Below `md` a table is a list of cards, its columns flowing one after another. A column marked
// `cardRow` takes a line of its own there — a row's lone "…" otherwise landed at the end of one
// card's line and on the next line of another. A card is its row's press surface too, as the row is.
import { describe, it, expect, afterEach, vi } from "vitest";
import { render, cleanup, screen, fireEvent } from "@testing-library/react";
import DataTable, { type Column } from "./DataTable";
vi.mock("react-i18next", async (importOriginal) => ({
...(await importOriginal<typeof import("react-i18next")>()),
useTranslation: () => ({ i18n: { language: "en" }, t: (key: string) => key }),
}));
const narrow = (matches: boolean) =>
vi.stubGlobal(
"matchMedia",
(query: string) =>
({
matches,
media: query,
addEventListener: () => {},
removeEventListener: () => {},
}) as unknown as MediaQueryList,
);
afterEach(() => {
cleanup();
vi.unstubAllGlobals();
});
type Row = { id: string };
const columns: Column<Row>[] = [
{ key: "name", header: "Name", cardPrimary: true, render: (r) => r.id },
{ key: "size", header: "Size", render: () => "1 MB" },
{ key: "menu", header: "", cardLabel: false, cardRow: true, render: () => <button>more</button> },
];
describe("DataTable cards", () => {
it("gives a cardRow column a line of its own; the others flow", () => {
narrow(false);
render(<DataTable rows={[{ id: "a" }]} columns={columns} rowKey={(r) => r.id} />);
expect(screen.getByText("more").parentElement!.className).toContain("basis-full");
expect(screen.getByText("1 MB").parentElement!.className).not.toContain("basis-full");
});
it("opens its object from a tap on the card, and leaves its control's tap to the control", () => {
narrow(false);
const open = vi.fn();
render(
<DataTable
rows={[{ id: "a" }]}
columns={columns}
rowKey={(r) => r.id}
rowOpen={() => open}
/>,
);
fireEvent.click(screen.getByText("1 MB"), { detail: 1 });
expect(open).toHaveBeenCalledTimes(1);
fireEvent.click(screen.getByText("more"), { detail: 1 });
expect(open).toHaveBeenCalledTimes(1);
});
});