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

110 lines
3.3 KiB
TypeScript

import { render, screen, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import { LibraryDialog } from "../../src/components/LibraryDialog";
const summaries = [
{
id: "killer",
title: "Evening Killer",
createdAt: 1,
updatedAt: 2,
size: 4,
completed: false,
tags: ["killer", "hard"],
thumbnail: "1...............",
},
{
id: "classic",
title: "Morning Classic",
createdAt: 1,
updatedAt: 3,
size: 4,
completed: true,
tags: ["classic"],
thumbnail: "....2...........",
},
] as const;
function renderDialog(overrides: Record<string, unknown> = {}) {
const props = {
open: true,
summaries,
mode: "indexeddb" as const,
busy: false,
onClose: vi.fn(),
onSave: vi.fn(),
onOpen: vi.fn(),
onDelete: vi.fn(),
onClear: vi.fn(),
onExport: vi.fn(),
onExportSelected: vi.fn(),
onDuplicateSelected: vi.fn(),
onDeleteSelected: vi.fn(),
onUpdateTags: vi.fn(),
onImport: vi.fn(),
...overrides,
};
render(<LibraryDialog {...props} />);
return props;
}
describe("LibraryDialog", () => {
it("filters by text, tag and completion while showing safe previews", async () => {
const user = userEvent.setup();
renderDialog();
expect(
screen.getAllByRole("img", { name: /puzzle preview/u }),
).toHaveLength(2);
await user.type(screen.getByRole("searchbox"), "killer");
expect(screen.getByText("Evening Killer")).toBeInTheDocument();
expect(screen.queryByText("Morning Classic")).not.toBeInTheDocument();
await user.clear(screen.getByRole("searchbox"));
await user.selectOptions(
screen.getByLabelText("Completion filter"),
"complete",
);
expect(screen.getByText("Morning Classic")).toBeInTheDocument();
expect(screen.queryByText("Evening Killer")).not.toBeInTheDocument();
});
it("exports, duplicates and deletes an explicit selection", async () => {
const user = userEvent.setup();
const props = renderDialog();
await user.click(screen.getByLabelText("Select Evening Killer"));
const selection = screen.getByText(/1 selected/u).parentElement!;
await user.click(
within(selection).getByRole("button", { name: "Export selected" }),
);
await user.click(
within(selection).getByRole("button", { name: "Duplicate selected" }),
);
await user.click(
within(selection).getByRole("button", { name: "Delete selected" }),
);
expect(props.onExportSelected).toHaveBeenCalledWith(["killer"]);
expect(props.onDuplicateSelected).toHaveBeenCalledWith(["killer"]);
expect(props.onDeleteSelected).toHaveBeenCalledWith(["killer"]);
});
it("edits bounded comma-separated tags", async () => {
const user = userEvent.setup();
const props = renderDialog();
const item = screen.getByText("Evening Killer").closest("li")!;
await user.click(within(item).getByRole("button", { name: "Edit tags" }));
const input = within(item).getByLabelText("Tags for Evening Killer");
await user.clear(input);
await user.type(input, "killer, weekend");
await user.click(within(item).getByRole("button", { name: "Apply" }));
expect(props.onUpdateTags).toHaveBeenCalledWith("killer", [
"killer",
"weekend",
]);
});
});