Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react native test renderer returns null in jest test #822

Closed
lukaszgoworko opened this issue May 8, 2018 · 4 comments
Closed

react native test renderer returns null in jest test #822

lukaszgoworko opened this issue May 8, 2018 · 4 comments

Comments

@lukaszgoworko
Copy link

After adding redux persist, the jest test fails, because the react-test renderer do not renders the app (returns null). App in Simulator is working. Even when I do not use a component with connect (removing Component from App.js) error did not appear, but the test-renderer returns still a null.

react-native info

Environment:
  OS: macOS High Sierra 10.13.4
  Node: 9.8.0
  Yarn: 1.5.1
  npm: 5.6.0
  Watchman: 4.9.0
  Xcode: Xcode 9.3 Build version 9E145
  Android Studio: 2.3 AI-162.3764568

Packages: (wanted => installed)
  react: 16.2.0 => 16.2.0
  react-native: 0.52.0 => 0.52.0

package.json

{
  "name": "app",
  "version": "0.1.0",
  "private": true,
  "devDependencies": {
    "babel-eslint": "^8.2.2",
    "babel-jest": "^22.4.3",
    "babel-plugin-module-resolver": "^3.1.1",
    "babel-preset-react-native-stage-0": "^1.0.1",
    "eslint": "^4.19.1",
    "eslint-config-airbnb": "^16.1.0",
    "eslint-import-resolver-babel-module": "^4.0.0",
    "eslint-plugin-import": "^2.9.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-react": "^7.7.0",
    "flow-bin": "^0.56.0",
    "jest": "^22.4.3",
    "jest-react-native": "^18.0.0",
    "react-test-renderer": "16.2.0"
  },
  "scripts": {
    "start": "react-native start",
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "test": "jest --no-cache",
    "tdd": "jest --watch",
    "flow": "flow",
    "lint": "node node_modules/eslint/bin/eslint.js ./src",
    "simulator": "react-native run-ios --simulator \"iPhone 6s\""
  },
  "jest": {
    "preset": "react-native",
    "transformIgnorePatterns": [
        "node_modules/(?!(react-native|mangobo|redux-persist)/)"
    ]
  },
  "dependencies": {
    "axios": "^0.18.0",
    "i18n-js": "^3.0.3",
    "react": "16.2.0",
    "react-native": "0.52.0",
    "react-native-i18n": "^2.0.12",
    "react-redux": "^5.0.7",
    "redux": "^4.0.0",
    "redux-axios-middleware": "^4.0.0",
    "redux-persist": "^5.9.1"
  }
}

The Test - App.test.js

import React from 'react';
import 'react-native';
import App from '@';

import renderer from 'react-test-renderer';

it('App renders without crashing', () => {
  const rendered = renderer.create(<App />).toJSON();
  expect(rendered).toBeTruthy();
});

The App Component - App.js

/* flow */
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { createStore, applyMiddleware } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import { PersistGate } from 'redux-persist/integration/react';
import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
import { Provider } from 'react-redux';
import axios from 'axios';
import axiosMiddleware from 'redux-axios-middleware';
import I18n from '@/i18n';

import reducer from '@/reducers/repos';

import RepoList from './repoList';

const persistConfig = {
  key: 'root',
  storage,
  stateReconciler: autoMergeLevel2
};

const client = axios.create({
  baseURL: 'https://api.github.com',
  responseType: 'json',
});

const persistedReducer = persistReducer(persistConfig, reducer);

const store = createStore(persistedReducer, {}, applyMiddleware(axiosMiddleware(client)));
const persistor = persistStore(store);

type Props = {}

const styles: StyleSheet.Styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    marginTop: 50,
  },
});

export default class App extends React.Component<Props> {
  render() {
    return (
      <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}>
          <View style={styles.container}>
            <Text>{I18n.t('greeting')}</Text>
            <Text>{I18n.t('start1')}</Text>
            <Text>{I18n.t('start2')}</Text>
            <Text>{I18n.t('start3')}</Text>
            <RepoList />
          </View>
        </PersistGate>
      </Provider>
    );
  }
}

The Error Output

  ✕ App renders without crashing (3146ms)

  ● App renders without crashing

    expect(received).toBeTruthy()

    Expected value to be truthy, instead received
      null

       7 | it('App renders without crashing', () => {
       8 |   const rendered = renderer.create(<App />).toJSON();
    >  9 |   expect(rendered).toBeTruthy();
      10 | });
      11 |

      at Object.<anonymous> (tests/App.test.js:9:20)

  console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:5530
    The above error occurred in the <Connect(RepoList)> component:
        in Connect(RepoList) (created by App)
        in View (created by View)
        in View (created by App)
        in PersistGate (created by App)
        in Provider (created by App)
        in App

    Consider adding an error boundary to your tree to customize error handling behavior.
    Visit https://fb.me/react-error-boundaries to learn more about error boundaries.
@co2-git
Copy link

co2-git commented May 10, 2018

it returns null because null is the value you specified as the property loading of your PersistGate component. renderer.create() sends you the element at the mount time, and not through eventual updates. Here, at mount time, PersistGate will show you the loading. Maybe use mount from enzyme, or mock PersistGate, something like this:

renderer.create(
  <App />,
  {
    createNodeMock: (element) => {
      if (element.type === PersistGate) { return element.props.children }
      return null;
   }
)

@Jekiwijaya
Copy link

Me too.
you could do this too.

jest.mock('redux-persist/integration/react', () => ({
  PersistGate: props => props.children,
}));

@ortonomy
Copy link

ortonomy commented Sep 2, 2018

Holy crap, this issue saved my bacon! I was getting soooooo frustrated why my Jest tests were failing.

@aguynamedben
Copy link
Collaborator

This seems to be a gotcha with Jest and async components that was sorted out. I'm happy to merge a PR or docs update if appropriate for the project, but closing this for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants