import * as Redux from 'redux' ; import configureStore from 'redux-mock-store' ; import thunk from 'redux-thunk' ; import combinedReducers from './reducers/CombinedReducers' ; import { AppState } from './reducers/StateTypes' ; export function newMockStoreWithInitializedState ( ) { return newMockStore ( combinedReducers ( { } as any , { type : '@@INIT' } ) ) ; } interface MockStore extends Redux . Store { clearActions : ( ) => void ; getActions : any ; } export function newMockStore ( state ) { return configureStore < AppState > ( [ thunk ] ) ( state as any as AppState ) ; } const defaultGlobalState = { settings : { numLocalPlayers : 1 } , } as any as AppState ; export function Reducer < A extends Redux . Action > ( reducer ) { const defaultInitialState = reducer ( undefined , ( { type : '@@INIT' } as any ) ) ; function internalReducerCommands ( initialState ) { const store = configureStore < AppState > ( [ thunk ] ) ( defaultGlobalState ) ; return { execute : ( action ) => { store . dispatch ( action ) ; let newState = initialState ; for ( const a of store . getActions ( ) ) { newState = reducer ( newState , a ) ; } return newState ; } , expect : ( action ) => { store . dispatch ( action ) ; let newState = initialState ; for ( const a of store . getActions ( ) ) { newState = reducer ( newState , a ) ; } return { toChangeState : ( expectedChanges ) => { expect ( newState ) . toEqual ( jasmine . objectContaining ( expectedChanges ) ) ; } , toReturnState : ( expected ) => { expect ( newState ) . toEqual ( expected ) ; } , toStayTheSame : ( ) => { expect ( newState ) . toBe ( initialState ) ; } , } ; } , } ; } return { withState : ( state ) => { const initialState = state || defaultInitialState ; return internalReducerCommands ( initialState ) ; } , } ; } export function Action < A > ( action , baseState ? ) { let store = configureStore < AppState > ( [ thunk ] ) ( ( baseState as any as AppState ) || defaultGlobalState ) ; function internalActionCommands ( ) { return { execute : ( ... a ) => { const v = store . dispatch ( action ( ... a ) ) ; if ( v && v instanceof Promise ) { return v . then ( ( ) => store . getActions ( ) ) ; } return store . getActions ( ) ; } , expect : ( ... a ) => { store . dispatch ( action ( ... a ) ) ; return { toDispatch ( expected ) { expect ( store . getActions ( ) ) . toContainEqual ( expected ) ; } , } ; } , } ; } return { withState ( storeState ) { store = configureStore < AppState > ( [ thunk ] ) ( storeState as AppState ) ; return internalActionCommands ( ) ; } , ... internalActionCommands ( ) , } ; }