Skip to content
This repository was archived by the owner on Jul 30, 2020. It is now read-only.
This repository was archived by the owner on Jul 30, 2020. It is now read-only.

Warning: An update to Example inside a test was not wrapped in act(...). #25

Closed
@lewie9021

Description

@lewie9021
  • react-native or expo: react-native
  • native-testing-library version: 3.1.1
  • jest-preset: native-testing-library
  • react-native version: 0.59.2
  • node version: 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(...)".

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions