En utilisant des enzymes, du moka et des assertions attendues.
Le but de mon test unitaire est de vérifier que l'envoi est appelé avec les arguments corrects lorsqu'il est suspendu et non suspendu dans mergeProps. Je dois changer dynamiquement l'état de ma boutique pour faire: paused: true
.
Pour le moment, j'essaie de mettre à jour la valeur suspendue en répartissant, mais je ne pense pas que ce soit correct car c'est juste une maquette et ne passe jamais par le réducteur.
J'utilise le package redux-mock-store .
Comment puis-je faire cela?
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));
});
});
récipient:
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
est une fabrique, qui est utilisée pour configurer le faux magasin en appliquant les middlewares. renvoie l'objet mockStore
.mockStore
renvoie une instance du magasin virtuel configuré. Il ne change pas d'état par l'action. Il enregistrait juste des actions avec des actions. La raison en est que c'est un outil utilitaire pour créer des tests unitaires, pas des tests "d'intégration" (état + composant).
Néanmoins, vous pouvez simuler un changement d'état. mockStore
accepte une fonction, vous pouvez donc procéder comme suit:
import configureMockStore from 'redux-mock-store';
const middlewares = [];
const mockStore = configureMockStore(middlewares);
let state = {
players: {
'audio-player-1': { paused: false }
}
};
const store = mockStore(() => state);
Ensuite, dans vos tests, vous pouvez faire:
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' });
Ce que vous pouvez faire, c'est utiliser un vrai magasin dans votre test. Créez d'abord une fonction de réduction:
const reducer = (state, action) => {
if (action.type === actionTypes.player.UPDATE_OPTION) {
return {
...state,
players: {
...state.players,
[action.id]: {
...state.players[action.id],
[action.key]: action.value,
},
},
};
}
return state;
};
(Remarque, si vous acceptez de ne pas conserver d'autre état dans ce test, vous pouvez simplifier ce qui précède et simplement renvoyer un nouvel état.)
Créez ensuite un magasin avec ce réducteur et l'état initial:
import { createStore } from 'redux';
const store = createStore(reducer, {
players: {
'audio-player-1': { paused: false }
}
});
Avec cela, votre envoi avec updateOption
devrait entraîner le nouvel état.