redux-testkit
Advanced tools
Comparing version 0.1.17 to 0.1.18
@@ -1,3 +0,4 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof(typeof Symbol==="function"?Symbol.iterator:"@@iterator")==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==(typeof Symbol==="function"?Symbol.prototype:"@@prototype")?"symbol":typeof obj;};exports.default= | ||
'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.default= | ||
function(reducer,state){ | ||
@@ -10,3 +11,3 @@ var initialState=state||reducer(undefined,{}); | ||
var mutated=!deepEqual(initialState,originalState); | ||
var mutated=!(0,_utils.deepEqual)(initialState,originalState); | ||
@@ -16,3 +17,6 @@ return{ | ||
expect(newState).toEqual(expected); | ||
expect(mutated).toEqual(false); | ||
if(mutated){ | ||
throw new Error('state mutated after running reducer'); | ||
} | ||
}, | ||
@@ -25,27 +29,2 @@ toReturnStateWithMutation:function toReturnStateWithMutation(expected){ | ||
};var _lodash=require("lodash");var _lodash2=_interopRequireDefault(_lodash);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};} | ||
function deepEqual(x,y){ | ||
if((typeof x==="undefined"?"undefined":_typeof(x))==="object"&&x!==null&&(typeof y==="undefined"?"undefined":_typeof(y))==="object"&&y!==null){ | ||
if(Object.keys(x).length!==Object.keys(y).length){ | ||
return false; | ||
} | ||
for(var prop in x){ | ||
if(y.hasOwnProperty(prop)){ | ||
if(!deepEqual(x[prop],y[prop])){ | ||
return false; | ||
} | ||
}else{ | ||
return false; | ||
} | ||
} | ||
return true; | ||
}else if(x!==y){ | ||
return false; | ||
}else{ | ||
return true; | ||
} | ||
} | ||
};var _lodash=require('lodash');var _lodash2=_interopRequireDefault(_lodash);var _utils=require('./utils');function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};} |
{ | ||
"name": "redux-testkit", | ||
"version": "0.1.17", | ||
"version": "0.1.18", | ||
"description": "Test kit for redux", | ||
@@ -5,0 +5,0 @@ "author": "Yedidya Kennard <yedidyak@gmail.com>", |
@@ -6,2 +6,4 @@ # Redux Testkit | ||
* [Recipe - Unit testing reducers](#recipe---unit-testing-reducers) | ||
* [Recipe - Unit testing selectors](#recipe---unit-testing-selectors) | ||
* [Building and testing this library](#building-and-testing-this-library) | ||
@@ -13,2 +15,3 @@ <br> | ||
* *Unit tests* for [reducers](http://redux.js.org/docs/basics/Reducers.html) - test recipe [here](#recipe---unit-testing-reducers) | ||
* *Unit tests* for [selectors](http://redux.js.org/docs/recipes/ComputingDerivedData.html) - test recipe [here](#recipe---unit-testing-selectors) | ||
@@ -44,3 +47,3 @@ <br> | ||
}); | ||
it('should handle INCREMENT action on initial state', () => { | ||
@@ -51,3 +54,3 @@ const action = { type: 'INCREMENT' }; | ||
}); | ||
it('should handle INCREMENT action on existing state', () => { | ||
@@ -59,3 +62,3 @@ const action = { type: 'INCREMENT' }; | ||
}); | ||
}); | ||
@@ -65,13 +68,13 @@ | ||
A redux reducer is a function that takes an action object, with a `type` field, and changes the state. In almost every case the state object itself must remain immutable. | ||
A redux reducer is a pure function that takes an action object, with a `type` field, and changes the state. In almost every case the state object itself must remain immutable. | ||
#### `Reducer(reducer, state).expect(action).toReturnState(result)` | ||
Runs the `reducer` on current `state` providing an `action`. The current `state` argument is optional, if not provided uses initial state. Makes sure the returned state is `result`. | ||
Runs the `reducer` on current `state` providing an `action`. The current `state` argument is optional, if not provided uses initial state. Makes sure the returned state is `result`. | ||
Also verifies immutability - that `state` did not mutate. | ||
Also verifies immutability - that `state` did not mutate. [Why is this important? see example bug](BUG-EXAMPLES.md#reducer) | ||
#### `Reducer(reducer, state).expect(action).toReturnStateWithMutation(result)` | ||
Runs the `reducer` on current `state` providing an `action`. The current `state` argument is optional, if not provided uses initial state. Makes sure the returned state is `result`. | ||
Runs the `reducer` on current `state` providing an `action`. The current `state` argument is optional, if not provided uses initial state. Makes sure the returned state is `result`. | ||
@@ -82,2 +85,55 @@ Does not verify immutability. | ||
## Recipe - Unit testing selectors | ||
```js | ||
import { Selector } from 'redux-testkit'; | ||
import * as uut from '../reducer'; | ||
describe('numbers selectors', () => { | ||
it('should select integers from numbers state', () => { | ||
const state = { numbers: [1, 2.2, 3.14, 4, 5.75, 6] }; | ||
const result = [1, 4, 6]; | ||
Selector(uut.getIntegers).expect(state).toReturn(result); | ||
}); | ||
}); | ||
``` | ||
A redux selector is a pure function that takes the state and computes some derivation from it. This operation is read-only and the state object itself must not change. | ||
#### `Selector(selector).expect(state).toReturn(result)` | ||
Runs the `selector` function on a given `state`. Makes sure the returned result is `result`. | ||
Also verifies that `state` did not mutate. [Why is this important? see example bug](BUG-EXAMPLES.md#selector) | ||
#### `Selector(selector).expect(state, ...args).toReturn(result)` | ||
Runs the `selector` function on a given `state`. If the selector takes more arguments, provide them at `...args` (the state is always assumed to be the first argument of a selector). Makes sure the returned result is `result`. | ||
Also verifies that `state` did not mutate. | ||
<br> | ||
## Building and testing this library | ||
This section is relevant only if you want to contribute to this library or build it locally. | ||
* Install and build | ||
``` | ||
npm install | ||
npm run build | ||
``` | ||
* Run lint and tests | ||
``` | ||
npm run test | ||
``` | ||
<br> | ||
### What's Included? | ||
@@ -137,3 +193,3 @@ * [Actions Unit Tests using ActionTest](#usage---actions) | ||
2. By dispatching another action to the store | ||
3. By calling some external function | ||
3. By calling some external function | ||
@@ -182,3 +238,3 @@ In case 3, you test the effect by mocking the external function. Typically you would extract that logic to a separate class and import it into your action's class, and so you mock it by using a tool like `proxyquire` when importing you actions into the test suite. | ||
`import {ReducerTest} from 'redux-testkit';` | ||
`import {ReducerTest} from 'redux-testkit';` | ||
@@ -201,3 +257,3 @@ A redux reducer is a function that takes an action object, with a `type` field, and changes the state. In almost every case the state object itslef must be immutable. | ||
`{action, expected, state, description}` where state and description are optional. | ||
`{action, expected, state, description}` where state and description are optional. | ||
@@ -208,3 +264,3 @@ `ReducerTest` will test each case given in the params, with either the default initial state or the provided state, and asseert that the expected result is equal to the actual result. | ||
#### throwOnMutation() | ||
#### throwOnMutation() | ||
@@ -214,7 +270,7 @@ This will set the `ReducerTest` to throw an exception when the state is mutated in any test then run on it. By testing with `ReducerTest` with this set, you can insure that your state is immutable without the need for any immutability library. | ||
### Usage - WaitForAsyncsMiddleware | ||
a Helpful middleware for running integration tests that include thunk actions. | ||
a Helpful middleware for running integration tests that include thunk actions. | ||
If you want to test a complex flow in your app from end to end that has nested thunk actions calls, async calls and more, use it. | ||
To import the module in your test file, use | ||
`import {WaitForAsyncsMiddleware} from 'redux-testkit';` | ||
To import the module in your test file, use | ||
`import {WaitForAsyncsMiddleware} from 'redux-testkit';` | ||
@@ -225,3 +281,3 @@ WaitForAsyncsMiddleware provides these methods: | ||
Creates a redux middleware that captures all async actions and allows you to wait till they are all resolved. | ||
Creates a redux middleware that captures all async actions and allows you to wait till they are all resolved. | ||
@@ -251,3 +307,3 @@ ```js | ||
This method will reset the array of pending async action calls were captured. | ||
This method will reset the array of pending async action calls were captured. | ||
reset is being called every time you call `createMiddleware` method. | ||
@@ -254,0 +310,0 @@ |
import _ from 'lodash'; | ||
import {deepEqual} from './utils'; | ||
@@ -9,3 +10,3 @@ export default function(reducer, state) { | ||
const newState = reducer(initialState, action); | ||
const mutated = !deepEqual(initialState, originalState); | ||
@@ -16,3 +17,6 @@ | ||
expect(newState).toEqual(expected); | ||
expect(mutated).toEqual(false); | ||
// expect(mutated).toEqual(false); | ||
if (mutated) { | ||
throw new Error('state mutated after running reducer'); | ||
} | ||
}, | ||
@@ -26,26 +30,1 @@ toReturnStateWithMutation: (expected) => { | ||
} | ||
function deepEqual(x, y) { | ||
if ((typeof x === "object" && x !== null) && (typeof y === "object" && y !== null)) { | ||
if (Object.keys(x).length !== Object.keys(y).length) { | ||
return false; | ||
} | ||
for (let prop in x) { | ||
if (y.hasOwnProperty(prop)) { | ||
if (!deepEqual(x[prop], y[prop])) { | ||
return false; | ||
} | ||
} else { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} else if (x !== y) { | ||
return false; | ||
} else { | ||
return true; | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
46589
23
542
306