React-Boilerplate default tests throw TypeError: Cannot read property 'store' of null

Viewed 1570

I'm using React-Boilerplate to write an application and I want to test connected react components. The default "npm run generate" script generates a component/container with default tests. The index.test.js script fails by default with the following error and I haven't been able to rectify it.

I believe this error has to do with a lack of a redux "context" existing in the test. How can I provide a context so that the "store" property is defined? Why does IntlProvider not provide the context to the component automatically?

Test Code (Jest):

import { render } from 'react-testing-library';
import { IntlProvider } from 'react-intl';
// import 'jest-dom/extend-expect'; // add some helpful assertions

import { TestConnectedComponent } from '../index';
import { DEFAULT_LOCALE } from '../../../i18n';

describe('<TestConnectedComponent />', () => {
  it('Expect to not log errors in console', () => {
    const spy = jest.spyOn(global.console, 'error');
    const dispatch = jest.fn();
    render(
      <IntlProvider locale={DEFAULT_LOCALE}>
        <TestConnectedComponent dispatch={dispatch} />
      </IntlProvider>,
    );
    expect(spy).not.toHaveBeenCalled();
  });

  it('Expect to have additional unit tests specified', () => {
    expect(true).toEqual(true);
  });

Error received:

    FAIL app/containers/TestConnectedComponent/tests/index.test.js 
   <TestConnectedComponent /> › Expect to not log errors in console

        TypeError: Cannot read property 'store' of null


  at app/utils/injectReducer.js:95:44
  at commitHookEffectList (node_modules/react-dom/cjs/react-dom.development.js:17283:26)
  at commitPassiveHookEffects (node_modules/react-dom/cjs/react-dom.development.js:17307:3)
  at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:149:14)
  at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:193:27)
  at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
  at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
  at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:30:27)
  at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
  at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:199:16)
  at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:256:31)
  at commitPassiveEffects (node_modules/react-dom/cjs/react-dom.development.js:18774:9)
  at wrapped (node_modules/scheduler/cjs/scheduler-tracing.development.js:207:34)
  at flushPassiveEffects (node_modules/react-dom/cjs/react-dom.development.js:18822:5)
  at scheduleRootUpdate (node_modules/react-dom/cjs/react-dom.development.js:20570:3)
  at updateContainerAtExpirationTime (node_modules/react-dom/cjs/react-dom.development.js:20600:10)
  at updateContainer (node_modules/react-dom/cjs/react-dom.development.js:20657:10)
  at ReactRoot.Object.<anonymous>.ReactRoot.render (node_modules/react-dom/cjs/react-dom.development.js:20953:3)
  at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:21105:12)
  at Object.render (node_modules/react-dom/cjs/react-dom.development.js:21155:12)
  at act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:1175:14)
  at render (node_modules/react-testing-library/dist/index.js:79:26)
  at Object.<anonymous> (app/containers/TestConnectedComponent/tests/index.test.js:27:37)
1 Answers

Your initial analysis is correct; This is an error caused by the store not existing.The default generated container tests do not pull in and create the store.

react-intl provides React components and an API to handle internationalization. It will not provide a store.

To add the store in a format compatible with React-Boilerplate do the following:

Firstly setup the imports

import { Provider } from 'react-redux';
import configureStore from '../../../configureStore';

then create the store just above your first 'it'

let store;

beforeAll(() => {
    store = configureStore();
});

finally use the store inside your tests

<Provider store={store}>
    ...
</Provider>

Your code with the new bits...

import { render } from 'react-testing-library';
import { IntlProvider } from 'react-intl';
// import 'jest-dom/extend-expect'; // add some helpful assertions

import { TestConnectedComponent } from '../index';
import { DEFAULT_LOCALE } from '../../../i18n';

import { Provider } from 'react-redux';
import configureStore from '../../../configureStore';

describe('<TestConnectedComponent />', () => {

  let store;
  beforeAll(() => {
      store = configureStore();
  });

  it('Expect to not log errors in console', () => {
    const spy = jest.spyOn(global.console, 'error');
    const dispatch = jest.fn();
    render(
      <Provider store={store}>
          <IntlProvider locale={DEFAULT_LOCALE}>
            <TestConnectedComponent dispatch={dispatch} />
          </IntlProvider>
      </Provider>,
    );
    expect(spy).not.toHaveBeenCalled();
  });

  it('Expect to have additional unit tests specified', () => {
    expect(true).toEqual(true);
  });
Related