Search code examples
reactjstypescriptjestjsreact-testing-library

React unit test failing


I have a unit test written in react jest and for unknown reason its failing. This is the test

  it('handles filter addition and removal', async () => {
const addNewButton = await screen.findByText('actions.addNew')

await act(async () => {
  userEvent.click(addNewButton)

  const compareDropdown = await waitFor(() => screen.getByTestId('dimensionDropdown'), { timeout: 5000 })
  userEvent.click(compareDropdown)

  const optionSelect = await screen.findByRole('option')
  userEvent.click(optionSelect)

  const treeSelect = await screen.findByTestId('dimensionValues')
  userEvent.click(treeSelect)

  const optionTreeSelect = await screen.findByRole('treeitem')
  userEvent.click(optionTreeSelect)

  const submitButton = await screen.findByTestId('filtersSubmit')
  userEvent.click(submitButton)

  await waitFor(() => {
    const chips = screen.queryByTestId('filterChips0')
    expect(chips).toBeInTheDocument()
  })

  const chips = screen.getByTestId('filterChips0')
  const chipsContent = chips.querySelector('p') as HTMLElement

  expect(chipsContent).toHaveTextContent('Department = test-1')

  const removeButton = await screen.findByTestId('removeFilterChips')
  userEvent.click(removeButton)

  await waitFor(() => {
    const chips = screen.queryByTestId('filterChips0')
    expect(chips).not.toBeInTheDocument()
  })
})
  })

The warning I receive it's

Warning: An update to DomainFilterWindow 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 */

But can not find the reason why. It seems that I wrapped the DOM changes into act, but still receive the error for it


Solution

  • I use React Native testing library, so there migth be slight differences. But I am believe you have to setup a user with userEvent.setup. user.click is already wrapped in act and it is async, so you shouldn't reWrap it and you should await it directly instead. I think the issue was that all your code was inside the act(). Also you defined 3 consts named filterChips, I don't think you want to do that. I think it should look more like this:

    const user = userEvent.setup();
    
    it('handles filter addition and removal', async () => {
      renderScreen() // I don't see where you do this, but it is best practice to have it inside your test.
      
      const addNewButton = await screen.findByText('actions.addNew')
      await user.click(addNewButton)
    
      const compareDropdown = screen.getByTestId('dimensionDropdown')
      await user.click(compareDropdown)
    
      const optionSelect = await screen.findByRole('option')
      await user.click(optionSelect)
    
      const treeSelect = await screen.findByTestId('dimensionValues')
      await user.click(treeSelect)
    
      const optionTreeSelect = await screen.findByRole('treeitem')
      await user.click(optionTreeSelect)
    
      const submitButton = await screen.findByTestId('filtersSubmit')
      await user.click(submitButton)
    
    
      const chips = screen.getByTestId('filterChips0')
      expect(chips).toBeInTheDocument()
    
      const chipsContent = chips.querySelector('p') as HTMLElement
      expect(chipsContent).toHaveTextContent('Department = test-1')
    
      const removeButton = await screen.findByTestId('removeFilterChips')
      await userEvent.click(removeButton)
    
      expect(screen.queryByTestId('filterChips0')).toBeNull()
    })