I am rendering the component in an integration test of my single page app and attempting to follow a happy path from landing on a page to the first question of a quiz / memory game.
Warning: An update to GamePlay inside a test was not wrapped in act(...).
The second line is the one that triggers multiple warnings...
const firstItem = getAllByRole("listitem")[0]
userEvent.click(firstItem)
It clicks the first option in a list which causes the gameplay component to render. That component shows a word for 5000ms then hides it using a setTimeout which is set in the component's useEffect hook (below). An answer input field is also disabled and enabled in this routine.
function hideQuestion() {
setInputDisabled(false)
setDisplayWord(false)
}
const [displayWord, setDisplayWord]= useState(true);
useEffect(()=>{
setTimeout(hideQuestion, 5000)
},[displayWord])
const [inputDisabled, setInputDisabled] = useState(true);
From reading around I think it might be this use of setTimeout that's responsible but none of the mitigations I have tried have done anything. I tried wrapping the click line in an "act" function and that did nothing. I tried making the test async and awaiting that line but again that did nothing - I still get this error (and several similar)...
console.error
Warning: An update to GamePlay inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
at GamePlay (/home/user/code/spellingapp/src/components/GamePlay.js:3:20)
at MainPage (/home/user/code/spellingapp/src/components/MainPage.js:8:29)
at Route (/home/user/code/spellingapp/node_modules/react-router/cjs/react-router.js:470:29)
at Switch (/home/user/code/spellingapp/node_modules/react-router/cjs/react-router.js:676:29)
at Router (/home/user/code/spellingapp/node_modules/react-router/cjs/react-router.js:99:30)
at BrowserRouter (/home/user/code/spellingapp/node_modules/react-router-dom/cjs/react-router-dom.js:67:35)
at App (/home/user/code/spellingapp/src/App.js:16:29)
5 | function hideQuestion() {
6 | // console.log("I have hidden the word and enabled the text box")
> 7 | setInputDisabled(false)
I tried reading this article: https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warning
But I'm struggling to understand it fully and relate it to my own code. I think the gist of it is that you will get these warning when there are "unexpected" state changes but I can't see how I'm supposed to make mine expected. My app is a real time game so the whole thing runs off timers - one timer finishes and another one starts. I don't want to have to run through a full 10 minutes of gameplay so it can finish neatly. I just want to test from landing page to the first interaction as a smoke test of the core integration logic.
Right now all I can think of is to make a test fixture with only one question so I can run the whole game end to end, but this seems like overkill when my current test runs fine (apart from the warnings) and does all I want it to do right now. I'd appreciate any pointers or suggestions, even if it's that I'm just barking up the wrong tree. Thanks!
userEvent.clickline? Care to share the full test that triggers the warning?