DEV Community

Cover image for Unit Testing Components with Jest in React Native. Setup and Trouble Resolutions
Daniil Sitdikov
Daniil Sitdikov

Posted on

Unit Testing Components with Jest in React Native. Setup and Trouble Resolutions

Setup

1. Jest configuration

I removed properties not related to react-native (such as testMatch, testUrl, etc.)

"jest": {
    "preset": "react-native",
    "moduleNameMapper": {
        "styled-components": "styled-components/native"
    },
    "transform": {
        "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
    }
}
Enter fullscreen mode Exit fullscreen mode

Also, it could be jest.config.js (depends on your project organization)

2. Mocking store

I used redux-mock-store.

1. For decrease duplicate code I put it into mocks.

As an example of middleware, there is a thunk here. You could use any.

import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';

const middlewares = [thunk];
const mockStore = configureStore(middlewares);

export default mockStore;
Enter fullscreen mode Exit fullscreen mode

Redux mock store located in mocks folder

2. I've created a separate render component function.

import { render } from 'react-native-testing-library';
import { Provider } from 'react-redux';
import * as React from 'react';

export function renderComponent(content, store) {
    return render(<Provider store={store}>{content}</Provider>);
}
Enter fullscreen mode Exit fullscreen mode

Receives component to render as content and state of the store

3. And just use it:

import Catalog from './index';
import * as React from 'react';
import mockStore from 'redux-mock-store';
import state from '../../../dev/spec-helpers/state';
import { renderComponent } from '../../../dev/spec-helpers/render-component';

describe('Catalog', () => {
  const store = mockStore(state);

  it('should render component in init state', () => {
      const component = renderCatalog(store, { disabled: true });
      expect(component.toJSON()).toMatchSnapshot();
  });
});

function renderCatalog(store, extendedProps = {}) {
    const props = { ...extendedProps, resultId: 'P39' };
    return renderComponent(<Catalog {...props} />, store);
}
Enter fullscreen mode Exit fullscreen mode

Fragment of some component testing

3. Add more readable expect method "toBeFound"

const expect = require('expect');

expect.extend({
    toBeFound(received) {
        if (received === null) {
            return {
                message: () => 'Target node doesn\'t exist',
                pass: false
            };
        }

        return { pass: true };
    }
});
Enter fullscreen mode Exit fullscreen mode

Extension of expect-file

  1. Create a script config/jest/expect.js
  2. Add it to setupFiles in your jest config:
it('should correctly render last-date laboratory result', () => {
      const {getByText} = renderHomeResult(store);
      expect(getByText('Urogenital swab')).toBeFound();
      expect(getByText('Inhibin B')).toBeFound();
  });
Enter fullscreen mode Exit fullscreen mode

Trouble resolutions:

1. ES6 in node_modules

Error in using of es6+ libraries from node_modules such it:

/Users/dsitdikov/Projects/experimentx-dx-app/node_modules/react-native/jest/mockComponent.js:20 static displayName = 'Component'; ^ SyntaxError: Unexpected token =

Solution:

Use transformIgnorePatterns in jest config:

{
    "transformIgnorePatterns": [
        "<rootDir>/node_modules/(?!react-navigation|react-native|rn-apple-healthkit|rn-fetch-blob)"
    ]
}
Enter fullscreen mode Exit fullscreen mode

A fragment of the package.json > jest

By default, jest transformIgnorePatterns has <rootDir>/node_modules and ignores all node_modules. So that it transforms each file from es6+ to understandable es5 except node_modules. Some modules are not in es6, and we should say ignore all node_modules except react-navigation, react-native, rn-apple-healthkit, etc.

You also can read about it in jest documentation.

2. Modules don't work in jest.

Something like:

TypeError: Cannot read property 'RNFSFileTypeRegular' of undefined | import RNFS from 'react-native-fs';

Solution:

It's ok. Just:

  1. Create mocks.js in your project
  2. Add setupFiles in your jest configuration
{
    "setupFiles": [
      "<rootDir>/config/jest/mocks.js"
    ]
}
Enter fullscreen mode Exit fullscreen mode

Fragment of package.json > jest

3. For each unnecessary and unworking module write the following:

jest.mock('react-native-camera', () => {});
Enter fullscreen mode Exit fullscreen mode

An example of a mock some module

3. Error in using mocked default exported modules.

An error could be such this:

TypeError: Cannot read property 'dirs' of undefined

Solution:

Just add this to your mocks file.

jest.mock(
    'rn-fetch-blob', 
    () => ({
        __esModule: true,
        default: {
           fs: {
           dirs: {
               DocumentDir: jest.fn()
           }
        }
    })
);
Enter fullscreen mode Exit fullscreen mode

A fragment of mocks.js file

Top comments (0)