feat: complete advanced Sudoku workbench
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
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",
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user