I have a test that generates the warning An update to DropDownMultiPick inside a test was not wrapped in act(...)
And the warning points to this code :
10 | const toggleDropdown = () => {
> 11 | setIsOpen(!isOpen);
| ^
12 | };
my component
const DropDownMultiPick = ({ title, options, selectedOptions, handleOptionsChange }) => {
const [isOpen, setIsOpen] = useState(false);
const [tempSelectedOptions, setTempSelectedOptions] = useState([...selectedOptions]);
const toggleDropdown = () => {
setIsOpen(!isOpen);
};
...
My test
const title = "Test Options";
const options = ["Option 1", "Option 2", "Option 3"];
const selectedOptions = ["Option 1"];
const handleOptionsChange = jest.fn();
it("should open and close the dropdown menu on toggle button click", async () => {
render(
<DropDownMultiPick
title={title}
options={options}
selectedOptions={selectedOptions}
handleOptionsChange={handleOptionsChange}
/>
);
const user = userEvent.setup();
const toggleButton = screen.getByRole("button", { name: "Option 1" });
await user.click(toggleButton);
// expect(await screen.findByRole("button", { name: /done/i })).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByRole("button", { name: /done/i })).toBeInTheDocument();
});
});
What I tried
I added an act
in my component. The warning is gone, but I don't think it is the best solution to add the act
at this place!
const DropDownMultiPick = ({ title, options, selectedOptions, handleOptionsChange }) => {
const [isOpen, setIsOpen] = useState(false);
const [tempSelectedOptions, setTempSelectedOptions] = useState([...selectedOptions]);
const toggleDropdown = async () => {
await act(async () => {
setIsOpen(!isOpen);
});
};
Question
What is the best solution to get rid of this warning? I looked on this website, but it dit not help : https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warning
EDIT
The whole component :
// src/components/batchrec/dropdown-menu-multipick.jsx
import React, { useState } from "react";
import "./dropdown-menu-multipick.styles.scss";
const DropDownMultiPick = ({ title, options, selectedOptions, handleOptionsChange }) => {
const [isOpen, setIsOpen] = useState(false);
const [tempSelectedOptions, setTempSelectedOptions] = useState([...selectedOptions]);
const toggleDropdown = () => {
setIsOpen(!isOpen);
};
const handleItemClick = (option) => {
if (tempSelectedOptions.includes(option)) {
setTempSelectedOptions(tempSelectedOptions.filter((item) => item !== option));
} else {
setTempSelectedOptions([...tempSelectedOptions, option]);
}
};
const handleClose = () => {
setIsOpen(false);
};
const handleDone = () => {
handleOptionsChange(tempSelectedOptions);
handleClose();
};
return (
<div className="dropdown-multipick__container">
<span className="label-title-style-5">
<span className="dropdown-multipick__text label-title-style-1">{title}: </span>
<button className="dropdown-multipick__toggle" onClick={toggleDropdown}>
{selectedOptions.join(", ") || "Select..."}
</button>
</span>
{isOpen && (
<div className="dropdown-multipick__menu">
{options.map((option, index) => (
<div
key={index}
className={`dropdown-multipick__item ${
tempSelectedOptions.includes(option) ? "dropdown-multipick__item--selected" : ""
}`}
onClick={() => handleItemClick(option)}
>
{option}
</div>
))}
<button className="dropdown-multipick__done" onClick={handleDone}>
Done
</button>
</div>
)}
</div>
);
};
export default DropDownMultiPick;
toggleDropdown
is called? Is there any asynchronous events? – Mainsheetact
is supposed to be put in the test, not in your components. You can try to wrap theuser.click
event into anact
– Lilah@testing-library/react
version and@testing-library/user-event
. Can you try upgrading both of them to latest version? (@testing-library/[email protected]
and@testing-library/[email protected]
) – Mainsheet