Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When testing, code that causes React state updates should be wrapped into act

Tags:

I have this test:

import {
  render,
  cleanup,
  waitForElement
} from '@testing-library/react'

const TestApp = () => {
  const { loading, data, error } = useFetch<Person>('https://example.com', { onMount: true });

  return (
    <>
      {loading && <div data-testid="loading">loading...</div>}
      {error && <div data-testid="error">{error.message}</div>}
      {data && 
        <div>
          <div data-testid="person-name">{data.name}</div>
          <div data-testid="person-age">{data.age}</div>
        </div>
      }
    </>
  );
};

  describe("useFetch", () => {
    const renderComponent = () => render(<TestApp/>);

    it('should be initially loading', () => {
      const { getByTestId } = renderComponent();

      expect(getByTestId('loading')).toBeDefined();
    })
  });

The test passes but I get the following warning:

Warning: An update to TestApp 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
    in TestApp

console.error node_modules/react-dom/cjs/react-dom.development.js:506 Warning: An update to TestApp 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
    in TestApp
like image 607
dagda1 Avatar asked Jun 23 '19 08:06

dagda1


People also ask

When testing code that causes React State updates should be wrapped into act React?

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.

When should you wrap for the act?

So you're supposed to wrap every interaction you make with your component in act to let React know that we expect our component to perform some updates and when you don't do that and there are updates, React will warn us that unexpected updates happened.

Do I need to use ACT WITH React testing library?

You don't need to use act() actually. testing-library/react overrides eventWrapper() so the event functions are executed in act() . Therefore you don't have to wrap any event like userEvent with act() .

What is act in React testing library?

react-dom/test-utils provides a helper called act() that makes sure all updates related to these “units” have been processed and applied to the DOM before you make any assertions: act(() => { // render components }); // make assertions.


2 Answers

The key is to await act and then use async arrow function.

await act( async () => render(<TestApp/>));

Source:

https://stackoverflow.com/a/59839513/3850405

like image 118
Ogglas Avatar answered Sep 29 '22 03:09

Ogglas


Try asserting inside 'await waitFor()' - for this your it() function should be async

it('should be initially loading', async () => {
  const { getByTestId } = renderComponent();

  await waitFor(() => {
    expect(getByTestId('loading')).toBeDefined();
  });
});

Keep calm and happy coding

like image 36
sugaith Avatar answered Sep 29 '22 03:09

sugaith