reducer.js 5.57 KB
/*
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2016 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 */
/* globals expect, it */
define('screens/player/shared/test-helper/reducer', [], function() {
    'use strict';

    /**
     * A Test Helper that provide utility methods to run reducer tests.
     *
     * @param {Reducer} [reducer] The reducer to run tests against
     * @returns {Object} The reducer Test Helper
     */
    return function(reducer) {
        var _testActionTypesExist = function(actions) {
            var actionsArray = Array.prototype.concat(actions);
            for (var i = 0; i < actionsArray.length; i++) {
                var action = actionsArray[i];
                it('action is a string', function() {
                    expect(action.type).to.be.a('string');
                });
            }
        };

        var _testMutability = function(actions, initialState) {
            var actionsArray = Array.prototype.concat(actions);
            for (var i = 0; i < actionsArray.length; i++) {
                var action = actionsArray[i];
                it('reducer must not mutate the state on state change with action ' + action.type, function() {
                    var newState = reducer(initialState, action);
                    expect(initialState === newState).to.be.false;
                });
            }
        };

        var _testNonMutability = function(initialState) {
            it('reducer must return the state if no action', function() {
                var newState = reducer(initialState, {
                    type: 'ANOTHER_ACTION'
                });

                expect(initialState === newState).to.be.true;
            });
        };

        /**
         * A helper object to run unit tests on a reducer.
         * @class ReducerTestHelper
         */
        return {

            /**
             * Runs the default standard reducer tests (state mutability in case of action, state non mutability...).
             * @memberof ReducerTestHelper
             * @param {Object|Array} actions The reducer supported dispatched action(s). Action(s) should be triggering a state change. Supports one action and an array of actions.
             * @param {Object} [initialState] Initial state to be provided to the reducer.
             */
            runDefaultTests: function(actions, initialState) {
                _testActionTypesExist(actions);
                _testMutability(actions, initialState);
                _testNonMutability(initialState);
            },

            /**
             * Runs a state comparison test.
             * @memberof ReducerTestHelper
             * @param {String} testName Name of the test.
             * @param {Object} action Action to dispatch to the reducer.
             * @param {Object} initialState Initial state to be provided to the reducer.
             * @param {Object} newState The expected state returned by the reducer (deep compare).
             */
            runCompareStateTest: function(testName, action, initialState, newState) {
                it(testName, function() {
                    var state = reducer(initialState, action);

                    expect(state).to.deep.equal(newState);
                });
            },

            /**
             * Runs a state change test.
             * @memberof ReducerTestHelper
             * @param {String} testName Name of the test.
             * @param {Object} setterAction Action to dispatch to the reducer.
             */
            runSetterPayloadTest: function(testName, setterAction) {
                this.runCompareStateTest(testName, {
                    type: setterAction,
                    payload: {
                        p1: 'v1',
                        p2: {
                            p21: 'v21'
                        }
                    }
                }, {
                    p1: 'ov1',
                    p3: {
                        p31: 'ov31'
                    }
                }, {
                    p1: 'v1',
                    p2: {
                        p21: 'v21'
                    }
                });
            },

            /**
             * Runs a state update test.
             * @memberof ReducerTestHelper
             * @param {String} testName Name of the test.
             * @param {Object} updaterAction Action to dispatch to the reducer.
             */
            runUpdaterPayloadTest: function(testName, updaterAction) {
                this.runCompareStateTest(testName, {
                    type: updaterAction,
                    payload: {
                        p1: 'v1',
                        p2: {
                            p21: 'v21'
                        }
                    }
                }, {
                    p1: 'ov1',
                    p3: {
                        p31: 'ov31'
                    }
                }, {
                    p1: 'v1',
                    p2: {
                        p21: 'v21'
                    },
                    p3: {
                        p31: 'ov31'
                    }
                });
            }
        };
    };

});