mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-14 18:01:06 +00:00
Fixes a bug where the input `value` is immediately reset when re-focusing the input. The `value` resetting is necessary to support programmatically clearing the value, but it should only execute if the input is not currently focused.
204 lines
5.9 KiB
TypeScript
204 lines
5.9 KiB
TypeScript
import { render, screen } from "@testing-library/svelte";
|
|
import { user } from "../setup-tests";
|
|
import ComboBox from "./ComboBox.test.svelte";
|
|
import ComboBoxCustom from "./ComboBoxCustom.test.svelte";
|
|
|
|
describe("ComboBox", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it("should render with default props", () => {
|
|
render(ComboBox);
|
|
|
|
expect(screen.getByText("Contact")).toBeInTheDocument();
|
|
const input = screen.getByRole("textbox");
|
|
expect(input).toHaveAttribute("placeholder", "Select contact method");
|
|
});
|
|
|
|
it("should open menu on click", async () => {
|
|
render(ComboBox);
|
|
|
|
const input = screen.getByRole("textbox");
|
|
await user.click(input);
|
|
|
|
const dropdown = screen.getAllByRole("listbox")[1];
|
|
expect(dropdown).toBeVisible();
|
|
});
|
|
|
|
it("should handle item selection", async () => {
|
|
const consoleLog = vi.spyOn(console, "log");
|
|
render(ComboBox);
|
|
|
|
await user.click(screen.getByRole("textbox"));
|
|
await user.click(screen.getByText("Email"));
|
|
|
|
expect(consoleLog).toHaveBeenCalledWith("select", {
|
|
selectedId: "1",
|
|
selectedItem: { id: "1", text: "Email" },
|
|
});
|
|
expect(screen.getByRole("textbox")).toHaveValue("Email");
|
|
});
|
|
|
|
it("should handle keyboard navigation", async () => {
|
|
render(ComboBox);
|
|
|
|
const input = screen.getByRole("textbox");
|
|
await user.click(input);
|
|
await user.keyboard("{ArrowDown}");
|
|
await user.keyboard("{Enter}");
|
|
|
|
expect(input).toHaveValue("Slack");
|
|
});
|
|
|
|
it("should handle clear selection", async () => {
|
|
const consoleLog = vi.spyOn(console, "log");
|
|
render(ComboBox, {
|
|
props: {
|
|
selectedId: "1",
|
|
value: "Email",
|
|
},
|
|
});
|
|
|
|
const clearButton = screen.getByRole("button", { name: /clear/i });
|
|
await user.click(clearButton);
|
|
|
|
expect(consoleLog).toHaveBeenCalledWith("clear", expect.any(String));
|
|
expect(screen.getByRole("textbox")).toHaveValue("");
|
|
});
|
|
|
|
it("should handle disabled state", () => {
|
|
render(ComboBox, { props: { disabled: true } });
|
|
|
|
expect(screen.getByRole("textbox")).toBeDisabled();
|
|
expect(screen.getByText("Contact")).toHaveClass("bx--label--disabled");
|
|
});
|
|
|
|
it("should handle invalid state", () => {
|
|
render(ComboBox, {
|
|
props: {
|
|
invalid: true,
|
|
invalidText: "Invalid selection",
|
|
},
|
|
});
|
|
|
|
expect(screen.getByRole("listbox")).toHaveAttribute("data-invalid", "true");
|
|
expect(screen.getByText("Invalid selection")).toBeInTheDocument();
|
|
});
|
|
|
|
it("should handle warning state", () => {
|
|
render(ComboBox, {
|
|
props: {
|
|
warn: true,
|
|
warnText: "Warning message",
|
|
},
|
|
});
|
|
|
|
expect(screen.getByText("Warning message")).toBeInTheDocument();
|
|
});
|
|
|
|
it("should handle helper text", () => {
|
|
render(ComboBox, { props: { helperText: "Helper message" } });
|
|
|
|
expect(screen.getByText("Helper message")).toBeInTheDocument();
|
|
});
|
|
|
|
it("should handle light variant", () => {
|
|
render(ComboBox, { props: { light: true } });
|
|
|
|
expect(screen.getByRole("textbox")).toHaveClass("bx--text-input--light");
|
|
});
|
|
|
|
test.each([
|
|
["sm", "bx--list-box--sm"],
|
|
["xl", "bx--list-box--xl"],
|
|
] as const)("should handle size variants", (size, className) => {
|
|
render(ComboBox, { props: { size } });
|
|
expect(screen.getByRole("listbox")).toHaveClass(className);
|
|
});
|
|
|
|
it("should handle filtering items", async () => {
|
|
render(ComboBox);
|
|
|
|
const input = screen.getByRole("textbox");
|
|
await user.click(input);
|
|
await user.type(input, "em");
|
|
|
|
const options = screen.getAllByRole("option");
|
|
expect(options).toHaveLength(1);
|
|
expect(options[0]).toHaveTextContent("Email");
|
|
|
|
await user.clear(input);
|
|
expect(input).toHaveValue("");
|
|
expect(screen.getAllByRole("option")).toHaveLength(3);
|
|
|
|
await user.click(document.body);
|
|
expect(input).not.toHaveFocus();
|
|
|
|
await user.keyboard("{Tab}");
|
|
expect(input).toHaveFocus();
|
|
|
|
await user.type(input, "a");
|
|
await user.click(screen.getAllByRole("option")[1]);
|
|
expect(input).toHaveValue("Email");
|
|
|
|
await user.click(document.body);
|
|
expect(input).not.toHaveFocus();
|
|
expect(screen.queryByRole("option")).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("should handle disabled items", async () => {
|
|
render(ComboBoxCustom);
|
|
|
|
await user.click(screen.getByRole("textbox"));
|
|
const disabledOption = screen.getByText(/Fax/).closest('[role="option"]');
|
|
assert(disabledOption);
|
|
expect(disabledOption).toHaveAttribute("disabled", "true");
|
|
|
|
await user.click(disabledOption);
|
|
expect(screen.getByRole("textbox")).toHaveValue("");
|
|
|
|
// Dropdown remains open
|
|
const dropdown = screen.getAllByRole("listbox")[1];
|
|
expect(dropdown).toBeVisible();
|
|
});
|
|
|
|
it("should handle custom item display", async () => {
|
|
render(ComboBoxCustom);
|
|
|
|
await user.click(screen.getByRole("textbox"));
|
|
const options = screen.getAllByRole("option");
|
|
|
|
expect(options[0]).toHaveTextContent("Item Slack");
|
|
expect(options[1]).toHaveTextContent("Item Email");
|
|
expect(options[2]).toHaveTextContent("Item Fax");
|
|
});
|
|
|
|
it("should handle top direction", async () => {
|
|
render(ComboBoxCustom, { props: { direction: "top" } });
|
|
|
|
await user.click(screen.getAllByRole("button")[0]);
|
|
expect(screen.getByRole("listbox")).toHaveClass("bx--list-box--up");
|
|
});
|
|
|
|
it("should programmatically clear selection", async () => {
|
|
render(ComboBoxCustom, { props: { selectedId: "1" } });
|
|
|
|
expect(screen.getByRole("textbox")).toHaveValue("Email");
|
|
await user.click(screen.getByText("Clear"));
|
|
expect(screen.getByRole("textbox")).toHaveValue("");
|
|
});
|
|
|
|
it("should close menu on Escape key", async () => {
|
|
render(ComboBox);
|
|
|
|
const input = screen.getByRole("textbox");
|
|
await user.click(input);
|
|
|
|
const dropdown = screen.getAllByRole("listbox")[1];
|
|
expect(dropdown).toBeVisible();
|
|
|
|
await user.keyboard("{Escape}");
|
|
expect(dropdown).not.toBeVisible();
|
|
});
|
|
});
|