Closed krzysztofpniak closed 7 years ago
Well yeah, I didn't go into a depth because basically unit testing in redux-elm
should follow the best practices of unit testing Sagas & Reducers.
Testing reducers is very easy:
it('should increment', () => {
const initialState = reducer();
expect(reducer(initialState, { type: 'Increment' })).toEqual(1);
});
So it's all about expecting output based on input.
Testing Sagas is theoretically easy, but it's not that easy in practice because you need to follow some good practices, like for example avoiding yield*
:
function* apiSaga() {
yield put({ type: 'SetLoadingSpinner' });
try {
yield call(api);
} finally {
yield put({ type: 'ResetLoadingSpinner' });
}
}
// You better do this
function* rootSaga() {
yield take('CallAPI');
// You should realize that you can choose between call and fork
// depending on use case
yield call(apiSaga);
}
// Instead of this
function* rootSaga(){
yield take('CallAPI');
yield* apiSaga();
}
Because now you can write tests quite easily:
it('should call an API when CallAPI kicks in', function() {
const it = rootSaga();
// Saga should wait for CallAPI
expect(it.next().value).toEqual(take('CallAPI'));
// And then call the API
// which is encapsulated in apiSaga, we don't need to test internals
// because we just rely on the correctness proven by other unit test
expect(it.next().value).toEqual(apiSaga);
});
it('should show spinner, call api and hide spinner', function() {
const it = apiSaga();
// Show the spinner
expect(it.next().value).toEqual(put({ type: 'SetLoadingSpinner' }));
// Call API
expect(it.next().value).toEqual(call(api));
// Hide the spinner
expect(it.next().value).toEqual(put({ type: 'ResetLoadingSpinner' }));
});
it('should hide the spinner even when api fails', function() {
const it = apiSaga();
// Show the spinner
expect(it.next().value).toEqual(put({ type: 'SetLoadingSpinner' }));
// Call API
expect(it.next().value).toEqual(call(api));
// Even when API fails, just reset the spinner
expect(it.throw(new Error('API error'))).toEqual(put({ type: 'ResetLoadingSpinner' }));
});
However, both of these examples should rather be part of redux
and redux-saga
.
I'm 100% sure that unit tests are easy in redux-elm, but it would be nice if docs provide some of examples.