React Testing Library and Redux Observable

You can use the test scheduler to test sequences in epics but integration testing breakdown if you don’t include redux observable in your test redux wrapper.

Here is how I successfully managed to integrate redux observable with react testing library by mocking out the store. This wrapper replaces the default react-testing-library render method with a render method that gives components access to redux, react-router and redux observable in a test environment.

import React from 'react';
import { render as rtlRender } from '@testing-library/react';
import { Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import { createEpicMiddleware } from 'redux-observable';
import { rootReducer, rootEpic, dependencies } from './store';

function configureStore(initialState) {
  const epicMiddleware = createEpicMiddleware({ dependencies });

  const store = createStore(
    rootReducer,
    initialState,
    applyMiddleware(epicMiddleware)
  );

  epicMiddleware.run(rootEpic);

  return store;
}

export const render = (
  ui,
  {
    route = '/',
    history = createMemoryHistory({ initialEntries: [route] }),
    initialState,
    store = configureStore(initialState),
    ...renderOptions
  } = {}
) => ({
  ...rtlRender(
    <Provider store={store}>
      <Router history={history}>{ui}</Router>
    </Provider>,
    renderOptions
  ),
  history,
  store,
});

// adding `history and store` to the returned utilities to allow you to reference it in our tests (just try to avoid using this to test implementation details).

Then to run an integration test you mock out the dependency you intend to test.

import { exampleMethod } from '../exampleAPI';

jest.mock('../exampleAPI', () => ({
  exampleMethod: jest.fn(),
}));

Then you can just write an integration test that fires the epic and asserts that the dependency was called with the correct values.

it('tests exampleMethod runs when example epic is called ', 
async () => {
      const { getByTestId, getByPlaceholderText } = render(
        <ExampleComponent />,
        {
          initialState: {
            user: {
              userId: '123',
            },
          },
        }
      );

      userEvent.type(getByPlaceholderText('Their name...'), 'Mr. Happy');
      await wait(() => {
        expect(exampleMethod).toHaveBeenCalled();
        expect(exampleMethod).toHaveBeenCalledWith('123', {
          name: 'Mr. Happy',
        });
      });
    });
 
1
Kudos
 
1
Kudos

Now read this

React + Firestore : Authentication

To get setup please refer to part 1 : React + Firestore : Get Setup In Five Steps. Please refer to part 2 for the basics of reading and writing to the database in React + Firestore: CRUD. Please refer to part 3 for how to deploy your... Continue →