Sometimes we want to test our Redux reducers to make sure they work as expected. In this lesson we will walk through setting up some Redux reducer tests for common situations and edge cases.

 

quoteReducer.js

import {ADD_QUOTE_BY_ID, REMOVE_QUOTE_BY_ID, LIKE_QUOTE_BY_ID, UNLIKE_QUOTE_BY_ID} from './ActionTypes';

export default function quoteReducer(state = [], action) {

    function changeLikeCountById(change) {
        const newQuotes = state
            .map(quote => {
                if(quote.id === action.payload.id) {
                    switch (change) {
                        case 'increment':
                            quote.likeCount++;
                            return quote;
                        case 'decrement':
                            if(quote.likeCount > 0) {
                                quote.likeCount--;
                            }
                            return quote;
                        default:
                            return quote;
                    }
                }
                return quote;
            });
        return newQuotes;
    }

    switch(action.type) {

        case ADD_QUOTE_BY_ID:
            return state
                .concat(action.payload);

        case REMOVE_QUOTE_BY_ID:
            return state
                .filter(quote => quote.id !== action.payload.id);

        case LIKE_QUOTE_BY_ID:
            return changeLikeCountById('increment');

        case UNLIKE_QUOTE_BY_ID:
            return changeLikeCountById('decrement');

        default:
            return state;
    }
}

 

quoteReducer.spec.js:

import expect from 'expect';
import {addQuoteById, removeQuoteById, likeQuoteById, unlikeQuoteById} from './quoteActionCreator';
import quoteReducer from './quoteReducer';

describe( 'should render quote component correctly', ()=> {

    const initQuoteState = ()=> {
        return [
            {
                text: 'Lorem ipsum',
                author: 'Jane Doe',
                id: 1,
                likeCount: 7
            },
            {
                text: 'Ullamco laboris nisi ut aliquip',
                author: 'John Smith',
                id: 2,
                likeCount: 0
            }
        ];
    };

    it( 'should add quote by id', ()=> {

        const action = addQuoteById({
            text: 'This is a new quote',
            author: 'Someone awesome',
            id: 3,
            likeCount: 0
        });

        const actual = quoteReducer(initQuoteState(), action);

        const expected = [
            {
                text: 'Lorem ipsum',
                author: 'Jane Doe',
                id: 1,
                likeCount: 7
            },
            {
                text: 'Ullamco laboris nisi ut aliquip',
                author: 'John Smith',
                id: 2,
                likeCount: 0
            },
            {
                text: 'This is a new quote',
                author: 'Someone awesome',
                id: 3,
                likeCount: 0
            }
        ];

        expect( actual )
            .toEqual( expected );
    } );
} )
;

 

quoteActionCreator.js

import {ADD_QUOTE_BY_ID, REMOVE_QUOTE_BY_ID, LIKE_QUOTE_BY_ID, UNLIKE_QUOTE_BY_ID} from './ActionTypes';

export function addQuoteById(payload) {
    return {
        type: ADD_QUOTE_BY_ID,
        payload: payload
    };
}

export function removeQuoteById(payload) {
    return {
        type: REMOVE_QUOTE_BY_ID,
        payload: payload
    };
}

export function likeQuoteById(payload) {
    return {
        type: LIKE_QUOTE_BY_ID,
        payload: payload
    };
}

export function unlikeQuoteById(payload) {
    return {
        type: UNLIKE_QUOTE_BY_ID,
        payload: payload
    };
}