test-reducer
Version:
A simple yet smart testing framework for your redux's reducers
68 lines (50 loc) • 2.35 kB
text/typescript
import * as utils from './utils'
import * as merge from 'lodash.merge'
import * as isFunction from 'lodash.isfunction'
import * as isObject from 'lodash.isobject'
export interface IAction {
type: string;
payload?: any;
}
export class TestReducer {
private reducer: (state: any, action: IAction) => any;
private baseState: any;
private initialState: any;
private actualResult: any;
constructor (reducer: (state: any, action: IAction) => any, baseState: any = {}) {
if (!reducer) throw new Error('No reducer supplied to TestReducer');
if (!isFunction(reducer)) throw new Error('The reducer must be a function');
this.reducer = reducer;
this.baseState = baseState;
}
public givenState (initStateDiff: any = {}): TestReducer {
if(!isObject(initStateDiff)) throw new Error('initState must be an object')
this.initialState = merge({}, this.baseState, initStateDiff);
Object.freeze(this.initialState);
return this;
}
public whenActionIs (action: IAction): TestReducer {
if (this.initialState === undefined) this.givenState();
this.actualResult = this.reducer(this.initialState, action);
if (utils.objectHasCycles(this.actualResult)) throw new Error('Actual state contains cyclic objects\n');
return this;
}
public thenStateIs (nextStateDiff: any = {}): boolean {
if (!this.actualResult) throw new Error('No actual state found. Must call "When" Before calling "Then"');
const expected = merge({}, this.initialState, nextStateDiff);
if (utils.objectHasCycles(expected)) throw new Error('Expect state contains cyclic objects\n');
const diff = utils.generateDiffBetweenObjectsAsMessage(this.actualResult, expected);
if(diff) throw new Error(diff);
return true;
}
public thenStateIsExactly (expected: any = {}): boolean {
if (!this.actualResult) throw new Error('No actual state found. Must call "When" Before calling "Then"');
if (utils.objectHasCycles(expected)) throw new Error('Expect state contains cyclic objects\n');
const diff = utils.generateDiffBetweenObjectsAsMessage(this.actualResult, expected);
if(diff) throw new Error(diff);
return true;
}
public thenNoChange (): void {
this.thenStateIs({});
}
}