react-native-testing-library: Console.Error When Trying To Test NavigationContainer

Describe the bug

When trying to test NavigationContainer, I get a console.error log:

    console.error
      Warning: An update to ForwardRef(NavigationContainer) 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 ForwardRef(NavigationContainer)

Expected behavior

No console.error log.

Steps to Reproduce

import React from 'react';
import { NavigationContainer } from "@react-navigation/native";
import { render, fireEvent } from 'react-native-testing-library';

// Silence the warning https://github.com/facebook/react-native/issues/11094#issuecomment-263240420
jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper');

describe('<NavigationContainer />', () => {
  it('should match snapshot', () => {
    const result = render(<NavigationContainer>
    </NavigationContainer>);
    expect(result).toMatchSnapshot();
  })
})

Versions

npmPackages: react: ~16.9.0 => 16.9.0 react-native: ~0.61.5 => 0.61.5 react-native-testing-library: ^2.0.1 => 2.0.1 react-test-renderer: ^16.13.1 => 16.13.1

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15 (1 by maintainers)

Commits related to this issue

Most upvoted comments

I utilized async, await, and act to make it work without any warnings or errors.

import React from 'react';
import { NavigationContainer } from "@react-navigation/native";
import { act } from 'react-test-renderer';
import { render, fireEvent } from 'react-native-testing-library';

// Silence the warning https://github.com/facebook/react-native/issues/11094#issuecomment-263240420
jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper');

describe('<NavigationContainer />', () => {
  it('should match snapshot', async () => {
    const result = render(<NavigationContainer>
    </NavigationContainer>);
    await act(async () => { expect(result).toMatchSnapshot(); })
  });
});

Perhaps this will help someone…

It’s because your component wrapped in navigation perform some state updates that you don’t await for. Instead of snapshotting the whole screen, it would be better to find certain elements in it and assert if they rendered or not. Using findBy queries the library would automatically wait for the elements to appear.

If you don’t care about further updates to this component, you can call unmount on it straight away after the assertion.

Anyway it’s not a bug in the library. Learn about the act warning for your tests safety.

It seems passing an async callback means there is a “signal” sent back to react-testing library when everything is rendered. My guess is the library does its (conceptual) act checks after everything is rendered, and thus does not complain.

await act(async () => undefined)

I have a similar issue,

I utilized async, await, and act to make it work without any warnings or errors.

import React from 'react';
import { NavigationContainer } from "@react-navigation/native";
import { act } from 'react-test-renderer';
import { render, fireEvent } from 'react-native-testing-library';

// Silence the warning https://github.com/facebook/react-native/issues/11094#issuecomment-263240420
jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper');

describe('<NavigationContainer />', () => {
  it('should match snapshot', async () => {
    const result = render(<NavigationContainer>
    </NavigationContainer>);
    await act(async () => { expect(result).toMatchSnapshot(); })
  });
});

Perhaps this will help someone…

This works great but fail when putting some Navigator inside NavigationContainer

describe('<NavigationContainer />', () => {
   it('should match snapshot', async () => {
    const result = render(<NavigationContainer>
       <Stack.Navigator>
        <Stack.Screen name="Home" component={SomeComponent} />
      </Stack.Navigator>
    </NavigationContainer>);
     await act(async () => { expect(result).toMatchSnapshot(); })
   });
});

I’m getting this error just running render on the NavigationContainer (and it also repros if I put anything inside):

test("Renders nav container", () => {
  const rr = render(<NavigationContainer></NavigationContainer>);
});

Why is this closed? Still having the issue as @xD3CODER have suggested.

In addition to the wait trick above, I also had to call render in the same function as my expect call. Returning the render result from a shared async function, strangely, triggered this navigation error.

I don’t see why it would be any different - other than maybe some interaction with resolving an extra promise.