How to do it...

Let's test our Redux containers:

  1. Redux containers should not have any JSX code; the best practice is to have mapStateToProps and mapDispatchToProps in our connect method passing another component (such as a Layout component) in the export, for example, let's see our Todo List Container:
  // Dependencies
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

// Components
import Layout from '../components/Layout';

// Actions
import { fetchTodo } from '../actions';

export default connect(({ todo }) => ({
todo: todo.list
}), dispatch => bindActionCreators(
{
fetchTodo
},
dispatch
))(Layout);
File: src/client/todo/container/index.js

  1. You might be wondering what exactly we need to test in here. Well, the most important things we need to test in a container are the action dispatch (the fetchTodo action) and get our todo state from Redux with data. That being said, this is our container unit test file:
  // Dependencies
import React from 'react';
import { shallow } from 'enzyme';
import configureStore from 'redux-mock-store';

// Actions
import { fetchTodo } from '../actions';

// Testable Container
import Container from './index';

// Mocking Initial State
const mockInitialState = {
todo: {
list: [
{
id: 1,
title: 'Go to the Gym'
},
{
id: 2,
title: 'Dentist Appointment'
},
{
id: 3,
title: 'Finish homework'
}
]
}
};

// Configuring Mock Store
const mockStore = configureStore()(mockInitialState);

// Mocking the Actions
jest.mock('../actions', () => ({
fetchTodo: jest.fn().mockReturnValue({ type: 'mock-FETCH_TODO_SUCCESS' })
}));

describe('Todo Container', () => {
let mockParams;
let container;

beforeEach(() => {
fetchTodo.mockClear();
mockParams = {};
mockStore.clearActions();
container = shallow(<Container {...mockParams} store={mockStore} />);
});

it('should dispatch fetchTodo', () => {
const { fetchTodo } = container.props();

fetchTodo();

const actions = mockStore.getActions();

expect(actions).toEqual([{ type: 'mock-FETCH_TODO_SUCCESS' }]);
});

it('should map todo and get the todo list from Initial State', () => {
const { todo } = container.props();
const { todo: { list }} = mockInitialState;

expect(todo).toEqual(list);
});
});
File: src/client/todo/container/index.test.js
  1. Test the fetchTodo action. This is the code for our action file:
  // Base Actions
import { request, received } from '@baseActions';

// Api
import api from '../api';

// Action Types
import { FETCH_TODO } from './actionTypes';

export const fetchTodo = () => dispatch => {
const action = FETCH_TODO;
const { fetchTodo } = api;

dispatch(request(action));

return fetchTodo()
.then(response => dispatch(received(action, response.data)));
};
File: src/client/todo/actions/index.js
  1. This is our actionTypes.js file:
  // Actions
export const FETCH_TODO = {
request: () => 'FETCH_TODO_REQUEST',
success: () => 'FETCH_TODO_SUCCESS'
};
File: src/client/todo/actions/actionTypes.js
  1. To test an async Redux Action, we need to use redux-thunk and moxios to test an action that is using axios to retrieve data from the server. Our test file should look like this:
  // Dependencies
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import moxios from 'moxios';

// Action
import { fetchTodo } from './index';

// Action Types
import { FETCH_TODO } from './actionTypes';

// Configuring Store with Thunk middleware
const mockStore = configureMockStore([thunk]);

// Response Mock
const todoResponseMock = [
{
id: 1,
title: 'Go to the Gym'
},
{
id: 2,
title: 'Dentist Appointment'
},
{
id: 3,
title: 'Finish homework'
}
];

describe('fetchTodo action', () => {
beforeEach(() => {
moxios.install();
});

afterEach(() => {
moxios.uninstall();
});

it('should fetch the Todo List', () => {
moxios.wait(() => {
const req = moxios.requests.mostRecent();

req.respondWith({
status: 200,
response: todoResponseMock
});
});

const expectedActions = [
{
type: FETCH_TODO.request()
},
{
type: FETCH_TODO.success(),
payload: todoResponseMock
}
];

const store = mockStore({ todo: [] })

return store.dispatch(fetchTodo()).then(() => {
expect(store.getActions()).toEqual(expectedActions);
});
});
});
File: src/client/todo/actions/index.test.js

  1. Let's test our reducer. This is the Todo reducer file:
  // Utils
import { getNewState } from '@utils/frontend';

// Action Types
import { FETCH_TODO } from '../actions/actionTypes';

// Initial State
const initialState = {
list: []
};

export default function todoReducer(state = initialState, action) {
switch (action.type) {
case FETCH_TODO.success(): {
const { payload: { response = [] } } = action;

return getNewState(state, {
list: response
});
}

default:
return state;
}
}
File: src/client/todo/reducer/index.js
  1. We need to test two things in our reducer: the initial state and the state when the FETCH_TODO action is a success:
  // Reducer
import todo from './index';

// Action Types
import { FETCH_TODO } from '../actions/actionTypes';

// Initial State
const initialState = {
list: []
};

describe('Todo List Reducer', () => {
it('should return the initial state', () => {
const expectedInitialState = todo(undefined, {});

expect(expectedInitialState).toEqual(initialState);
});

it('should handle FETCH_TODO when is success', () => {
const action = {
type: FETCH_TODO.success(),
payload: {
response: [
{
id: 1,
title: 'Go to the Gym'
},
{
id: 2,
title: 'Dentist Appointment'
},
{
id: 3,
title: 'Finish homework'
}
]
}
};

const expectedState = {
list: action.payload.response
};

const state = todo(initialState, action);

expect(state).toEqual(expectedState);
});
});
File: src/client/todo/reducer/index.test.js
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset