Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/components/ui/input/InputCombobox.test.tsx
T

81 lines
2.9 KiB
TypeScript

import "@testing-library/jest-dom";
import { fireEvent, render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router";
import { describe, expect, it, vi } from "vitest";
import InputCombobox from "./InputCombobox";
vi.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key: string) => {
const translations: Record<string, string> = {
"shared.clear": "Clear",
"shared.new": "New",
"shared.noRecords": "No records",
"shared.searchDot": "Search...",
"shared.select": "Select",
"shared.selectedCount": "selected",
};
return translations[key] ?? key;
},
}),
}));
const manyOptions = Array.from({ length: 12 }, (_, index) => ({
value: `option-${index}`,
name: `Option ${index}`,
}));
function renderCombobox(ui: React.ReactElement) {
return render(<MemoryRouter>{ui}</MemoryRouter>);
}
describe("InputCombobox", () => {
it("keeps the clear control reachable with a visible keyboard focus style", () => {
const onClear = vi.fn();
renderCombobox(<InputCombobox title="Workspace" value={["option-1"]} options={[{ value: "option-1", name: "Acme workspace" }]} onClear={onClear} />);
const clearButton = screen.getByRole("button", { name: "Clear" });
expect(clearButton).toHaveClass("min-h-8", "shrink-0", "focus-visible:ring-2");
fireEvent.click(clearButton);
expect(onClear).toHaveBeenCalledTimes(1);
});
it("gives the icon-only new button an accessible name and stable hit area", () => {
const onNew = vi.fn();
renderCombobox(<InputCombobox title="Workspace" options={manyOptions} onNew={onNew} />);
const newButton = screen.getByRole("button", { name: "New" });
expect(newButton).toHaveClass("h-9", "w-10", "shrink-0", "focus-visible:ring-2");
fireEvent.click(newButton);
expect(onNew).toHaveBeenCalledTimes(1);
});
it("keeps route-based icon-only creation and the popover constrained on mobile", () => {
renderCombobox(<InputCombobox title="Workspace" options={manyOptions} onNewRoute="/admin/workspaces/new" />);
const newLink = screen.getByRole("link", { name: "New" });
expect(newLink).toHaveAttribute("href", "/admin/workspaces/new");
expect(newLink).toHaveClass("h-9", "w-10", "shrink-0", "focus-visible:ring-2");
fireEvent.click(screen.getByText("Select...").closest("button") as HTMLButtonElement);
expect(screen.getByRole("listbox").parentElement).toHaveClass("max-w-[calc(100vw-2rem)]", "overflow-hidden");
expect(screen.getByRole("listbox")).toHaveClass("max-h-72", "overflow-auto");
});
it("localizes collapsed multi-select counts instead of appending hard-coded English", () => {
renderCombobox(<InputCombobox title="Workspace" value={["option-1", "option-2", "option-3"]} options={manyOptions} minDisplayCount={3} />);
expect(screen.getByRole("button", { name: /workspace selected/i })).toBeInTheDocument();
});
});