3

I'm trying to test the screen that has useEffect hook with the following:

export const SomeScreen: React.FC<Props> = ({}) => {

  const [isSensorAvailable, setIsSensorAvailable] = useState(false);

  useEffect(() => {
    const isSensorAvailableCheck = async () => {
      try {
        await FingerprintScanner.isSensorAvailable();
        setIsSensorAvailable(true);
      } catch (error) {
        console.log(error);
      }
    };

    isSensorAvailableCheck();
  }, []);
  
  ...
   Here goes code that renders View if the sensor is available
  ...
}

And I'm trying the following test:


import {default as FingerprintScannerMock} from 'react-native-fingerprint-scanner';

jest.mock('react-native-fingerprint-scanner');

(FingerprintScannerMock.isSensorAvailable as jest.Mock).mockResolvedValue(true);

const createTestProps = (props: Object) => ({
  navigation: {
    navigate: jest.fn(),
  },
  ...props,
});

describe('Testing some screen', () => {

   test('testing some functionalities', async () => {
     let props: any;
    props = createTestProps({});

    const component = render(
      <Provider store={store}>
        <RegisterPasswordScreen {...props} />
      </Provider>,
    );

    const {getByText, getByTestId, getAllByTestId} = component;

    const container = getByTestId('containerId');

    expect(container).toBeTruthy();
   });

});

But this container is never found because setIsSensorIsAvailable never sets the value to true because of the following error:

An update to SomeScreen inside a test was not wrapped in act(...).

I tried everything even like this:


  const component = await waitFor(() =>
       render(<Provider store={store}>
         <RegisterPasswordScreen {...props} />
        </Provider>,
       );
   ); 

But when I run this test it never ends. Tried also to wrap it with act(...) but that does not work either, then the error is following: Can't access .root on unmounted test renderer.

Any help appreciated, thanks!

cinemanja
  • 481
  • 6
  • 19

2 Answers2

2

Had a similar issue

Wrapping the component using act(https://reactjs.org/docs/testing-recipes.html#act) solved my issue

Using create to wrap your component for react native instead of using a typical render method wrapped in act

import { act, create } from 'react-test-renderer';


it('test', () => {
    await act(async () => {
        create(<ComponentWithAsyncUseEffect />);
    });
})
Elvis Enyi
  • 21
  • 3
1

I ended up using findByTestId rather than getByTestId and now it works well.

cinemanja
  • 481
  • 6
  • 19
  • For those curious, the reason `find` works instead of `get` is that `find` returns a promise and retries until the element is located or the timeout hits. You can also use `waitFor` to test components with asynchronous lifecycles. See [About Queries](https://testing-library.com/docs/queries/about/) for details. – ggorlen Nov 07 '21 at 05:32