Reputation: 1001
I want to test this saga API function:
export function* fetchEshopProjects(action: ProjectActionsGetEshopProjects) {
yield put(projectActions.currentEshopProjectsLoading(true))
const response: {
projects: string[],
error: Error
} = yield call(ajax.json, '/new-project/eshops-projects/?eshopId=' + action.eshopId)
if (response.error) {
yield put(projectActions.currentEshopProjectsFailed(response.error))
yield put(projectActions.currentEshopProjectsLoading(false))
} else {
yield put(projectActions.setCurrentEshopProjects(response.projects))
yield put(projectActions.currentEshopProjectsLoading(false))
}
}
I have written this test:
test('fetch projects', async() => {
mockParams({
locale: 'en-US',
});
ajax.json = jest.fn().mockResolvedValue(['kbp', 'tbp'])
const dispatched = []
await runSaga({
dispatch: (action) => dispatched.push(action),
},
fetchEshopProjects
)
expect(dispatched).toEqual([
{
type: 'CURRENT_ESHOP_PROJECTS_LOADING',
loadingState: true,
},
{
type: 'SET_CURRENT_ESHOP_PROJECTS',
payload: ['kbp', 'tbp'],
},
{
type: 'CURRENT_ESHOP_PROJECTS_LOADING',
loadingState: false,
},
])
})
It seems that the code only ever reaches the yield call(ajax.json...
part and then returns back to to testing function - thus only the first dispatch is recorded. How can I correct the test so that it will conclude successfully?
Upvotes: 0
Views: 890
Reputation: 102237
You forget to use task.toPromise for the task returned by runSaga
. Below is an working example:
saga.ts
:
import { call, put } from 'redux-saga/effects';
import { ajax } from './ajax';
export const projectActions = {
currentEshopProjectsLoading(loadingState) {
return { type: 'CURRENT_ESHOP_PROJECTS_LOADING', loadingState };
},
setCurrentEshopProjects(payload) {
return { type: 'SET_CURRENT_ESHOP_PROJECTS', payload };
},
currentEshopProjectsFailed(error) {
return { type: 'CURRENT_ESHOP_PROJECTS_FAILED', error };
},
};
export function* fetchEshopProjects(action) {
yield put(projectActions.currentEshopProjectsLoading(true));
const response: {
projects: string[];
error: Error;
} = yield call(ajax.json, '/new-project/eshops-projects/?eshopId=' + action.eshopId);
if (response.error) {
yield put(projectActions.currentEshopProjectsFailed(response.error));
yield put(projectActions.currentEshopProjectsLoading(false));
} else {
yield put(projectActions.setCurrentEshopProjects(response.projects));
yield put(projectActions.currentEshopProjectsLoading(false));
}
}
ajax.ts
:
export const ajax = {
async json(url) {},
};
saga.test.ts
:
import { runSaga } from 'redux-saga';
import { ajax } from './ajax';
import { fetchEshopProjects } from './saga';
test('fetch projects', async () => {
ajax.json = jest.fn().mockResolvedValue({ projects: ['kbp', 'tbp'] });
const dispatched: any[] = [];
await runSaga(
{
dispatch: (action) => dispatched.push(action),
},
fetchEshopProjects as any,
{ eshopId: '123' },
).toPromise();
expect(dispatched).toEqual([
{
type: 'CURRENT_ESHOP_PROJECTS_LOADING',
loadingState: true,
},
{
type: 'SET_CURRENT_ESHOP_PROJECTS',
payload: ['kbp', 'tbp'],
},
{
type: 'CURRENT_ESHOP_PROJECTS_LOADING',
loadingState: false,
},
]);
});
Test result:
PASS redux-saga-examples packages/redux-saga-examples/src/stackoverflow/71176872/saga.test.ts
✓ fetch projects (6 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 81.25 | 75 | 60 | 81.25 |
ajax.ts | 100 | 100 | 0 | 100 |
saga.ts | 80 | 75 | 75 | 80 | 12,25-26
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.623 s, estimated 3 s
Upvotes: 1