redux-testkit
Advanced tools
Comparing version 0.1.9 to 0.1.10
@@ -25,2 +25,6 @@ Object.defineProperty(exports,"__esModule",{value:true});exports.ActionTest=undefined;var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};}();var _lodash=require('lodash');var _lodash2=_interopRequireDefault(_lodash);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call&&(typeof call==="object"||typeof call==="function")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass);}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}var | ||
return _lodash2.default.isNumber(index)?this.dispatched[index]:this.dispatched; | ||
}},{key:'getNumberOfDispatched',value:function getNumberOfDispatched() | ||
{ | ||
return this.dispatched.length; | ||
}},{key:'dispatchSync',value:function dispatchSync( | ||
@@ -62,4 +66,2 @@ | ||
this.dispatched.push(new DispatchedFunction(action)); | ||
}else if(_lodash2.default.has(action,'_instance')){ | ||
this.dispatched.push(new DispatchedEvent(action)); | ||
}else if(_lodash2.default.has(action,'type')){ | ||
@@ -121,20 +123,2 @@ this.dispatched.push(new DispatchedObject(action)); | ||
return this.action.name; | ||
}}]);return DispatchedFunction;}(Dispatched);var | ||
DispatchedEvent=function(_Dispatched3){_inherits(DispatchedEvent,_Dispatched3);function DispatchedEvent(){_classCallCheck(this,DispatchedEvent);return _possibleConstructorReturn(this,(DispatchedEvent.__proto__||Object.getPrototypeOf(DispatchedEvent)).apply(this,arguments));}_createClass(DispatchedEvent,[{key:'isEvent',value:function isEvent() | ||
{ | ||
return true; | ||
}},{key:'getInstance',value:function getInstance() | ||
{ | ||
return this.action._instance; | ||
}},{key:'getInstanceType',value:function getInstanceType() | ||
{ | ||
return this.getInstance().constructor; | ||
}},{key:'getParams',value:function getParams() | ||
{ | ||
return this.getInstance().params; | ||
}}]);return DispatchedEvent;}(Dispatched); | ||
}}]);return DispatchedFunction;}(Dispatched); |
@@ -1,2 +0,3 @@ | ||
Object.defineProperty(exports,"__esModule",{value:true});exports.ReducerTest=undefined;var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};}();var _lodash=require('lodash');var _lodash2=_interopRequireDefault(_lodash);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}var | ||
Object.defineProperty(exports,"__esModule",{value:true});exports.ReducerTest=undefined;var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};}(); | ||
var _lodash=require('lodash');var _lodash2=_interopRequireDefault(_lodash);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}var | ||
@@ -39,22 +40,23 @@ ReducerTest=exports.ReducerTest=function(){ | ||
x,y){ | ||
if(typeof x=="object"&&x!=null&&typeof y=="object"&&y!=null){ | ||
if(Object.keys(x).length!=Object.keys(y).length) | ||
if(typeof x==="object"&&x!==null&&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(!this.deepEqual(x[prop],y[prop])) | ||
if(y.hasOwnProperty(prop)){ | ||
if(!this.deepEqual(x[prop],y[prop])){ | ||
return false; | ||
}else | ||
} | ||
}else{ | ||
return false; | ||
} | ||
} | ||
return true; | ||
}else | ||
if(x!==y) | ||
return false;else | ||
}else if(x!==y){ | ||
return false; | ||
}else{ | ||
return true; | ||
} | ||
}}]);return ReducerTest;}(); |
{ | ||
"name": "redux-testkit", | ||
"version": "0.1.9", | ||
"version": "0.1.10", | ||
"description": "Test kit for redux", | ||
@@ -5,0 +5,0 @@ "author": "Yedidya Kennard <yedidyak@gmail.com>", |
# redux-testkit | ||
##Testkit for redux actions (thunks or otherwise) | ||
##Testkit for redux reducers and redux actions (thunks or otherwise) | ||
@@ -12,8 +12,8 @@ ### Installation | ||
### Usage | ||
### Usage - Actions | ||
To import the module in your test file, use | ||
`import {MockStore} from 'redux-testkit';` | ||
`import {ActionTest} from 'redux-testkit';` | ||
MockStore provides these methods: | ||
ActionTest provides these methods: | ||
@@ -26,3 +26,3 @@ #### reset() | ||
beforeEach(() => { | ||
mockStore.reset(); | ||
actionTest.reset(); | ||
}); | ||
@@ -48,7 +48,7 @@ ``` | ||
``` | ||
then you send this to the mockStore with `mockStore.dispatchSync(actionToTest(paramObjects));`. | ||
then you send this to the mockStore with `actionTest.dispatchSync(actionToTest(paramObjects));`. | ||
The testkit will run this test **synchronously** and then you can run `expect` asertations on the output with: | ||
#### getActions() | ||
#### getDispatched() | ||
@@ -65,7 +65,10 @@ This is where you do the work in the tests. To unit test an action, you want to test what effect the action has given a specific starting environment. We set up this environment before the test with `setState()` and by passing parameters. There are three ways a dispatched action can cause effects: | ||
`getActions()` returns an `array` of all the dispatches sent by the tested action, in order. In case 1, the entire object is saved and you can `expect` it to have a type and other fields, for example: | ||
`getDispatched()` returns an `array` of all the dispatches sent by the tested action, in order. In case 1, the entire object is saved and you can `expect` it to have a type and other fields, for example: | ||
`getDispatched(n)` returns an object with data about the dispatched at position `n`. | ||
``` | ||
expect(mockStore.getActions()[0].type).toEqual(actionTypes.ACTION_TYPE_1); | ||
expect(mockStore.getActions()[0].otherField).toEqual({some object}); | ||
expect(getDispatched(0).isPlainObject()). toBeTrue(); | ||
expect(getDispatched(0).getType()).toEqual(actionTypes.ACTION_TYPE_1); | ||
expect(getDispatched(0).getParams().otherField).toEqual({some object}); | ||
``` | ||
@@ -76,3 +79,4 @@ | ||
``` | ||
expect(mockStore.getActions()[1]).toEqual('name_of_function'); | ||
expect(uut.getDispatched(1).isFunction()).toBeTrue(); | ||
expect(uut.getDispatched(1).getName()).toEqual('name_of_function'); | ||
``` | ||
@@ -89,11 +93,41 @@ | ||
To test a **synchronous** action that dispacthes other actions or objects, you should inject the `mockDispatch()` and `getState()` from the mockStore. For example: | ||
To test a **synchronous** action that dispacthes other actions or objects, you should inject the `mockDispatch()` and `getState()` from the actionTest. For example: | ||
``` | ||
const result = actions.syncAction(mockStore.mockDispatch, mockStore.getState(), params...); | ||
const result = actions.syncAction(actionTest.mockDispatch, actionTest.getState(), params...); | ||
expect(result).toEqual(123456); | ||
expect(mockStore.getActions()).to.... | ||
expect(uut.getDispatched()).to.... | ||
``` | ||
### Usage - Reducers | ||
`import {ReducerTest} from 'redux-testkit';` | ||
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. | ||
Uou can enforce immutability by using immutability libraries, but those often have a performance impact. | ||
`ReducerTest` offers a test absed new way of enforcing immutability, and syntactic sugar for testing redcuers. | ||
`ReducerTest` takes two arguments in the constructor: the first is the reduce function you want to test, and the second is an option initialState to use for each test. | ||
`ReducerTest` has two methods: | ||
#### test(name, params, testEqual) | ||
This uses your `testEqual` to test a number of cases provided in the `params`. | ||
`params` must be an arra of objects with this structure: | ||
`{action, expected, state, description}` where state and description are optional. | ||
`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. | ||
To test for immutability, use: | ||
#### throwOnMutation() | ||
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. | ||
## TODO | ||
[ ] Improve syntax with Matchers - Please open issues to suggest the syntax you'd want! |
@@ -27,2 +27,6 @@ import _ from 'lodash'; | ||
getNumberOfDispatched() { | ||
return this.dispatched.length; | ||
} | ||
dispatchSync(action) { | ||
@@ -62,4 +66,2 @@ let done = false; | ||
this.dispatched.push(new DispatchedFunction(action)); | ||
} else if (_.has(action, '_instance')) { | ||
this.dispatched.push(new DispatchedEvent(action)); | ||
} else if (_.has(action, 'type')) { | ||
@@ -123,19 +125,1 @@ this.dispatched.push(new DispatchedObject(action)); | ||
} | ||
class DispatchedEvent extends Dispatched { | ||
isEvent() { | ||
return true; | ||
} | ||
getInstance() { | ||
return this.action._instance; | ||
} | ||
getInstanceType() { | ||
return this.getInstance().constructor; | ||
} | ||
getParams() { | ||
return this.getInstance().params; | ||
} | ||
} |
@@ -0,1 +1,2 @@ | ||
/*eslint prefer-const: 0*/ | ||
import _ from 'lodash'; | ||
@@ -18,4 +19,4 @@ | ||
test(name, params, testEqual) { | ||
_.forEach(params, (param, index) => { | ||
it(`${index}:${name} ${(param.description || '')}`, () => { | ||
_.forEach(params, (param, index) => { | ||
it(`${index}:${name} ${(param.description || '')}`, () => { | ||
let {state, action, expected} = param; | ||
@@ -30,3 +31,3 @@ state = state ? state : this.initialState; | ||
if(didMutate && this.shoudThrowOnMutation) { | ||
if (didMutate && this.shoudThrowOnMutation) { | ||
throw new Error(`${index}:${name} ${(param.description || '')} mutated the state!`); | ||
@@ -41,23 +42,24 @@ } | ||
deepEqual(x, y) { | ||
if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) { | ||
if (Object.keys(x).length != Object.keys(y).length) | ||
if ((typeof x === "object" && x !== null) && (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 (! this.deepEqual(x[prop], y[prop])) | ||
for (let prop in x) { | ||
if (y.hasOwnProperty(prop)) { | ||
if (!this.deepEqual(x[prop], y[prop])) { | ||
return false; | ||
} | ||
} else { | ||
return false; | ||
} | ||
else | ||
return false; | ||
} | ||
return true; | ||
} | ||
else if (x !== y) | ||
} else if (x !== y) { | ||
return false; | ||
else | ||
} 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
109980
13
128
360