Files
sudoku-tools/tests/components/aidMemoire.test.tsx
T

149 lines
4.9 KiB
TypeScript

import { useState } from "react";
import { fireEvent, render, screen, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import { AidMemoire } from "../../src/components/AidMemoire";
import {
configureAidMemoire,
createAidMemoire,
type AidMemoireState,
} from "../../src/state/aidMemoire";
import type { EntryMode } from "../../src/state/session";
function Harness({
initial,
readOnly = false,
}: {
initial?: AidMemoireState;
readOnly?: boolean;
}) {
const [state, setState] = useState(
initial ?? createAidMemoire(9, { enabled: true }),
);
const [selected, setSelected] = useState(0);
const [active, setActive] = useState(false);
const [mode, setMode] = useState<EntryMode>("value");
return (
<AidMemoire
size={9}
state={state}
selectedCell={selected}
active={active}
readOnly={readOnly}
mode={mode}
onStateChange={setState}
onSelect={(cell) => {
setSelected(cell);
setActive(true);
}}
onMode={setMode}
/>
);
}
describe("aid-mémoire component", () => {
it("renders normal-like cells with keyboard entry and full descriptions", async () => {
const user = userEvent.setup();
render(<Harness />);
const grid = screen.getByRole("grid", {
name: "9 aid-mémoire scratch cells",
});
expect(within(grid).getAllByRole("row")).toHaveLength(1);
const first = within(grid).getByRole("gridcell", {
name: "Aid-mémoire cell 1, label 1, empty",
});
expect(first).toHaveAttribute("aria-colindex", "1");
await user.click(first);
await user.keyboard("4");
expect(
within(grid).getByRole("gridcell", {
name: "Aid-mémoire cell 1, label 1, value 4",
}),
).toHaveAttribute("aria-selected", "true");
const second = within(grid).getByRole("gridcell", {
name: "Aid-mémoire cell 2, label 2, empty",
});
second.focus();
await user.keyboard("c7");
expect(
within(grid).getByRole("gridcell", {
name: "Aid-mémoire cell 2, label 2, empty, centre marks 7",
}),
).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Centre" })).toHaveAttribute(
"aria-pressed",
"true",
);
});
it("uses row-aware WAI grid navigation without horizontal wrapping", () => {
const initial = configureAidMemoire(
createAidMemoire(9, { enabled: true }),
9,
5,
2,
);
render(<Harness initial={initial} />);
const cells = screen.getAllByRole("gridcell");
const rows = screen.getAllByRole("row");
expect(rows[0]).toHaveAttribute("aria-rowindex", "1");
expect(rows[2]).toHaveAttribute("aria-rowindex", "3");
expect(cells[2]).toHaveAttribute("aria-colindex", "1");
cells[1]!.focus();
fireEvent.keyDown(cells[1]!, { key: "ArrowRight" });
expect(document.activeElement).toBe(cells[1]);
fireEvent.keyDown(cells[1]!, { key: "Home" });
expect(document.activeElement).toBe(cells[0]);
fireEvent.keyDown(cells[0]!, { key: "End", ctrlKey: true });
expect(document.activeElement).toBe(cells[4]);
fireEvent.keyDown(cells[4]!, { key: "PageUp" });
expect(document.activeElement).toBe(cells[0]);
fireEvent.keyDown(cells[0]!, { key: "PageDown" });
expect(document.activeElement).toBe(cells[4]);
});
it("keeps read-only replay cells navigable without allowing edits", () => {
const initial = configureAidMemoire(
createAidMemoire(9, { enabled: true }),
9,
4,
2,
);
render(<Harness initial={initial} readOnly />);
const cells = screen.getAllByRole("gridcell");
cells[0]!.focus();
fireEvent.keyDown(cells[0]!, { key: "ArrowDown" });
expect(document.activeElement).toBe(cells[2]);
fireEvent.keyDown(cells[2]!, { key: "5" });
expect(cells[2]).toHaveAccessibleName("Aid-mémoire cell 3, label 3, empty");
});
it("edits labels, reflows, clears entries and resets with confirmation", async () => {
const user = userEvent.setup();
vi.spyOn(window, "confirm").mockReturnValue(true);
render(<Harness />);
const label = screen.getByLabelText("Selected cell label");
await user.clear(label);
await user.type(label, "Pseudo A");
expect(
screen.getByRole("gridcell", {
name: "Aid-mémoire cell 1, label Pseudo A, empty",
}),
).toBeInTheDocument();
await user.click(screen.getByText("Configure scratch layout"));
await user.click(screen.getByRole("button", { name: "Compact grid" }));
expect(screen.getByLabelText("Columns")).toHaveValue(3);
await user.click(screen.getByRole("button", { name: "Clear entries" }));
await user.click(screen.getByRole("button", { name: "Reset all" }));
expect(window.confirm).toHaveBeenCalledTimes(2);
expect(screen.getByLabelText("Columns")).toHaveValue(9);
expect(screen.getByLabelText("Selected cell label")).toHaveValue("1");
});
});