tsaga
A typesafe and lightweight way to write functions with asynchronous side-effects that are easily testable.
Examples
Setting Up a Watcher
/**
* Counts each user selection, if the user has been selected for at least 3 seconds
* (uses cancellation if a new `userSelected` action is triggered while the current saga is still running)
*/
export const countUserSelection = forLatest(userSelected, async (
$ /* fully typed environment */,
payload /* action payload */,
) => {
await $.call(sleep, 3000);
const count = $.select(getCount);
$.dispatch(setCount({ count: count + 1 }));
});
Tests
The boilerplate for creating test stubs will be reduced in the next version
When using redux-saga
with TypeScript we were often having tests failing at runtime with errors that could already be detected at compile time if we had better typings for redux-saga
/redux-saga-test-plan
. Failing test are still the best case scenario in this case, oftentimes though excess additional properties and the like were just silently being added to the state (and maybe even asserted on, in cases where message payload objects were stored directly into the state).
With the pure TypeScript approach taken by tsaga
, test declarations are fully type-checked, so one can't pass an invalid action message or wrong state shapes.
It also checks that all side-effects are mocked, and then called exhaustively and in order (or calls unmocked functions).
return testSagaWithState(
countUserSelection,
userSelected({ id: 2 }),
[calls(sleep).receiving(), selects(getCount).receiving(5)],
undefined,
userReducer,
{ count: 6, selectedUser: 2, usersById: {} },
);
We recomment using nock.disableNetConnect()
to disallow HTTP calls and to further use nock
to provide HTTP responses in tests (instead of stubbing API calling functions with dummy data).