chore(test): update testing libraries and refactor (#3886)

This commit is contained in:
Ryo Matsukawa 2024-10-14 23:13:04 +09:00 committed by GitHub
parent 3bc2490156
commit 507887eac3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 1179 additions and 1477 deletions

View File

@ -10,7 +10,7 @@ ReactDOM.createRoot(document.getElementById("root")).render(
<NextUIProvider>
<div className="w-screen h-screen p-8 flex items-start justify-center">
<App />
</div>
</div>
</NextUIProvider>
</React.StrictMode>
);`;

View File

@ -18,7 +18,7 @@ module.exports = {
],
},
transformIgnorePatterns: ["[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$"],
setupFilesAfterEnv: ["@testing-library/jest-dom/extend-expect", "./scripts/setup-test.ts"],
setupFilesAfterEnv: ["@testing-library/jest-dom", "./scripts/setup-test.ts"],
globals: {
"ts-jest": {
tsconfig: "tsconfig.json",

View File

@ -73,17 +73,15 @@
"@swc-node/jest": "^1.5.2",
"@swc/core": "^1.3.35",
"@swc/jest": "^0.2.24",
"@testing-library/dom": "^8.1.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^14.0.0",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.4.3",
"@types/jest": "^28.1.1",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.13",
"@types/node": "^15.12.4",
"@types/react": "^18.0.1",
"@types/react-dom": "^18.0.0",
"@types/shelljs": "^0.8.9",
"@types/testing-library__jest-dom": "5.14.5",
"@typescript-eslint/eslint-plugin": "^5.42.0",
"@typescript-eslint/parser": "^5.42.0",
"chalk": "^4.1.2",
@ -115,8 +113,8 @@
"gray-matter": "^4.0.3",
"husky": "^8.0.1",
"intl-messageformat": "^10.1.0",
"jest": "^28.1.1",
"jest-environment-jsdom": "^28.1.1",
"jest": "^29.7.0",
"jest-environment-jsdom": "^28.1.3",
"jest-watch-typeahead": "1.1.0",
"lint-staged": "^13.0.3",
"npm-check-updates": "^16.10.18",

View File

@ -30,7 +30,7 @@ describe("Accordion", () => {
expect(() => wrapper.unmount()).not.toThrow();
expect(spy).toBeCalledTimes(0);
expect(spy).toHaveBeenCalledTimes(0);
});
it("ref should be forwarded", () => {
@ -121,9 +121,7 @@ describe("Accordion", () => {
expect(button).toHaveAttribute("aria-expanded", "false");
await act(async () => {
await user.click(button);
});
await user.click(button);
expect(button).toHaveAttribute("aria-expanded", "true");
});
@ -163,18 +161,12 @@ describe("Accordion", () => {
const second = wrapper.getByTestId("item-2");
const secondButton = second.querySelector("button") as HTMLElement;
act(() => {
focus(firstButton);
});
await act(async () => {
await user.keyboard("[ArrowDown]");
});
await focus(firstButton);
await user.keyboard("[ArrowDown]");
expect(secondButton).toHaveFocus();
await act(async () => {
await user.keyboard("[ArrowUp]");
});
await user.keyboard("[ArrowUp]");
expect(firstButton).toHaveFocus();
});
@ -200,14 +192,10 @@ describe("Accordion", () => {
focus(secondButton);
});
await act(async () => {
await user.keyboard("[Home]");
});
await user.keyboard("[Home]");
expect(firstButton).toHaveFocus();
await act(async () => {
await user.keyboard("[End]");
});
await user.keyboard("[End]");
expect(secondButton).toHaveFocus();
});
@ -233,9 +221,7 @@ describe("Accordion", () => {
focus(firstButton);
});
await act(async () => {
await user.keyboard("[Tab]");
});
await user.keyboard("[Tab]");
expect(secondButton).toHaveFocus();
});
@ -276,10 +262,7 @@ describe("Accordion", () => {
expect(button).toHaveAttribute("aria-expanded", "false");
await act(async () => {
await user.click(button);
});
await user.click(button);
expect(button).toHaveAttribute("aria-expanded", "true");
});
@ -300,17 +283,11 @@ describe("Accordion", () => {
expect(item1.querySelector("[role='region']")).toBeInTheDocument();
await act(async () => {
await user.click(button);
});
await user.click(button);
const item2 = wrapper.getByTestId("item-2");
const button2 = item2.querySelector("button") as HTMLElement;
await act(async () => {
await user.click(button2);
});
await user.click(button2);
expect(item1.querySelector("[role='region']")).toBeInTheDocument();
expect(item2.querySelector("[role='region']")).toBeInTheDocument();
});
@ -331,29 +308,22 @@ describe("Accordion", () => {
const firstButton = await wrapper.getByRole("button", {name: "Accordion Item 1"});
await act(() => {
act(() => {
focus(firstButton);
});
await act(async () => {
await user.keyboard("[Tab]");
});
await user.keyboard("[Tab]");
expect(input).toHaveFocus();
await act(async () => {
await user.keyboard("aaa");
});
await user.keyboard("aaa");
expect(input).toHaveValue("aaa");
await act(async () => {
await user.keyboard("[ArrowLeft]");
await user.keyboard("b");
});
await user.keyboard("[ArrowLeft]");
await user.keyboard("b");
expect(input).toHaveValue("aaba");
await act(async () => {
await user.keyboard("[ArrowRight]");
await user.keyboard("c");
});
await user.keyboard("[ArrowRight]");
await user.keyboard("c");
expect(input).toHaveValue("aabac");
});

View File

@ -1,6 +1,6 @@
import * as React from "react";
import {within, render, renderHook, act} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {useForm} from "react-hook-form";
import {Autocomplete, AutocompleteItem, AutocompleteProps, AutocompleteSection} from "../src";
@ -77,6 +77,12 @@ const AutocompleteExample = (props: Partial<AutocompleteProps> = {}) => (
);
describe("Autocomplete", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
it("should render correctly", () => {
const wrapper = render(<AutocompleteExample />);
@ -172,9 +178,7 @@ describe("Autocomplete", () => {
const autocomplete = wrapper.getByTestId("autocomplete");
// open the select listbox
await act(async () => {
await userEvent.click(autocomplete);
});
await user.click(autocomplete);
// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
@ -201,9 +205,7 @@ describe("Autocomplete", () => {
const autocomplete = wrapper.getByTestId("autocomplete");
// open the select listbox
await act(async () => {
await userEvent.click(autocomplete);
});
await user.click(autocomplete);
// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
@ -211,9 +213,7 @@ describe("Autocomplete", () => {
let options = wrapper.getAllByRole("option");
// select the target item
await act(async () => {
await userEvent.click(options[0]);
});
await user.click(options[0]);
const {container} = wrapper;
@ -224,9 +224,7 @@ describe("Autocomplete", () => {
expect(clearButton).not.toBeNull();
// click the clear button
await act(async () => {
await userEvent.click(clearButton);
});
await user.click(clearButton);
// assert that the input has empty value
expect(autocomplete).toHaveValue("");
@ -253,9 +251,7 @@ describe("Autocomplete", () => {
const autocomplete = wrapper.getByTestId("autocomplete");
// open the select listbox
await act(async () => {
await userEvent.click(autocomplete);
});
await user.click(autocomplete);
// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
@ -263,9 +259,7 @@ describe("Autocomplete", () => {
let options = wrapper.getAllByRole("option");
// select the target item
await act(async () => {
await userEvent.click(options[0]);
});
await user.click(options[0]);
const {container} = wrapper;
@ -276,9 +270,7 @@ describe("Autocomplete", () => {
expect(clearButton).not.toBeNull();
// click the clear button
await act(async () => {
await userEvent.click(clearButton);
});
await user.click(clearButton);
// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
@ -294,9 +286,7 @@ describe("Autocomplete", () => {
const autocomplete = wrapper.getByTestId("autocomplete");
// open the select listbox
await act(async () => {
await userEvent.click(autocomplete);
});
await user.click(autocomplete);
// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
@ -304,9 +294,7 @@ describe("Autocomplete", () => {
let options = wrapper.getAllByRole("option");
// select the target item
await act(async () => {
await userEvent.click(options[0]);
});
await user.click(options[0]);
const {container} = wrapper;
@ -317,9 +305,7 @@ describe("Autocomplete", () => {
expect(clearButton).not.toBeNull();
/// click the clear button
await act(async () => {
await userEvent.click(clearButton);
});
await user.click(clearButton);
// assert that the input has empty value
expect(autocomplete).toHaveValue("");
@ -338,9 +324,7 @@ describe("Autocomplete", () => {
const autocomplete = wrapper.getByTestId("autocomplete");
// open the select listbox
await act(async () => {
await userEvent.click(autocomplete);
});
await user.click(autocomplete);
// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
@ -348,9 +332,7 @@ describe("Autocomplete", () => {
let options = wrapper.getAllByRole("option");
// select the target item
await act(async () => {
await userEvent.click(options[0]);
});
await user.click(options[0]);
const {container} = wrapper;
@ -361,9 +343,7 @@ describe("Autocomplete", () => {
expect(clearButton).not.toBeNull();
// click the clear button
await act(async () => {
await userEvent.click(clearButton);
});
await user.click(clearButton);
// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
@ -395,9 +375,7 @@ describe("Autocomplete", () => {
const autocomplete = wrapper.getByTestId("autocomplete");
// open the select listbox by clicking selector button
await act(async () => {
await userEvent.click(selectorButton);
});
await user.click(selectorButton);
// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
@ -406,9 +384,7 @@ describe("Autocomplete", () => {
expect(autocomplete).toHaveFocus();
// close the select listbox by clicking selector button again
await act(async () => {
await userEvent.click(selectorButton);
});
await user.click(selectorButton);
// assert that the autocomplete listbox is closed
expect(autocomplete).toHaveAttribute("aria-expanded", "false");
@ -439,17 +415,13 @@ describe("Autocomplete", () => {
const autocomplete = wrapper.getByTestId("close-when-clicking-outside-test");
// open the select listbox
await act(async () => {
await userEvent.click(autocomplete);
});
await user.click(autocomplete);
// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
// click outside the autocomplete component
await act(async () => {
await userEvent.click(document.body);
});
await user.click(document.body);
// assert that the autocomplete is closed
expect(autocomplete).toHaveAttribute("aria-expanded", "false");
@ -488,17 +460,14 @@ describe("Autocomplete", () => {
const autocomplete = wrapper.getByTestId("close-when-clicking-outside-test");
// open the autocomplete listbox
await act(async () => {
await userEvent.click(autocomplete);
});
await user.click(autocomplete);
// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
// click outside the autocomplete component
await act(async () => {
await userEvent.click(document.body);
});
await user.click(document.body);
// assert that the autocomplete listbox is closed
expect(autocomplete).toHaveAttribute("aria-expanded", "false");
@ -522,9 +491,7 @@ describe("Autocomplete", () => {
const autocomplete = wrapper.getByTestId("autocomplete");
// open the listbox
await act(async () => {
await userEvent.click(autocomplete);
});
await user.click(autocomplete);
// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
@ -537,9 +504,7 @@ describe("Autocomplete", () => {
expect(options.length).toBe(3);
// select the target item
await act(async () => {
await userEvent.click(options[0]);
});
await user.click(options[0]);
// assert that the input has target selection
expect(autocomplete).toHaveValue("Penguin");
@ -598,9 +563,7 @@ describe("Autocomplete", () => {
expect(selectorButton2).not.toBeNull();
// open the select listbox by clicking selector button in the first autocomplete
await act(async () => {
await userEvent.click(selectorButton);
});
await user.click(selectorButton);
// assert that the first autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
@ -609,9 +572,7 @@ describe("Autocomplete", () => {
expect(autocomplete).toHaveFocus();
// close the select listbox by clicking the second autocomplete
await act(async () => {
await userEvent.click(selectorButton2);
});
await user.click(selectorButton2);
// assert that the first autocomplete listbox is closed
expect(autocomplete).toHaveAttribute("aria-expanded", "false");

View File

@ -35,7 +35,7 @@ describe("ButtonGroup", () => {
let button = wrapper.getByTestId("button-test");
userEvent.click(button);
expect(handler).toBeCalledTimes(0);
expect(handler).toHaveBeenCalledTimes(0);
});
it("should render different variants", () => {

View File

@ -1,9 +1,16 @@
import * as React from "react";
import {act, render} from "@testing-library/react";
import {render} from "@testing-library/react";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {Button} from "../src";
describe("Button", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
it("should render correctly", () => {
const wrapper = render(<Button disableRipple />);
@ -17,24 +24,24 @@ describe("Button", () => {
expect(ref.current).not.toBeNull();
});
it("should trigger onPress function", () => {
it("should trigger onPress function", async () => {
const onPress = jest.fn();
const {getByRole} = render(<Button disableRipple onPress={onPress} />);
act(() => {
getByRole("button").click();
});
const button = getByRole("button");
await user.click(button);
expect(onPress).toHaveBeenCalled();
});
it("should ignore events when disabled", () => {
it("should ignore events when disabled", async () => {
const onPress = jest.fn();
const {getByRole} = render(<Button disableRipple isDisabled onPress={onPress} />);
act(() => {
getByRole("button").click();
});
const button = getByRole("button");
await user.click(button);
expect(onPress).not.toHaveBeenCalled();
});

View File

@ -1,6 +1,6 @@
import * as React from "react";
import {render} from "@testing-library/react";
import {act} from "@testing-library/react-hooks";
import userEvent from "@testing-library/user-event";
import {Card} from "../src";
@ -24,15 +24,15 @@ describe("Card", () => {
expect(() => wrapper.unmount()).not.toThrow();
});
it("should be clicked when is pressable", () => {
it("should be clicked when is pressable", async () => {
const onPress = jest.fn();
const {getByRole} = render(<Card disableRipple isPressable onPress={onPress} />);
const button = getByRole("button");
act(() => {
button.click();
});
const user = userEvent.setup();
await user.click(button);
expect(onPress).toHaveBeenCalled();
});

View File

@ -1,10 +1,16 @@
import * as React from "react";
import {act, render} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {CheckboxGroup, Checkbox} from "../src";
describe("Checkbox.Group", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
it("should render correctly", () => {
const wrapper = render(
<CheckboxGroup defaultValue={[]} label="Select cities">
@ -48,7 +54,7 @@ describe("Checkbox.Group", () => {
expect(container.querySelector("[data-testid=second-checkbox] input")).not.toBeChecked();
});
it("should change value after click", () => {
it("should change value after click", async () => {
let value = ["sydney"];
const wrapper = render(
<CheckboxGroup
@ -67,9 +73,7 @@ describe("Checkbox.Group", () => {
const secondCheckbox = wrapper.getByTestId("second-checkbox");
act(() => {
secondCheckbox.click();
});
await user.click(secondCheckbox);
expect(value).toEqual(["sydney", "buenos-aires"]);
});
@ -98,7 +102,7 @@ describe("Checkbox.Group", () => {
expect(secondCheckbox).not.toBeChecked();
});
it("should work correctly with controlled value", () => {
it("should work correctly with controlled value", async () => {
let checked = ["sydney"];
const onChange = jest.fn((value) => {
checked = value;
@ -125,20 +129,13 @@ describe("Checkbox.Group", () => {
const secondCheckbox = wrapper.getByTestId("second-checkbox");
act(() => {
secondCheckbox.click();
});
await user.click(secondCheckbox);
expect(onChange).toHaveBeenCalledTimes(1);
expect(checked).toEqual(["sydney", "buenos-aires"]);
});
describe("validation", () => {
let user = userEvent.setup();
beforeAll(() => {
user = userEvent.setup();
});
describe("validationBehavior=native", () => {
it("supports group level isRequired", async () => {
let {getAllByRole, getByRole, getByTestId} = render(

View File

@ -1,11 +1,17 @@
import * as React from "react";
import {render, renderHook, act} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {useForm} from "react-hook-form";
import {Checkbox, CheckboxProps} from "../src";
describe("Checkbox", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
it("should render correctly", () => {
const wrapper = render(<Checkbox>Label</Checkbox>);
@ -29,25 +35,21 @@ describe("Checkbox", () => {
expect(container.querySelector("input")?.checked).toBe(false);
});
it("should change value after click", () => {
it("should change value after click", async () => {
const wrapper = render(<Checkbox data-testid="checkbox-test">Option</Checkbox>);
const checkbox = wrapper.container.querySelector("input")!;
expect(checkbox.checked).toBe(false);
act(() => {
wrapper.getByTestId("checkbox-test").click();
});
await user.click(wrapper.getByTestId("checkbox-test"));
expect(checkbox.checked).toBe(true);
});
it("should ignore events when disabled", () => {
it("should ignore events when disabled", async () => {
const {container} = render(<Checkbox isDisabled>Option</Checkbox>);
act(() => {
userEvent.click(container.querySelector("label")!);
});
await user.click(container.querySelector("label")!);
expect(container.querySelector("input")?.checked).toBe(false);
});
@ -58,7 +60,7 @@ describe("Checkbox", () => {
expect(container.querySelector("input")?.indeterminate).toBe(true);
});
it('should work correctly with "onChange" prop', () => {
it('should work correctly with "onChange" prop', async () => {
const onChange = jest.fn();
const wrapper = render(
<Checkbox data-testid="checkbox-test" onChange={onChange}>
@ -66,11 +68,9 @@ describe("Checkbox", () => {
</Checkbox>,
);
act(() => {
wrapper.getByTestId("checkbox-test").click();
});
await user.click(wrapper.getByTestId("checkbox-test"));
expect(onChange).toBeCalled();
expect(onChange).toHaveBeenCalled();
});
it('should work correctly with "onFocus" prop', () => {
@ -87,7 +87,7 @@ describe("Checkbox", () => {
input.focus();
});
expect(onFocus).toBeCalled();
expect(onFocus).toHaveBeenCalled();
});
it("should have required attribute when isRequired with native validationBehavior", () => {
@ -112,7 +112,7 @@ describe("Checkbox", () => {
expect(container.querySelector("input")).toHaveAttribute("aria-required", "true");
});
it("should work correctly with controlled value", () => {
it("should work correctly with controlled value", async () => {
const onChange = jest.fn();
const Component = (props: CheckboxProps) => {
@ -138,20 +138,12 @@ describe("Checkbox", () => {
</Component>,
);
act(() => {
wrapper.getByTestId("checkbox-test").click();
});
await user.click(wrapper.getByTestId("checkbox-test"));
expect(onChange).toBeCalled();
expect(onChange).toHaveBeenCalled();
});
describe("validation", () => {
let user;
beforeEach(() => {
user = userEvent.setup();
});
describe("validationBehavior=native", () => {
it("supports isRequired", async () => {
const {getByRole, getByTestId} = render(
@ -257,14 +249,12 @@ describe("Checkbox with React Hook Form", () => {
});
it("should submit form when required field is not empty", async () => {
act(() => {
checkbox3.click();
});
const user = userEvent.setup();
await user.click(checkbox3);
expect(checkbox3.checked).toBe(true);
const user = userEvent.setup();
await user.click(submitButton);
expect(onSubmit).toHaveBeenCalledTimes(1);

View File

@ -1,7 +1,7 @@
import * as React from "react";
import {render} from "@testing-library/react";
import {Avatar} from "@nextui-org/avatar";
import {act} from "@testing-library/react-hooks";
import userEvent from "@testing-library/user-event";
import {Chip} from "../src";
@ -49,13 +49,13 @@ describe("Chip", () => {
expect(wrapper.getByRole("button")).not.toBeNull();
});
it("should call onClose when close button is clicked", () => {
it("should call onClose when close button is clicked", async () => {
const onClose = jest.fn();
const {getByRole} = render(<Chip onClose={onClose} />);
act(() => {
getByRole("button").click();
});
const user = userEvent.setup();
await user.click(getByRole("button"));
expect(onClose).toHaveBeenCalled();
});

View File

@ -1,6 +1,6 @@
/* eslint-disable jsx-a11y/no-autofocus */
import * as React from "react";
import {act, fireEvent, render} from "@testing-library/react";
import {fireEvent, render} from "@testing-library/react";
import {CalendarDate, CalendarDateTime, DateValue, ZonedDateTime} from "@internationalized/date";
import {pointerMap, triggerPress} from "@nextui-org/test-utils";
import userEvent from "@testing-library/user-event";
@ -67,10 +67,7 @@ describe("DateInput", () => {
/>,
);
await act(async () => {
await user.tab();
});
await user.tab();
await user.keyboard("01011980");
expect(tree.getByText("Date unavailable.")).toBeInTheDocument();
@ -205,17 +202,13 @@ describe("DateInput", () => {
expect(onBlurSpy).not.toHaveBeenCalled();
expect(onFocusChangeSpy).not.toHaveBeenCalled();
expect(onFocusSpy).not.toHaveBeenCalled();
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[0]).toHaveFocus();
expect(onBlurSpy).not.toHaveBeenCalled();
expect(onFocusChangeSpy).toHaveBeenCalledTimes(1);
expect(onFocusSpy).toHaveBeenCalledTimes(1);
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[1]).toHaveFocus();
expect(onBlurSpy).not.toHaveBeenCalled();
expect(onFocusChangeSpy).toHaveBeenCalledTimes(1);
@ -236,22 +229,14 @@ describe("DateInput", () => {
expect(onBlurSpy).not.toHaveBeenCalled();
expect(onFocusChangeSpy).not.toHaveBeenCalled();
expect(onFocusSpy).not.toHaveBeenCalled();
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[0]).toHaveFocus();
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[1]).toHaveFocus();
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[2]).toHaveFocus();
expect(onBlurSpy).toHaveBeenCalledTimes(0);
await act(async () => {
await user.tab();
});
await user.tab();
expect(onBlurSpy).toHaveBeenCalledTimes(1);
expect(onFocusChangeSpy).toHaveBeenCalledTimes(2);
expect(onFocusSpy).toHaveBeenCalledTimes(1);
@ -266,9 +251,7 @@ describe("DateInput", () => {
expect(onKeyDownSpy).not.toHaveBeenCalled();
expect(onKeyUpSpy).not.toHaveBeenCalled();
await act(() => {
user.tab();
});
await user.tab();
expect(segments[0]).toHaveFocus();
expect(onKeyDownSpy).not.toHaveBeenCalled();

View File

@ -1,6 +1,6 @@
/* eslint-disable jsx-a11y/no-autofocus */
import * as React from "react";
import {act, fireEvent, render} from "@testing-library/react";
import {fireEvent, render} from "@testing-library/react";
import {Time, ZonedDateTime} from "@internationalized/date";
import {TimeValue} from "@react-types/datepicker";
import {pointerMap, triggerPress} from "@nextui-org/test-utils";
@ -237,17 +237,13 @@ describe("TimeInput", () => {
expect(onBlurSpy).not.toHaveBeenCalled();
expect(onFocusChangeSpy).not.toHaveBeenCalled();
expect(onFocusSpy).not.toHaveBeenCalled();
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[0]).toHaveFocus();
expect(onBlurSpy).not.toHaveBeenCalled();
expect(onFocusChangeSpy).toHaveBeenCalledTimes(1);
expect(onFocusSpy).toHaveBeenCalledTimes(1);
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[1]).toHaveFocus();
expect(onBlurSpy).not.toHaveBeenCalled();
expect(onFocusChangeSpy).toHaveBeenCalledTimes(1);
@ -268,22 +264,14 @@ describe("TimeInput", () => {
expect(onBlurSpy).not.toHaveBeenCalled();
expect(onFocusChangeSpy).not.toHaveBeenCalled();
expect(onFocusSpy).not.toHaveBeenCalled();
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[0]).toHaveFocus();
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[1]).toHaveFocus();
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[2]).toHaveFocus();
expect(onBlurSpy).toHaveBeenCalledTimes(0);
await act(async () => {
await user.tab();
});
await user.tab();
expect(onBlurSpy).toHaveBeenCalledTimes(1);
expect(onFocusChangeSpy).toHaveBeenCalledTimes(2);
expect(onFocusSpy).toHaveBeenCalledTimes(1);
@ -298,10 +286,7 @@ describe("TimeInput", () => {
expect(onKeyDownSpy).not.toHaveBeenCalled();
expect(onKeyUpSpy).not.toHaveBeenCalled();
await act(() => {
user.tab();
});
await user.tab();
expect(segments[0]).toHaveFocus();
expect(onKeyDownSpy).not.toHaveBeenCalled();
expect(onKeyUpSpy).toHaveBeenCalledTimes(1);

View File

@ -246,19 +246,13 @@ describe("DatePicker", () => {
expect(onFocusChangeSpy).not.toHaveBeenCalled();
expect(onFocusSpy).not.toHaveBeenCalled();
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[0]).toHaveFocus();
expect(onBlurSpy).not.toHaveBeenCalled();
expect(onFocusChangeSpy).toHaveBeenCalledTimes(1);
expect(onFocusSpy).toHaveBeenCalledTimes(1);
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[1]).toHaveFocus();
expect(onBlurSpy).not.toHaveBeenCalled();
expect(onFocusChangeSpy).toHaveBeenCalledTimes(1);
@ -288,19 +282,13 @@ describe("DatePicker", () => {
expect(onFocusChangeSpy).not.toHaveBeenCalled();
expect(onFocusSpy).not.toHaveBeenCalled();
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[0]).toHaveFocus();
expect(onBlurSpy).not.toHaveBeenCalled();
expect(onFocusChangeSpy).toHaveBeenCalledTimes(1);
expect(onFocusSpy).toHaveBeenCalledTimes(1);
await act(() => {
user.click(document.body);
});
await user.click(document.body);
expect(document.body).toHaveFocus();
expect(onBlurSpy).toHaveBeenCalledTimes(1);
expect(onFocusChangeSpy).toHaveBeenCalledTimes(2);
@ -375,10 +363,7 @@ describe("DatePicker", () => {
expect(document.activeElement).toBe(button);
expect(button).toHaveFocus();
await act(async () => {
await user.tab();
});
await user.tab();
expect(document.body).toHaveFocus();
});
@ -391,10 +376,7 @@ describe("DatePicker", () => {
expect(onKeyDownSpy).not.toHaveBeenCalled();
expect(onKeyUpSpy).not.toHaveBeenCalled();
await act(async () => {
await user.tab();
});
await user.tab();
expect(segments[0]).toHaveFocus();
expect(onKeyDownSpy).not.toHaveBeenCalled();
expect(onKeyUpSpy).toHaveBeenCalledTimes(1);

View File

@ -1,7 +1,7 @@
import * as React from "react";
import {act, render, fireEvent} from "@testing-library/react";
import {Button} from "@nextui-org/button";
import userEvent from "@testing-library/user-event";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {keyCodes} from "@nextui-org/test-utils";
import {User} from "@nextui-org/user";
import {Image} from "@nextui-org/image";
@ -14,6 +14,11 @@ import {Dropdown, DropdownTrigger, DropdownMenu, DropdownItem, DropdownSection}
const spy = jest.spyOn(console, "error").mockImplementation(() => {});
describe("Dropdown", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
afterEach(() => {
jest.clearAllMocks();
});
@ -144,11 +149,8 @@ describe("Dropdown", () => {
expect(triggerButton).toBeTruthy();
await act(async () => {
await userEvent.click(triggerButton);
});
expect(spy).toBeCalledTimes(0);
await user.click(triggerButton);
expect(spy).toHaveBeenCalledTimes(0);
let menu = wrapper.queryByRole("menu");
@ -182,13 +184,11 @@ describe("Dropdown", () => {
let triggerButton = wrapper.getByTestId("trigger-test");
expect(onOpenChange).toBeCalledTimes(0);
expect(onOpenChange).toHaveBeenCalledTimes(0);
act(() => {
triggerButton.click();
});
await user.click(triggerButton);
expect(onOpenChange).toBeCalledTimes(1);
expect(onOpenChange).toHaveBeenCalledTimes(1);
let menu = wrapper.getByRole("menu");
@ -201,12 +201,10 @@ describe("Dropdown", () => {
expect(menuItems.length).toBe(4);
await act(async () => {
await userEvent.click(menuItems[1]);
await user.click(menuItems[1]);
expect(onSelectionChange).toBeCalledTimes(1);
expect(onOpenChange).toBeCalled();
});
expect(onSelectionChange).toHaveBeenCalledTimes(1);
expect(onOpenChange).toHaveBeenCalled();
});
it("should work with multiple selection (controlled)", async () => {
@ -236,13 +234,11 @@ describe("Dropdown", () => {
let triggerButton = wrapper.getByTestId("trigger-test");
expect(onOpenChange).toBeCalledTimes(0);
expect(onOpenChange).toHaveBeenCalledTimes(0);
act(() => {
triggerButton.click();
});
await user.click(triggerButton);
expect(onOpenChange).toBeCalledTimes(1);
expect(onOpenChange).toHaveBeenCalledTimes(1);
let menu = wrapper.getByRole("menu");
@ -255,12 +251,10 @@ describe("Dropdown", () => {
expect(menuItems.length).toBe(4);
await act(async () => {
await userEvent.click(menuItems[0]);
await user.click(menuItems[0]);
expect(onSelectionChange).toBeCalledTimes(1);
expect(onOpenChange).toBeCalled();
});
expect(onSelectionChange).toHaveBeenCalledTimes(1);
expect(onOpenChange).toHaveBeenCalled();
});
it("should show checkmarks if selectionMode is single and has a selected item", () => {
@ -366,7 +360,7 @@ describe("Dropdown", () => {
expect(checkmark1).toBeFalsy();
});
it("should not open on disabled button", () => {
it("should not open on disabled button", async () => {
const wrapper = render(
<Dropdown>
<DropdownTrigger>
@ -389,16 +383,14 @@ describe("Dropdown", () => {
expect(triggerButton).toBeTruthy();
act(() => {
triggerButton.click();
});
await user.click(triggerButton);
let menu = wrapper.queryByRole("menu");
expect(menu).toBeFalsy();
});
it("should not open on disabled dropdown", () => {
it("should not open on disabled dropdown", async () => {
const wrapper = render(
<Dropdown isDisabled>
<DropdownTrigger>
@ -419,16 +411,14 @@ describe("Dropdown", () => {
expect(triggerButton).toBeTruthy();
act(() => {
triggerButton.click();
});
await user.click(triggerButton);
let menu = wrapper.queryByRole("menu");
expect(menu).toBeFalsy();
});
it("should not select on disabled item", () => {
it("should not select on disabled item", async () => {
const onSelectionChange = jest.fn();
const wrapper = render(
<Dropdown isOpen>
@ -455,11 +445,9 @@ describe("Dropdown", () => {
expect(menuItems.length).toBe(4);
act(() => {
menuItems[1].click();
});
await user.click(menuItems[1]);
expect(onSelectionChange).toBeCalledTimes(0);
expect(onSelectionChange).toHaveBeenCalledTimes(0);
});
it("should render without error (custom trigger with isDisabled)", async () => {
@ -488,7 +476,7 @@ describe("Dropdown", () => {
</Dropdown>,
);
expect(spy).toBeCalledTimes(0);
expect(spy).toHaveBeenCalledTimes(0);
spy.mockRestore();
@ -502,7 +490,7 @@ describe("Dropdown", () => {
</Dropdown>,
);
expect(spy).toBeCalledTimes(0);
expect(spy).toHaveBeenCalledTimes(0);
spy.mockRestore();
@ -516,7 +504,7 @@ describe("Dropdown", () => {
</Dropdown>,
);
expect(spy).toBeCalledTimes(0);
expect(spy).toHaveBeenCalledTimes(0);
spy.mockRestore();
@ -534,7 +522,7 @@ describe("Dropdown", () => {
</Dropdown>,
);
expect(spy).toBeCalledTimes(0);
expect(spy).toHaveBeenCalledTimes(0);
spy.mockRestore();
});
@ -580,9 +568,7 @@ describe("Dropdown", () => {
expect(dropdown2).not.toBeNull();
// open the dropdown listbox by clicking dropdownor button in the first dropdown
await act(async () => {
await userEvent.click(dropdown);
});
await user.click(dropdown);
// assert that the first dropdown listbox is open
expect(dropdown).toHaveAttribute("aria-expanded", "true");
@ -591,9 +577,7 @@ describe("Dropdown", () => {
expect(dropdown2).toHaveAttribute("aria-expanded", "false");
// close the dropdown listbox by clicking the second dropdown
await act(async () => {
await userEvent.click(dropdown2);
});
await user.click(dropdown2);
// assert that the first dropdown listbox is closed
expect(dropdown).toHaveAttribute("aria-expanded", "false");
@ -601,281 +585,262 @@ describe("Dropdown", () => {
// assert that the second dropdown listbox is open
expect(dropdown2).toHaveAttribute("aria-expanded", "true");
});
});
describe("Keyboard interactions", () => {
it("should focus on the first item on keyDown (Enter)", async () => {
const wrapper = render(
<Dropdown>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu disallowEmptySelection aria-label="Actions" selectionMode="single">
<DropdownItem key="new">New file</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
<DropdownItem key="edit">Edit file</DropdownItem>
<DropdownItem key="delete" color="danger">
Delete file
</DropdownItem>
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
act(() => {
triggerButton.focus();
});
expect(triggerButton).toHaveFocus();
fireEvent.keyDown(triggerButton, {key: "Enter", charCode: keyCodes.Enter});
let menu = wrapper.queryByRole("menu");
expect(menu).toBeTruthy();
let menuItems = wrapper.getAllByRole("menuitemradio");
expect(menuItems.length).toBe(4);
expect(menuItems[0]).toHaveFocus();
});
it("should focus on the first item on keyDown (Space)", async () => {
const wrapper = render(
<Dropdown>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu disallowEmptySelection aria-label="Actions" selectionMode="single">
<DropdownItem key="new">New file</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
<DropdownItem key="edit">Edit file</DropdownItem>
<DropdownItem key="delete" color="danger">
Delete file
</DropdownItem>
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
act(() => {
triggerButton.focus();
});
expect(triggerButton).toHaveFocus();
fireEvent.keyDown(triggerButton, {key: " ", charCode: keyCodes[" "]});
let menu = wrapper.queryByRole("menu");
expect(menu).toBeTruthy();
let menuItems = wrapper.getAllByRole("menuitemradio");
expect(menuItems.length).toBe(4);
expect(menuItems[0]).toHaveFocus();
});
it("should press the item on keyDown (Enter)", async () => {
const user = userEvent.setup();
const logSpy = jest.spyOn(console, "log").mockImplementation(() => {});
const wrapper = render(
<Dropdown>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions" selectionMode="single">
<DropdownItem
key="new"
onPress={() => {
/* eslint-disable no-console */
console.log("ENTER");
}}
>
New file
</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
<DropdownItem key="edit">Edit file</DropdownItem>
<DropdownItem key="delete" color="danger">
Delete file
</DropdownItem>
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
act(() => {
triggerButton.focus();
});
expect(triggerButton).toHaveFocus();
fireEvent.keyDown(triggerButton, {key: "Enter", charCode: keyCodes.Enter});
let menu = wrapper.queryByRole("menu");
expect(menu).toBeTruthy();
let menuItems = wrapper.getAllByRole("menuitemradio");
expect(menuItems.length).toBe(4);
expect(menuItems[0]).toHaveFocus();
await act(async () => {
await user.keyboard("[Enter]");
});
expect(logSpy).toHaveBeenCalledWith("ENTER");
logSpy.mockRestore();
});
it("should press the item on keyDown (Space)", async () => {
const user = userEvent.setup();
const logSpy = jest.spyOn(console, "log").mockImplementation(() => {});
const wrapper = render(
<Dropdown>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions" selectionMode="single">
<DropdownItem
key="new"
onPress={() => {
/* eslint-disable no-console */
console.log("SPACE");
}}
>
New file
</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
<DropdownItem key="edit">Edit file</DropdownItem>
<DropdownItem key="delete" color="danger">
Delete file
</DropdownItem>
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
act(() => {
triggerButton.focus();
});
expect(triggerButton).toHaveFocus();
fireEvent.keyDown(triggerButton, {key: "Enter", charCode: keyCodes.Enter});
let menu = wrapper.queryByRole("menu");
expect(menu).toBeTruthy();
let menuItems = wrapper.getAllByRole("menuitemradio");
expect(menuItems.length).toBe(4);
expect(menuItems[0]).toHaveFocus();
await act(async () => {
await user.keyboard("[Space]");
});
expect(logSpy).toHaveBeenCalledWith("SPACE");
logSpy.mockRestore();
});
it("should respect closeOnSelect setting of DropdownItem (static)", async () => {
const onOpenChange = jest.fn();
const wrapper = render(
<Dropdown onOpenChange={onOpenChange}>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions">
<DropdownItem key="new" closeOnSelect={false}>
New file
</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
act(() => {
triggerButton.click();
});
expect(onOpenChange).toBeCalledTimes(1);
let menuItems = wrapper.getAllByRole("menuitem");
await act(async () => {
await userEvent.click(menuItems[0]);
expect(onOpenChange).toBeCalledTimes(1);
});
await act(async () => {
await userEvent.click(menuItems[1]);
expect(onOpenChange).toBeCalledTimes(2);
});
});
it("should respect closeOnSelect setting of DropdownItem (dynamic)", async () => {
const onOpenChange = jest.fn();
const items = [
{
key: "new",
label: "New file",
},
{
key: "copy",
label: "Copy link",
},
];
const wrapper = render(
<Dropdown onOpenChange={onOpenChange}>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions" items={items}>
{(item) => (
<DropdownItem key={item.key} closeOnSelect={item.key !== "new"}>
{item.label}
describe("Keyboard interactions", () => {
it("should focus on the first item on keyDown (Enter)", async () => {
const wrapper = render(
<Dropdown>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu disallowEmptySelection aria-label="Actions" selectionMode="single">
<DropdownItem key="new">New file</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
<DropdownItem key="edit">Edit file</DropdownItem>
<DropdownItem key="delete" color="danger">
Delete file
</DropdownItem>
)}
</DropdownMenu>
</Dropdown>,
);
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
let triggerButton = wrapper.getByTestId("trigger-test");
act(() => {
triggerButton.click();
});
expect(onOpenChange).toBeCalledTimes(1);
act(() => {
triggerButton.focus();
});
let menuItems = wrapper.getAllByRole("menuitem");
expect(triggerButton).toHaveFocus();
await act(async () => {
await userEvent.click(menuItems[0]);
expect(onOpenChange).toBeCalledTimes(1);
fireEvent.keyDown(triggerButton, {key: "Enter", charCode: keyCodes.Enter});
let menu = wrapper.queryByRole("menu");
expect(menu).toBeTruthy();
let menuItems = wrapper.getAllByRole("menuitemradio");
expect(menuItems.length).toBe(4);
expect(menuItems[0]).toHaveFocus();
});
await act(async () => {
await userEvent.click(menuItems[1]);
expect(onOpenChange).toBeCalledTimes(2);
it("should focus on the first item on keyDown (Space)", async () => {
const wrapper = render(
<Dropdown>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu disallowEmptySelection aria-label="Actions" selectionMode="single">
<DropdownItem key="new">New file</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
<DropdownItem key="edit">Edit file</DropdownItem>
<DropdownItem key="delete" color="danger">
Delete file
</DropdownItem>
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
act(() => {
triggerButton.focus();
});
expect(triggerButton).toHaveFocus();
fireEvent.keyDown(triggerButton, {key: " ", charCode: keyCodes[" "]});
let menu = wrapper.queryByRole("menu");
expect(menu).toBeTruthy();
let menuItems = wrapper.getAllByRole("menuitemradio");
expect(menuItems.length).toBe(4);
expect(menuItems[0]).toHaveFocus();
});
it("should press the item on keyDown (Enter)", async () => {
const logSpy = jest.spyOn(console, "log").mockImplementation(() => {});
const wrapper = render(
<Dropdown>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions" selectionMode="single">
<DropdownItem
key="new"
onPress={() => {
/* eslint-disable no-console */
console.log("ENTER");
}}
>
New file
</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
<DropdownItem key="edit">Edit file</DropdownItem>
<DropdownItem key="delete" color="danger">
Delete file
</DropdownItem>
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
act(() => {
triggerButton.focus();
});
expect(triggerButton).toHaveFocus();
fireEvent.keyDown(triggerButton, {key: "Enter", charCode: keyCodes.Enter});
let menu = wrapper.queryByRole("menu");
expect(menu).toBeTruthy();
let menuItems = wrapper.getAllByRole("menuitemradio");
expect(menuItems.length).toBe(4);
expect(menuItems[0]).toHaveFocus();
await user.keyboard("[Enter]");
expect(logSpy).toHaveBeenCalledWith("ENTER");
logSpy.mockRestore();
});
it("should press the item on keyDown (Space)", async () => {
const logSpy = jest.spyOn(console, "log").mockImplementation(() => {});
const wrapper = render(
<Dropdown>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions" selectionMode="single">
<DropdownItem
key="new"
onPress={() => {
/* eslint-disable no-console */
console.log("SPACE");
}}
>
New file
</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
<DropdownItem key="edit">Edit file</DropdownItem>
<DropdownItem key="delete" color="danger">
Delete file
</DropdownItem>
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
act(() => {
triggerButton.focus();
});
expect(triggerButton).toHaveFocus();
fireEvent.keyDown(triggerButton, {key: "Enter", charCode: keyCodes.Enter});
let menu = wrapper.queryByRole("menu");
expect(menu).toBeTruthy();
let menuItems = wrapper.getAllByRole("menuitemradio");
expect(menuItems.length).toBe(4);
expect(menuItems[0]).toHaveFocus();
await user.keyboard("[Space]");
expect(logSpy).toHaveBeenCalledWith("SPACE");
logSpy.mockRestore();
});
it("should respect closeOnSelect setting of DropdownItem (static)", async () => {
const onOpenChange = jest.fn();
const wrapper = render(
<Dropdown onOpenChange={onOpenChange}>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions">
<DropdownItem key="new" closeOnSelect={false}>
New file
</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
await user.click(triggerButton);
expect(onOpenChange).toHaveBeenCalledTimes(1);
let menuItems = wrapper.getAllByRole("menuitem");
await user.click(menuItems[0]);
expect(onOpenChange).toHaveBeenCalledTimes(1);
await user.click(menuItems[1]);
expect(onOpenChange).toHaveBeenCalledTimes(2);
});
it("should respect closeOnSelect setting of DropdownItem (dynamic)", async () => {
const onOpenChange = jest.fn();
const items = [
{
key: "new",
label: "New file",
},
{
key: "copy",
label: "Copy link",
},
];
const wrapper = render(
<Dropdown onOpenChange={onOpenChange}>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions" items={items}>
{(item) => (
<DropdownItem key={item.key} closeOnSelect={item.key !== "new"}>
{item.label}
</DropdownItem>
)}
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
await user.click(triggerButton);
expect(onOpenChange).toHaveBeenCalledTimes(1);
let menuItems = wrapper.getAllByRole("menuitem");
await user.click(menuItems[0]);
expect(onOpenChange).toHaveBeenCalledTimes(1);
await user.click(menuItems[1]);
expect(onOpenChange).toHaveBeenCalledTimes(2);
});
});
});

View File

@ -1,10 +1,16 @@
import * as React from "react";
import {act, render} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import {render} from "@testing-library/react";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {Listbox, ListboxItem, ListboxSection} from "../src";
describe("Listbox", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
it("should render correctly", () => {
const wrapper = render(
<Listbox aria-label="Actions" onAction={alert}>
@ -145,11 +151,8 @@ describe("Listbox", () => {
expect(listboxItems.length).toBe(4);
await act(async () => {
await userEvent.click(listboxItems[1]);
expect(onSelectionChange).toBeCalledTimes(1);
});
await user.click(listboxItems[1]);
expect(onSelectionChange).toHaveBeenCalledTimes(1);
});
it("should work with multiple selection (controlled)", async () => {
@ -179,11 +182,8 @@ describe("Listbox", () => {
expect(listboxItems.length).toBe(4);
await act(async () => {
await userEvent.click(listboxItems[0]);
expect(onSelectionChange).toBeCalledTimes(1);
});
await user.click(listboxItems[0]);
expect(onSelectionChange).toHaveBeenCalledTimes(1);
});
it("should show checkmarks if selectionMode is single and has a selected item", () => {

View File

@ -1,10 +1,16 @@
import * as React from "react";
import {act, render} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import {render} from "@testing-library/react";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {Menu, MenuItem, MenuSection} from "../src";
describe("Menu", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
it("should render correctly", () => {
const wrapper = render(
<Menu aria-label="Actions" onAction={alert}>
@ -146,11 +152,8 @@ describe("Menu", () => {
expect(menuItems.length).toBe(4);
await act(async () => {
await userEvent.click(menuItems[1]);
expect(onSelectionChange).toBeCalledTimes(1);
});
await user.click(menuItems[1]);
expect(onSelectionChange).toHaveBeenCalledTimes(1);
});
it("should work with multiple selection (controlled)", async () => {
@ -180,11 +183,8 @@ describe("Menu", () => {
expect(menuItems.length).toBe(4);
await act(async () => {
await userEvent.click(menuItems[0]);
expect(onSelectionChange).toBeCalledTimes(1);
});
await user.click(menuItems[0]);
expect(onSelectionChange).toHaveBeenCalledTimes(1);
});
it("should show checkmarks if selectionMode is single and has a selected item", () => {
@ -291,11 +291,8 @@ describe("Menu", () => {
let menuItems = wrapper.getAllByRole("menuitem");
await act(async () => {
await userEvent.click(menuItems[1]);
expect(onAction).toBeCalledTimes(1);
});
await user.click(menuItems[1]);
expect(onAction).toHaveBeenCalledTimes(1);
});
it("should not dispatch onAction events if item is disabled", async () => {
@ -316,11 +313,8 @@ describe("Menu", () => {
let menuItems = wrapper.getAllByRole("menuitem");
await act(async () => {
await userEvent.click(menuItems[1]);
expect(onAction).toBeCalledTimes(0);
});
await user.click(menuItems[1]);
expect(onAction).toHaveBeenCalledTimes(0);
});
it("should dispatch onPress, onAction and onClick events", async () => {
@ -343,12 +337,10 @@ describe("Menu", () => {
let menuItems = wrapper.getAllByRole("menuitem");
await act(async () => {
await userEvent.click(menuItems[0]);
await user.click(menuItems[0]);
expect(onAction).toBeCalledTimes(1);
expect(onPress).toBeCalledTimes(1);
expect(onClick).toBeCalledTimes(1);
});
expect(onAction).toHaveBeenCalledTimes(1);
expect(onPress).toHaveBeenCalledTimes(1);
expect(onClick).toHaveBeenCalledTimes(1);
});
});

View File

@ -1,5 +1,6 @@
import * as React from "react";
import {act, render, fireEvent} from "@testing-library/react";
import {render, fireEvent} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import {Modal, ModalContent, ModalBody, ModalHeader, ModalFooter} from "../src";
@ -25,7 +26,7 @@ describe("Modal", () => {
expect(() => wrapper.unmount()).not.toThrow();
expect(spy).toBeCalledTimes(0);
expect(spy).toHaveBeenCalledTimes(0);
});
it("ref should be forwarded", () => {
@ -68,7 +69,7 @@ describe("Modal", () => {
expect(modal).toHaveAttribute("aria-describedby", modalBody.id);
});
test("should fire 'onOpenChange' callback when close button is clicked", () => {
test("should fire 'onOpenChange' callback when close button is clicked", async () => {
const onClose = jest.fn();
const {getByLabelText} = render(
@ -83,9 +84,9 @@ describe("Modal", () => {
const closeButton = getByLabelText("Close");
act(() => {
closeButton.click();
});
const user = userEvent.setup();
await user.click(closeButton);
expect(onClose).toHaveBeenCalled();
});

View File

@ -1,5 +1,6 @@
import * as React from "react";
import {act, render} from "@testing-library/react";
import {render} from "@testing-library/react";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {
Navbar,
@ -18,6 +19,12 @@ window.scrollTo = jest.fn();
const spy = jest.spyOn(console, "error").mockImplementation(() => {});
describe("Navbar", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
afterEach(() => {
jest.clearAllMocks();
});
@ -62,7 +69,7 @@ describe("Navbar", () => {
expect(navbarContent.children.length).toBe(5);
});
it("should not throw error after toggle click", () => {
it("should not throw error after toggle click", async () => {
const items = ["item1", "item2", "item3", "item4", "item5"];
const wrapper = render(
@ -85,14 +92,12 @@ describe("Navbar", () => {
const toggle = wrapper.getByTestId("navbar-toggle-test");
act(() => {
toggle.click();
});
await user.click(toggle);
expect(spy).toBeCalledTimes(0);
expect(spy).toHaveBeenCalledTimes(0);
});
it("should render correctly with menu", () => {
it("should render correctly with menu", async () => {
const items = ["item1", "item2", "item3", "item4", "item5"];
const wrapper = render(
@ -115,16 +120,13 @@ describe("Navbar", () => {
const toggle = wrapper.getByTestId("navbar-toggle-test");
act(() => {
toggle.click();
});
await user.click(toggle);
const menu = wrapper.getByTestId("navbar-menu-test");
expect(menu.children.length).toBe(items.length);
});
it("should call on onChange when toggle is clicked", () => {
it("should call on onChange when toggle is clicked", async () => {
const onChange = jest.fn();
const wrapper = render(
@ -142,9 +144,7 @@ describe("Navbar", () => {
const toggle = wrapper.getByTestId("navbar-toggle-test");
act(() => {
toggle.click();
});
await user.click(toggle);
expect(onChange).toHaveBeenCalled();
});

View File

@ -1,6 +1,6 @@
import * as React from "react";
import {render, fireEvent, act} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {Button} from "@nextui-org/button";
import {Popover, PopoverContent, PopoverTrigger} from "../src";
@ -11,6 +11,12 @@ import {Select, SelectItem} from "../../select/src";
const spy = jest.spyOn(console, "error").mockImplementation(() => {});
describe("Popover", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
afterEach(() => {
jest.clearAllMocks();
});
@ -30,7 +36,7 @@ describe("Popover", () => {
expect(() => wrapper.unmount()).not.toThrow();
});
it("should not throw error when clicking trigger button", () => {
it("should not throw error when clicking trigger button", async () => {
const wrapper = render(
<Popover>
<PopoverTrigger>
@ -44,11 +50,9 @@ describe("Popover", () => {
const trigger = wrapper.getByTestId("trigger-test");
// open popover
act(() => {
trigger.click();
});
await user.click(trigger);
expect(spy).toBeCalledTimes(0);
expect(spy).toHaveBeenCalledTimes(0);
});
it("ref should be forwarded", () => {
@ -130,7 +134,7 @@ describe("Popover", () => {
expect(onClose).toHaveBeenCalledTimes(1);
});
it("should work with NextUI button", () => {
it("should work with NextUI button", async () => {
const onClose = jest.fn();
const wrapper = render(
@ -149,15 +153,11 @@ describe("Popover", () => {
const trigger = wrapper.getByTestId("trigger-test");
// open popover
act(() => {
trigger.click();
});
await user.click(trigger);
expect(onClose).toHaveBeenCalledTimes(0);
// close popover
act(() => {
trigger.click();
});
await user.click(trigger);
expect(onClose).toHaveBeenCalledTimes(1);
});
@ -193,9 +193,7 @@ describe("Popover", () => {
expect(popover2).not.toBeNull();
// open the popover by clicking popover in the first popover
await act(async () => {
await userEvent.click(popover);
});
await user.click(popover);
// assert that the first popover is open
expect(popover).toHaveAttribute("aria-expanded", "true");
@ -204,9 +202,7 @@ describe("Popover", () => {
expect(popover2).toHaveAttribute("aria-expanded", "false");
// close the popover by clicking the second popover
await act(async () => {
await userEvent.click(popover2);
});
await user.click(popover2);
// assert that the first popover is closed
expect(popover).toHaveAttribute("aria-expanded", "false");
@ -232,9 +228,7 @@ describe("Popover", () => {
const trigger = wrapper.getByTestId("trigger-test");
// open popover
await act(async () => {
await userEvent.click(trigger);
});
await user.click(trigger);
const {getByRole} = wrapper;
@ -260,9 +254,9 @@ describe("Popover", () => {
await act(async () => {
// open popover
await userEvent.click(trigger);
await user.click(trigger);
// close popover
await userEvent.click(trigger);
await user.click(trigger);
// assert that the focus is restored back to trigger
expect(trigger).toHaveFocus();
});
@ -286,27 +280,21 @@ describe("Popover", () => {
const popover = wrapper.getByTestId("popover");
await act(async () => {
// open popover
await userEvent.click(popover);
});
// open popover
await user.click(popover);
// assert that the popover is open
expect(popover).toHaveAttribute("aria-expanded", "true");
const select = wrapper.getByTestId("select");
await act(async () => {
// open select
await userEvent.click(select);
});
// open select
await user.click(select);
// assert that the select is open
expect(select).toHaveAttribute("aria-expanded", "true");
await act(async () => {
await userEvent.click(document.body);
});
await user.click(document.body);
// assert that the select is closed
expect(select).toHaveAttribute("aria-expanded", "false");
@ -334,9 +322,7 @@ describe("Popover", () => {
const popover = wrapper.getByTestId("popover");
// open popover
await act(async () => {
await userEvent.click(popover);
});
await user.click(popover);
// assert that the popover is open
expect(popover).toHaveAttribute("aria-expanded", "true");

View File

@ -1,10 +1,16 @@
import * as React from "react";
import {act, render} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {RadioGroup, Radio, RadioGroupProps} from "../src";
describe("Radio", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
it("should render correctly", () => {
const wrapper = render(
<RadioGroup label="Options">
@ -62,7 +68,7 @@ describe("Radio", () => {
expect(wrapper.container.querySelector("[data-testid=radio-test-2] input")).toBeChecked();
});
it("should change value after click", () => {
it("should change value after click", async () => {
const {container} = render(
<RadioGroup defaultValue="1" label="Options">
<Radio value="1">Option 1</Radio>
@ -74,14 +80,11 @@ describe("Radio", () => {
let radio2 = container.querySelector(".radio-test-2 input") as HTMLInputElement;
act(() => {
radio2.click();
});
await user.click(radio2);
expect(radio2).toBeChecked();
});
it("should ignore events when disabled", () => {
it("should ignore events when disabled", async () => {
const {container} = render(
<RadioGroup label="Options">
<Radio isDisabled className="radio-test-1" value="1">
@ -93,14 +96,11 @@ describe("Radio", () => {
let radio1 = container.querySelector(".radio-test-1 input") as HTMLInputElement;
act(() => {
radio1.click();
});
await user.click(radio1);
expect(radio1).not.toBeChecked();
});
it('should work correctly with "onValueChange" prop', () => {
it('should work correctly with "onValueChange" prop', async () => {
const onValueChange = jest.fn();
const {container} = render(
@ -114,11 +114,8 @@ describe("Radio", () => {
let radio2 = container.querySelector(".radio-test-2 input") as HTMLInputElement;
act(() => {
radio2.click();
});
expect(onValueChange).toBeCalledWith("2");
await user.click(radio2);
expect(onValueChange).toHaveBeenCalledWith("2");
expect(radio2).toBeChecked();
});
@ -141,7 +138,7 @@ describe("Radio", () => {
radio2.focus();
});
expect(onFocus).toBeCalled();
expect(onFocus).toHaveBeenCalled();
});
it("should have required attribute when isRequired with native validationBehavior", () => {
@ -178,7 +175,7 @@ describe("Radio", () => {
expect(radios[0]).not.toHaveAttribute("required");
});
it("should work correctly with controlled value", () => {
it("should work correctly with controlled value", async () => {
const onValueChange = jest.fn();
const Component = ({onValueChange}: Omit<RadioGroupProps, "value">) => {
@ -205,11 +202,8 @@ describe("Radio", () => {
let radio2 = container.querySelector(".radio-test-2 input") as HTMLInputElement;
act(() => {
radio2.click();
});
expect(onValueChange).toBeCalled();
await user.click(radio2);
expect(onValueChange).toHaveBeenCalled();
expect(radio2).toBeChecked();
});

View File

@ -1,8 +1,8 @@
import type {SelectProps} from "../src";
import * as React from "react";
import {render, renderHook, act} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import {render, renderHook} from "@testing-library/react";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {useForm} from "react-hook-form";
import {Select, SelectItem, SelectSection} from "../src";
@ -51,7 +51,7 @@ const itemsSectionData = [
];
describe("Select", () => {
let user;
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
@ -153,11 +153,8 @@ describe("Select", () => {
expect(listboxItems.length).toBe(3);
await act(async () => {
await user.click(listboxItems[1]);
expect(onSelectionChange).toBeCalledTimes(1);
});
await user.click(listboxItems[1]);
expect(onSelectionChange).toHaveBeenCalledTimes(1);
});
it("should work with multiple selection (controlled)", async () => {
@ -186,12 +183,10 @@ describe("Select", () => {
expect(listboxItems.length).toBe(3);
await act(async () => {
await user.click(listboxItems[1]);
await user.click(listboxItems[2]);
await user.click(listboxItems[1]);
await user.click(listboxItems[2]);
expect(onSelectionChange).toBeCalledTimes(2);
});
expect(onSelectionChange).toHaveBeenCalledTimes(2);
});
it("should work with dynamic placeholder and renderValue", async () => {
@ -226,15 +221,11 @@ describe("Select", () => {
const select = wrapper.getByTestId("render-selected-item-test");
await act(async () => {
await user.click(select);
});
await user.click(select);
const listboxItems = wrapper.getAllByRole("option");
await act(async () => {
await user.click(listboxItems[0]);
});
await user.click(listboxItems[0]);
expect(select).toHaveTextContent("Penguin");
expect(wrapper.queryByText("Select an favorite animal")).toBe(null);
@ -266,17 +257,13 @@ describe("Select", () => {
const select = wrapper.getByTestId("close-when-clicking-outside-test");
// open the select dropdown
await act(async () => {
await user.click(select);
});
await user.click(select);
// assert that the select is open
expect(select).toHaveAttribute("aria-expanded", "true");
// click outside the select component
await act(async () => {
await user.click(document.body);
});
await user.click(document.body);
// assert that the select is closed
expect(select).toHaveAttribute("aria-expanded", "false");
@ -306,17 +293,13 @@ describe("Select", () => {
const select = wrapper.getByTestId("close-when-clicking-outside-test");
// open the select dropdown
await act(async () => {
await user.click(select);
});
await user.click(select);
// assert that the select is open
expect(select).toHaveAttribute("aria-expanded", "true");
// click outside the select component
await act(async () => {
await user.click(document.body);
});
await user.click(document.body);
// assert that the select is closed
expect(select).toHaveAttribute("aria-expanded", "false");
@ -341,13 +324,11 @@ describe("Select", () => {
);
const select = wrapper.getByTestId("test-select");
await act(async () => {
await user.click(document.body);
await user.tab();
await user.type(select, "z", {skipClick: true});
await user.click(document.body);
await user.tab();
await user.type(select, "z", {skipClick: true});
expect(onSelectionChange).toBeCalledTimes(0);
});
expect(onSelectionChange).toHaveBeenCalledTimes(0);
});
it("should pre-select items based on defaultSelectedKeys (numeric keys)", () => {
@ -424,17 +405,15 @@ describe("Select", () => {
expect(listbox).toBeInTheDocument();
// Select item and check the correct ID is passed to the callback
await act(async () => {
await user.click(wrapperWithId.getByRole("option", {name: itemsWithId[0].value}));
});
await user.click(wrapperWithId.getByRole("option", {name: itemsWithId[0].value}));
expect(onSelectionChangeId).toHaveBeenCalled();
let selectionArg = onSelectionChangeId.mock.calls[0][0];
expect([...selectionArg]).toEqual([itemsWithId[0].id]);
await act(async () => {
await user.click(wrapperWithId.getByRole("option", {name: itemsWithId[1].value}));
});
await user.click(wrapperWithId.getByRole("option", {name: itemsWithId[1].value}));
expect(onSelectionChangeId).toHaveBeenCalledTimes(2);
selectionArg = onSelectionChangeId.mock.calls[1][0];
expect([...selectionArg]).toEqual([itemsWithId[1].id]);
@ -464,17 +443,15 @@ describe("Select", () => {
expect(listbox).toBeInTheDocument();
// Select item and check the correct key is passed to the callback
await act(async () => {
await user.click(wrapperWithKey.getByRole("option", {name: itemsWithKey[0].value}));
});
await user.click(wrapperWithKey.getByRole("option", {name: itemsWithKey[0].value}));
expect(onSelectionChangeKey).toHaveBeenCalled();
let selectionArg = onSelectionChangeKey.mock.calls[0][0];
expect([...selectionArg]).toEqual([itemsWithKey[0].key]);
await act(async () => {
await user.click(wrapperWithKey.getByRole("option", {name: itemsWithKey[1].value}));
});
await user.click(wrapperWithKey.getByRole("option", {name: itemsWithKey[1].value}));
expect(onSelectionChangeKey).toHaveBeenCalledTimes(2);
selectionArg = onSelectionChangeKey.mock.calls[1][0];
expect([...selectionArg]).toEqual([itemsWithKey[1].key]);
@ -537,9 +514,7 @@ describe("Select", () => {
expect(select2).not.toBeNull();
// open the select listbox by clicking selector button in the first select
await act(async () => {
await userEvent.click(select);
});
await user.click(select);
// assert that the first select listbox is open
expect(select).toHaveAttribute("aria-expanded", "true");
@ -548,9 +523,7 @@ describe("Select", () => {
expect(select2).toHaveAttribute("aria-expanded", "false");
// close the select listbox by clicking the second select
await act(async () => {
await userEvent.click(select2);
});
await user.click(select2);
// assert that the first select listbox is closed
expect(select).toHaveAttribute("aria-expanded", "false");
@ -603,8 +576,6 @@ describe("Select", () => {
it("should unset form value", async () => {
const logSpy = jest.spyOn(console, "log");
const user = userEvent.setup();
const wrapper = render(
<form
className="w-full max-w-xs items-end flex flex-col gap-4"
@ -634,20 +605,14 @@ describe("Select", () => {
const submitButton = wrapper.getByTestId("submit-button");
await act(async () => {
await user.click(submitButton);
});
await user.click(submitButton);
expect(logSpy).toHaveBeenCalledWith(JSON.stringify({select: "foo"}));
const select = wrapper.getByTestId("select");
expect(select).not.toBeNull();
await act(async () => {
await user.click(select);
});
await user.click(select);
const listbox = wrapper.getByRole("listbox");
expect(listbox).toBeTruthy();
@ -656,13 +621,8 @@ describe("Select", () => {
expect(listboxItems.length).toBe(2);
await act(async () => {
await user.click(listboxItems[0]);
});
await act(async () => {
await user.click(submitButton);
});
await user.click(listboxItems[0]);
await user.click(submitButton);
expect(logSpy).toHaveBeenCalledWith(JSON.stringify({select: ""}));
});
@ -682,22 +642,18 @@ describe("Select", () => {
</Select>,
);
const select = wrapper.getByTestId("select");
const select = await wrapper.findByTestId("select");
expect(select).not.toBeNull();
// open the select listbox by clicking selector button
await act(async () => {
await userEvent.click(select);
});
await user.click(select);
// assert that the select listbox is open
expect(select).toHaveAttribute("aria-expanded", "true");
// open the select listbox by clicking selector button
await act(async () => {
await userEvent.click(select);
});
await user.click(select);
// assert that the select listbox is closed
expect(select).toHaveAttribute("aria-expanded", "false");
@ -730,11 +686,9 @@ describe("Select", () => {
expect(listboxItems.length).toBe(10);
await act(async () => {
await user.click(listboxItems[1]);
await user.click(listboxItems[1]);
expect(onChange).toBeCalledTimes(1);
});
expect(onChange).toHaveBeenCalledTimes(1);
});
it("should work with onChange (>= 300 select items)", async () => {
@ -764,11 +718,9 @@ describe("Select", () => {
expect(listboxItems.length).toBe(300);
await act(async () => {
await user.click(listboxItems[1]);
await user.click(listboxItems[1]);
expect(onChange).toBeCalledTimes(1);
});
expect(onChange).toHaveBeenCalledTimes(1);
});
it("should place the label outside when labelPlacement is outside", () => {
@ -858,11 +810,21 @@ describe("Select with React Hook Form", () => {
wrapper = render(
<form className="flex flex-col gap-4" onSubmit={handleSubmit(onSubmit)}>
<Select data-testid="select-1" items={itemsData} {...register("withDefaultValue")}>
<Select
data-testid="select-1"
items={itemsData}
{...register("withDefaultValue")}
aria-label="select-1"
>
{(item) => <SelectItem key={item.id}>{item.label}</SelectItem>}
</Select>
<Select data-testid="select-2" items={itemsData} {...register("withoutDefaultValue")}>
<Select
data-testid="select-2"
items={itemsData}
{...register("withoutDefaultValue")}
aria-label="select-2"
>
{(item) => <SelectItem key={item.id}>{item.label}</SelectItem>}
</Select>
@ -870,6 +832,7 @@ describe("Select with React Hook Form", () => {
data-testid="select-3"
items={itemsData}
{...register("requiredField", {required: true})}
aria-label="select-3"
>
{(item) => <SelectItem key={item.id}>{item.label}</SelectItem>}
</Select>

View File

@ -1,10 +1,16 @@
import * as React from "react";
import {render, act} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {Slider, SliderValue} from "../src";
describe("Slider", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
it("should render correctly", () => {
const wrapper = render(<Slider />);
@ -138,9 +144,7 @@ describe("Slider", () => {
expect(output).toHaveTextContent("50");
// change slider value
await act(async () => {
await userEvent.click(button);
});
await user.click(button);
expect(slider).toHaveProperty("value", "55");
expect(slider).toHaveAttribute("aria-valuetext", "55");
@ -201,9 +205,7 @@ describe("Slider", () => {
expect(rightSlider).toHaveAttribute("aria-valuetext", "20");
// change slider value
await act(async () => {
await userEvent.click(button);
});
await user.click(button);
expect(leftSlider).toHaveProperty("value", "15");
expect(leftSlider).toHaveAttribute("aria-valuetext", "15");
@ -318,10 +320,7 @@ describe("Slider", () => {
expect(marks).toHaveLength(3);
await act(async () => {
await userEvent.click(marks[1]);
});
await user.click(marks[1]);
const slider = getByRole("slider");
expect(slider).toHaveProperty("value", "0.5");
@ -358,10 +357,7 @@ describe("Slider", () => {
expect(marks).toHaveLength(3);
await act(async () => {
await userEvent.click(marks[1]);
});
await user.click(marks[1]);
const [leftSlider, rightSlider] = getAllByRole("slider");
expect(leftSlider).toHaveProperty("value", "0.5");

View File

@ -1,11 +1,17 @@
import * as React from "react";
import {render, renderHook, act} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import {render, renderHook} from "@testing-library/react";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {useForm} from "react-hook-form";
import {Switch} from "../src";
describe("Switch", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
it("should render correctly", () => {
const wrapper = render(<Switch aria-label="switch" />);
@ -19,35 +25,26 @@ describe("Switch", () => {
expect(ref.current).not.toBeNull();
});
it("should check and uncheck", () => {
it("should check and uncheck", async () => {
const {getByRole} = render(<Switch aria-label="switch" />);
const checkbox = getByRole("switch");
expect(checkbox).not.toBeChecked();
act(() => {
checkbox.click();
});
await user.click(checkbox);
expect(checkbox).toBeChecked();
act(() => {
checkbox.click();
});
await user.click(checkbox);
expect(checkbox).not.toBeChecked();
});
it("should not check if disabled", () => {
it("should not check if disabled", async () => {
const {getByRole} = render(<Switch isDisabled aria-label="switch" />);
const checkbox = getByRole("switch");
act(() => {
checkbox.click();
});
await user.click(checkbox);
expect(checkbox).not.toBeChecked();
});
@ -59,19 +56,16 @@ describe("Switch", () => {
expect(checkbox).toBeChecked();
});
it("should not check if readOnly", () => {
it("should not check if readOnly", async () => {
const {getByRole} = render(<Switch isReadOnly aria-label="switch" />);
const checkbox = getByRole("switch");
act(() => {
checkbox.click();
});
await user.click(checkbox);
expect(checkbox).not.toBeChecked();
});
it("should check and uncheck with controlled state", () => {
it("should check and uncheck with controlled state", async () => {
const ControlledSwitch = ({onChange}: any) => {
const [isSelected, setIsSelected] = React.useState(false);
@ -95,10 +89,7 @@ describe("Switch", () => {
expect(checkbox).not.toBeChecked();
act(() => {
checkbox.click();
});
await user.click(checkbox);
expect(checkbox).toBeChecked();
expect(onChange).toHaveBeenCalledWith(true);
@ -121,7 +112,7 @@ describe("Switch", () => {
expect(wrapper.getByTestId("thumb-icon")).toBeInTheDocument();
});
it("should change the thumbIcon when clicked", () => {
it("should change the thumbIcon when clicked", async () => {
const thumbIcon = jest.fn((props) => {
const {isSelected} = props;
@ -138,10 +129,7 @@ describe("Switch", () => {
expect(checkbox).not.toBeChecked();
act(() => {
checkbox.click();
});
await user.click(checkbox);
expect(checkbox).toBeChecked();
expect(thumbIcon).toHaveBeenCalledWith(
@ -154,10 +142,7 @@ describe("Switch", () => {
expect(checkedthumbIcon).toBeInTheDocument();
act(() => {
checkbox.click();
});
await user.click(checkbox);
expect(checkbox).not.toBeChecked();
expect(thumbIcon).toHaveBeenCalledWith(
@ -253,21 +238,16 @@ describe("Switch with React Hook Form", () => {
const user = userEvent.setup();
await user.click(submitButton);
expect(onSubmit).toHaveBeenCalledTimes(0);
});
it("should submit form when required field is not empty", async () => {
act(() => {
switch3.click();
});
expect(switch3.checked).toBe(true);
const user = userEvent.setup();
await user.click(submitButton);
await switch3.click();
expect(switch3.checked).toBe(true);
await user.click(submitButton);
expect(onSubmit).toHaveBeenCalledTimes(1);
});
});

View File

@ -1,6 +1,6 @@
import * as React from "react";
import {act, render} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {Table, TableHeader, TableCell, TableColumn, TableBody, TableRow} from "../src";
@ -16,6 +16,12 @@ let items = [
];
describe("Table", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
it("should render correctly", () => {
const wrapper = render(
<Table aria-label="Test example table">
@ -131,7 +137,7 @@ describe("Table", () => {
expect(wrapper.getAllByRole("gridcell")).toHaveLength(4);
});
it("should work with single selectionMode='single'", () => {
it("should work with single selectionMode='single'", async () => {
const onRowAction = jest.fn();
const wrapper = render(
@ -163,14 +169,11 @@ describe("Table", () => {
// get the first row
const row1 = wrapper.getAllByRole("row")[1];
act(() => {
row1.click();
});
await user.click(row1);
expect(onRowAction).toHaveBeenCalledTimes(1);
});
it("should work with single selectionMode='multiple'", () => {
it("should work with single selectionMode='multiple'", async () => {
const onRowAction = jest.fn();
const wrapper = render(
@ -207,15 +210,13 @@ describe("Table", () => {
const row1 = wrapper.getAllByRole("row")[1];
const row2 = wrapper.getAllByRole("row")[2];
act(() => {
row1.click();
row2.click();
});
await user.click(row1);
await user.click(row2);
expect(onRowAction).toHaveBeenCalledTimes(2);
});
it("should set the proper aria-sort on an ascending sorted column header", () => {
it("should set the proper aria-sort on an ascending sorted column header", async () => {
const wrapper = render(
<Table aria-label="Static Table">
<TableHeader>

View File

@ -1,6 +1,6 @@
import * as React from "react";
import {act, render, fireEvent, within} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {focus} from "@nextui-org/test-utils";
import {Tabs, Tab, TabsProps} from "../src";
@ -50,6 +50,11 @@ function getPlacementTemplate(position: TabsProps["placement"]) {
const spy = jest.spyOn(console, "error").mockImplementation(() => {});
describe("Tabs", () => {
let user: UserEvent;
beforeEach(() => {
user = userEvent.setup();
});
afterEach(() => {
jest.clearAllMocks();
});
@ -71,7 +76,7 @@ describe("Tabs", () => {
expect(() => wrapper.unmount()).not.toThrow();
expect(spy).toBeCalledTimes(0);
expect(spy).toHaveBeenCalledTimes(0);
});
it("should render correctly (dynamic)", () => {
@ -168,26 +173,17 @@ describe("Tabs", () => {
focus(tab1);
});
await act(async () => {
await userEvent.keyboard("[ArrowRight]");
});
await user.keyboard("[ArrowRight]");
expect(tab1).toHaveAttribute("aria-selected", "false");
expect(tab2).toHaveAttribute("aria-selected", "true");
expect(tab3).toHaveAttribute("aria-selected", "false");
await act(async () => {
await userEvent.keyboard("[ArrowRight]");
});
await user.keyboard("[ArrowRight]");
expect(tab1).toHaveAttribute("aria-selected", "false");
expect(tab2).toHaveAttribute("aria-selected", "false");
expect(tab3).toHaveAttribute("aria-selected", "true");
await act(async () => {
await userEvent.keyboard("[ArrowRight]");
});
await user.keyboard("[ArrowRight]");
expect(tab1).toHaveAttribute("aria-selected", "true");
expect(tab2).toHaveAttribute("aria-selected", "false");
expect(tab3).toHaveAttribute("aria-selected", "false");
@ -220,22 +216,13 @@ describe("Tabs", () => {
focus(tab1);
});
await act(async () => {
await userEvent.keyboard("[ArrowRight]");
});
await user.keyboard("[ArrowRight]");
expect(tab2).toHaveFocus();
await act(async () => {
await userEvent.keyboard("[ArrowRight]");
});
await user.keyboard("[ArrowRight]");
expect(tab3).toHaveFocus();
await act(async () => {
await userEvent.keyboard("[ArrowLeft]");
});
await user.keyboard("[ArrowLeft]");
expect(tab2).toHaveFocus();
expect(tab1).toHaveAttribute("aria-selected", "true");
@ -280,10 +267,7 @@ describe("Tabs", () => {
const tab2 = wrapper.getByTestId("item2");
await act(async () => {
await userEvent.click(tab2);
});
await user.click(tab2);
expect(tab2).toHaveAttribute("aria-selected", "false");
});
@ -396,16 +380,10 @@ describe("Tabs", () => {
focus(tab1);
});
await act(async () => {
await userEvent.keyboard("[ArrowRight]");
});
await user.keyboard("[ArrowRight]");
expect(tab2).toHaveFocus();
await act(async () => {
await userEvent.keyboard("[ArrowLeft]");
});
await user.keyboard("[ArrowLeft]");
expect(tab1).toHaveFocus();
expect(input).toHaveValue("23");

View File

@ -30,7 +30,7 @@ describe("Tooltip", () => {
expect(() => wrapper.unmount()).not.toThrow();
expect(spy).toBeCalledTimes(0);
expect(spy).toHaveBeenCalledTimes(0);
});
it("ref should be forwarded", () => {

View File

@ -1,4 +1,4 @@
import {renderHook, act} from "@testing-library/react-hooks";
import {renderHook, act} from "@testing-library/react";
import {useClipboard} from "../src";

View File

@ -1,4 +1,4 @@
import {renderHook, act} from "@testing-library/react-hooks";
import {renderHook, act} from "@testing-library/react";
import {usePagination} from "../src";
@ -97,6 +97,6 @@ describe("usePagination", () => {
const {result} = renderHook(() => usePagination({total: 10, onChange}));
act(() => result.current.setPage(5));
expect(onChange).toBeCalledWith(5);
expect(onChange).toHaveBeenCalledWith(5);
});
});

View File

@ -1,5 +1,5 @@
import * as React from "react";
import {renderHook, act} from "@testing-library/react-hooks";
import {renderHook, act} from "@testing-library/react";
import {render} from "@testing-library/react";
import {useRefState} from "../src";

View File

@ -1,4 +1,4 @@
import {renderHook} from "@testing-library/react-hooks";
import {renderHook} from "@testing-library/react";
import { {{camelCase hookName}} } from "../src";

1103
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
import "@testing-library/jest-dom/extend-expect";
import "@testing-library/jest-dom";
import { configure } from "@testing-library/react";
const {getComputedStyle} = window;