110 lines
3.3 KiB
TypeScript
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",
|
|
]);
|
|
});
|
|
});
|