Usando enzima, moka y expect afirma.
El objetivo de mi prueba unitaria es comprobar que se llama a dispatch con los argumentos correctos cuando está en pausa y no en mergeProps. Necesito cambiar dinámicamente el estado de mi tienda para hacer: paused: true
.
Por el momento, intento actualizar el valor en pausa despachando, pero no creo que esto sea correcto porque es solo una simulación y en realidad nunca se ejecuta a través del reductor.
Estoy usando el paquete redux-mock-store .
¿Cómo hago esto?
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)); }); });
envase:
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);
conectarConId:
//getContext() is from recompose library and just injects id into props export const connectWithId = (...args) => compose( getContext({ id: React.PropTypes.string }), connect(...args), );
comportamiento:
updateOption: (key, value, id) => ({ type: actionTypes.player.UPDATE_OPTION, key, value, id, }),
configureMockStore
es una fábrica que se usa para configurar una tienda simulada aplicando los middlewares especificados. Esta fábrica devuelve una función de mockStore
.
La propia función mockStore
devuelve una instancia de la tienda simulada configurada. No cambia de estado a través de acciones; en su lugar, solo registra qué acciones se aprobaron. Esto se debe a que es una herramienta de utilidad para crear pruebas unitarias y no pruebas de "integración" (estado + componente).
No obstante, puede simular un cambio de estado. mockStore
acepta una función, por lo que podría hacer lo siguiente:
import configureMockStore from 'redux-mock-store'; const middlewares = []; const mockStore = configureMockStore(middlewares); let state = { players: { 'audio-player-1': { paused: false } } }; const store = mockStore(() => state);
Luego, en tus pruebas, puedes hacer:
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' });
Lo que puede hacer es usar una tienda real en su prueba. Primero, crea una función reductora:
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; };
(Tenga en cuenta que si está de acuerdo con no conservar otro estado en esta prueba, puede simplificar lo anterior y simplemente devolver un nuevo estado).
Luego crea una tienda con ese reductor y el estado inicial:
import { createStore } from 'redux'; const store = createStore(reducer, { players: { 'audio-player-1': { paused: false } } });
Con eso, su envío con updateOption
debería dar como resultado el nuevo estado.
Ahora parece que gracias a un pr de @catarinasoliveira , puede proporcionar su reductor real que actualizará la tienda en consecuencia. Está en master pero no sé si todavía está en npm o, francamente, si hace lo que acabo de decir, pero estoy a punto de probarlo e informaré de nuevo.