- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 44
Warning: An update to Example inside a test was not wrapped in act(...). #25
Description
- react-nativeor- expo: react-native
- native-testing-libraryversion: 3.1.1
- jest-preset: native-testing-library
- react-nativeversion: 0.59.2
- nodeversion: 10.13.0
Relevant code or config:
import * as React from "react";
import { Button, Text, TextInput, View } from "react-native";
import { fireEvent, render, wait } from "native-testing-library";
function Example() {
  const [name, setUser] = React.useState("");
  const [show, setShow] = React.useState(false);
  return (
    <View>
      <TextInput value={name} onChangeText={setUser} testID="input" />
      <Button
        title="Print Username"
        onPress={() => {
          // let"s pretend this is making a server request, so it"s async
          // (you"d want to mock this imaginary request in your unit tests)...
          setTimeout(() => {
            setShow(!show);
          }, Math.floor(Math.random() * 200));
        }}
      />
      {show && <Text testID="printed-username">{name}</Text>}
    </View>
  );
}
test("examples of some things", async () => {
  const { getByTestId, getByText, queryByTestId } = render(<Example />);
  const famousWomanInHistory = "Ada Lovelace";
  const input = getByTestId("input");
  fireEvent.changeText(input, famousWomanInHistory);
  const button = getByText("Print Username");
  fireEvent.press(button);
  await wait(() => expect(queryByTestId("printed-username")).toBeTruthy());
  expect(getByTestId("printed-username").props.children).toBe(famousWomanInHistory);
  expect(baseElement).toMatchSnapshot();
});What you did:
Ran the example found within the documentation that demonstrates an async state update: https://www.native-testing-library.com/docs/example.
What happened:
I get a console.error message suggesting there is a problem with the tests:
console.error node_modules/react-native/Libraries/YellowBox/YellowBox.js:132
    Warning: An update to Example 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://fb.me/react-wrap-tests-with-act
        in Example
        in View (created by View)
        in View (at AppContainer.js:98)
        in View (created by View)
        in View (at AppContainer.js:115)
        in AppContainer (at src/index.js:24)
Reproduction:
See code snippet above.
Problem description:
Whenever I run the tests, I'm flooded with these console.error messages whenever I test components that make state changes after async logic such as network requests.
Suggested solution:
I feel this is a known issue, but I've not yet seen a ticket open for it on this project. I figured it would be helpful for others to reference and track the progress.
I've attempted to Google around to see if I can find a solution, but appears to be something fundamentally wrong with the underlying library that the *-testing-library family uses, react-test-renderer. This was highlighted in a react-testing-library issue and appears to have a fix on the way in React 16.9 once at least this umbrella issue is closed.
Below is my current workaround:
In my Jest config file, I have a reference to a custom setup script:
module.exports = {
  // ...
  preset: 'native-testing-library',
  setupFiles: [
    ...jestPreset.setupFiles,
    "<rootDir>/setupJest.js"
  ],
  // ...
};In the custom setup script (setupJest.js), I have the following:
// Auto-mock YellowBox component.
jest.mock("YellowBox");
const mockConsoleMethod = (realConsoleMethod) => {
  const ignoredMessages = [
    "test was not wrapped in act(...)"
  ];
  return (message, ...args) => {
    const containsIgnoredMessage = ignoredMessages.some((ignoredMessage) => message.includes(ignoredMessage));
    if (!containsIgnoredMessage) {
      realConsoleMethod(message, ...args);
    }
  };
};
// Suppress console errors and warnings to avoid polluting output in tests.
console.warn = jest.fn(mockConsoleMethod(console.warn));
console.error = jest.fn(mockConsoleMethod(console.error));Note: mockConsoleMethod is used to only suppress logs that contain "test was not wrapped in act(...)".