Search code examples
reactjsjestjsts-jest

Jest tells me to use act, but then IDE indicates it is deprecated. what is best?


Confused about whether to use act or something else?

Jest tells me to wrap in act:

"console.error, Warning: An update to ContactFormController inside a test was not wrapped in act(...). When testing, code that causes React state updates should be wrapped into act(...)"

IDE tells me act is deprecated:

"The signature '(callback: () => void | Promise): Promise' of 'act' is deprecated.ts(6387) index.d.ts(393, 4): The declaration was marked as deprecated here."

ChatGPT tells me that React batches calls so you dont need to wrap in act:

"In React 17 and above, you typically don't need to manually wrap your updates in act calls in your tests. Instead, React will automatically batch updates within test environments like Jest."

When I remove act the test fails.

What should I use as an alternative to act?

Here are the packages:

"react": "^18.2.0", 
"@testing-library/jest-dom": "^5.16.5", 
"@testing-library/react": "^13.4.0", 
"@testing-library/user-event": "^13.5.0", 

Here is my test below, this works but I get the act is deprecated warning, if I remove act the test will fail because it did not wait for the component to re-render:

import '@testing-library/jest-dom'
import { act, render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

import ContactFormController from '.'

describe('Contact Form Controller tests', () => {
  it('should render loader and disable submit button on form submit', async () => {
    const component = render(<ContactFormController />)

    const submitBtn = component.getByTestId('contact-submit-button')

    await act(async () => {
      userEvent.type(component.getByLabelText(/^First Name/i), 'Captain')
      userEvent.type(component.getByLabelText(/^Last Name/i), 'Bob')
      userEvent.type(component.getByLabelText(/^Email/i), '[email protected]')
      userEvent.type(component.getByPlaceholderText(/^Greetings/i), 'Captain Ahoy')
      userEvent.click(submitBtn)
    })

    expect(component.getByRole('alert')).toBeInTheDocument()
    expect(submitBtn).toBeDisabled()
  })
})

Solution

  • I'm guessing you're on react >= 18.3.0 and @testing-library/react <= 15.0.5.

    You can try updating to @testing-library/[email protected] which includes a fix to use act from either react-dom/test-utils or react.

    Additionally, you can upgrade to [email protected] which includes an export of act and install RTL's optional peer dep of @types/[email protected].

    Now you should be able to use act in your tests without the deprecation warning.