Reduction structure and side effects

I use redux-thunk and am not sure if the side effects are structured correctly ( showAlertError function). Despite the fact that at first glance the settings of my humorous test seem normal, I get an error message:

The value of jest.fn () must be a dummy function or spy. Received: undefined '

showAlertError function in the right place, or should it be in the action creator or somewhere else? Also, if this is the right place, then how can I check if he called.

 export const submitTeammateInvitation = (data) => { const config = { // config code }; return async (dispatch) => { dispatch(submitTeammateInvitationRequest(data)); try { const response = await fetch(inviteTeammateEndpoint, config); const jsonResponse = await response.json(); if (!response.ok) { showErrorAlert(jsonResponse); dispatch(submitTeammateInvitationError(jsonResponse)); throw new Error(response.statusText); } dispatch(submitTeammateInvitationSuccess(jsonResponse)); } catch (error) { if (process.env.NODE_ENV === 'development') { console.log('Request failed', error); } } }; }; 

test

 import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { showAlertError } from '../../../../_helpers/alerts'; jest.mock('../../../../_helpers/alerts'); const middlewares = [thunk]; const createMockStore = configureMockStore(middlewares); describe('submitTeammateInvitation', () => { it('dispatches the correct actions on a failed fetch request', () => { fetch.mockResponse( JSON.stringify(error), { status: 500, statusText: 'Internal Server Error' } ); const store = createMockStore({}); const expectedActions = [ submitTeammateInvitationRequestObject, submitTeammateInvitationErrorObject ]; const showAlertError = jest.fn(); return store.dispatch(submitTeammateInvitation(inviteTeammateEndpoint)) .then(() => { expect(showAlertError).toBeCalled(); // this does not work expect(store.getActions()).toEqual(expectedActions); // this works }); }); }); 
+1
javascript reactjs redux redux-thunk jestjs
source share
1 answer

You can simulate the showErrorAlert function manually. Here is the solution:

actionCreators.ts :

 import fetch from 'node-fetch'; import { showErrorAlert } from './showErrorAlert'; const SUBMIT_TEAMATE_INVITATION_REQUEST = 'SUBMIT_TEAMATE_INVITATION_REQUEST'; const SUBMIT_TEAMATE_INVITATION_SUCCESS = 'SUBMIT_TEAMATE_INVITATION_SUCCESS'; const SUBMIT_TEAMATE_INVITATION_ERROR = 'SUBMIT_TEAMATE_INVITATION_ERROR'; export const submitTeammateInvitationRequest = data => ({ type: SUBMIT_TEAMATE_INVITATION_REQUEST, payload: { data } }); export const submitTeammateInvitationSuccess = data => ({ type: SUBMIT_TEAMATE_INVITATION_SUCCESS, payload: { data } }); export const submitTeammateInvitationError = data => ({ type: SUBMIT_TEAMATE_INVITATION_ERROR, payload: { data } }); export const submitTeammateInvitation = data => { const config = { // config code }; const inviteTeammateEndpoint = 'https://github.com/mrdulin'; return async dispatch => { dispatch(submitTeammateInvitationRequest(data)); try { const response = await fetch(inviteTeammateEndpoint, config); const jsonResponse = await response.json(); if (!response.ok) { showErrorAlert(jsonResponse); dispatch(submitTeammateInvitationError(jsonResponse)); throw new Error(response.statusText); } dispatch(submitTeammateInvitationSuccess(jsonResponse)); } catch (error) { if (process.env.NODE_ENV === 'development') { console.log('Request failed', error); } } }; }; 

showErrorAlert.ts :

 export function showErrorAlert(jsonResponse) { console.log(jsonResponse); } 

actionCreators.spec.ts :

 import { submitTeammateInvitation, submitTeammateInvitationRequest, submitTeammateInvitationSuccess, submitTeammateInvitationError } from './actionCreators'; import createMockStore from 'redux-mock-store'; import thunk, { ThunkDispatch } from 'redux-thunk'; import fetch from 'node-fetch'; import { AnyAction } from 'redux'; import { showErrorAlert } from './showErrorAlert'; const { Response } = jest.requireActual('node-fetch'); jest.mock('node-fetch'); jest.mock('./showErrorAlert.ts', () => { return { showErrorAlert: jest.fn() }; }); const middlewares = [thunk]; const mockStore = createMockStore<any, ThunkDispatch<any, any, AnyAction>>(middlewares); describe('submitTeammateInvitation', () => { it('dispatches the correct actions on a failed fetch request', () => { const mockedResponse = { data: 'mocked response' }; const mockedJSONResponse = JSON.stringify(mockedResponse); const mockedData = { data: 'mocked data' }; (fetch as jest.MockedFunction<typeof fetch>).mockResolvedValueOnce( new Response(mockedJSONResponse, { status: 500, statusText: 'Internal Server Error' }) ); const intialState = {}; const store = mockStore(intialState); const expectedActions = [ submitTeammateInvitationRequest(mockedData), submitTeammateInvitationError(mockedResponse) ]; return store.dispatch(submitTeammateInvitation(mockedData)).then(() => { expect(store.getActions()).toEqual(expectedActions); expect(showErrorAlert).toBeCalledWith(mockedResponse); }); }); }); 

Unit test result with coverage report:

  PASS src/stackoverflow/47560126/actionCreators.spec.ts submitTeammateInvitation βœ“ dispatches the correct actions on a failed fetch request (11ms) -------------------|----------|----------|----------|----------|-------------------| File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s | -------------------|----------|----------|----------|----------|-------------------| All files | 89.29 | 50 | 83.33 | 90.91 | | actionCreators.ts | 89.29 | 50 | 83.33 | 90.91 | 32,35 | -------------------|----------|----------|----------|----------|-------------------| Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 5.864s 

Here is the finished demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/47560126

0
source share

All Articles