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, }),
The only way to update a state inside a store is to dispatch an action and define a reducer function to perform tasks based on the given actions. Once dispatched, the action goes inside the reducer functions which performs the tasks and return the updated state to the store. This is what Redux is all about.
Redux can be tested with any test runner, since it's just plain JavaScript. One common option is Jest, a widely used test runner that comes with Create-React-App, and is used by the Redux library repos. If you're using Vite to build your project, you may be using Vitest as your test runner.
In most apps, the need to update the Redux store arises when data in the backend is updated and we need to update the store to reflect the same changes so that presentation to the frontend is possible without reloading updated data from backend. In most cases it involves add, update, and delete.
redux-mock-store. A mock store for testing Redux async action creators and middleware. The mock store will create an array of dispatched actions which serve as an action log for tests. Please note that this library is designed to test the action-related logic, not the reducer-related one.
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' });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With