Using enzyme, mocha and expect asserts.
The aim of my unit test is to check that dispatch gets called with the correct arguments when paused and not paused in mergeProps.
I need to dynamically change the state of my store to do: paused: true
.
At the moment I try and update the paused value by dispatching but I don't think this is correct because it's just a mock and never actually runs through the reducer.
I am using the package redux-mock-store.
How do I do this?
describe('Play Container', () => {
const id = 'audio-player-1';
const store = configureMockStore()({
players: {
'audio-player-1': { paused: false }
}
});
let dispatchSpy;
let wrapper;
beforeEach(() => {
dispatchSpy = expect.spyOn(store, 'dispatch');
wrapper = shallow(
<PlayContainer className={attributes.className}>
{children}
</PlayContainer>,
{ context: { id } },
).shallow({ context: { store } });
});
it('onClick toggles play if paused', () => {
//Not Working
store.dispatch(updateOption('paused', true, id));
wrapper.simulate('click');
expect(dispatchSpy).toHaveBeenCalledWith(play(id));
});
it('onClick toggles pause if playing', () => {
wrapper.simulate('click');
expect(dispatchSpy).toHaveBeenCalledWith(pause(id));
});
});
container:
const mapStateToProps = ({ players }, { id }) => ({
paused: players[id].paused
});
const mergeProps = (stateProps, { dispatch }, { id }) => ({
onClick: () => (stateProps.paused ? dispatch(play(id)) : dispatch(pause(id)))
});
export default connectWithId(mapStateToProps, null, mergeProps)(Play);
connectWithId:
//getContext() is from recompose library and just injects id into props
export const connectWithId = (...args) => compose(
getContext({ id: React.PropTypes.string }),
connect(...args),
);
actions:
updateOption: (key, value, id) => ({
type: actionTypes.player.UPDATE_OPTION,
key,
value,
id,
}),
configureMockStore
is a factory that is used to configure a mock store by applying the specified middlewares. This factory returns a mockStore
function.
The mockStore
function itself returns an instance of the configured mock store. It doesn't change state through actions; instead it just records which actions were passed. This is because it's a utility tool to create unit tests and not "integration" (state + component) tests.
Nonetheless, you can simulate a state change. mockStore
accepts a function, so you could do the following:
import configureMockStore from 'redux-mock-store';
const middlewares = [];
const mockStore = configureMockStore(middlewares);
let state = {
players: {
'audio-player-1': { paused: false }
}
};
const store = mockStore(() => state);
Then in your tests, you can do:
state = NEW_STATE;
// now you need to make the components update the state.
// so you can dispatch any action so the mock store will notify the subscribers
store.dispatch({ type: 'ANY_ACTION' });