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 = {}) { 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(); 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", ]); }); });