Testing async action creator (using axios) in Redux with Jest - asynchronous

I have an issue creating a test for my async action creator in Redux. I am using axios for fetching and Jest for testing. Data is loaded correctly in the app itself. Just the test which I am writing is going all wrong ...
I followed Redux documentation concerning testing, but it is fetchMock used there. I have trouble transferring it to my case.
I tried two approaches which are both failing:
using moxios to mock axios
using jest.mock('axios'),
This is the code in my action creator:
import {
BG_LOAD_START,
BG_LOAD_SUCCESS,
BG_LOAD_FAILURE} from './types'
import axios from 'axios'
export const bgLoad = (url, pictureNumber=0) => {
return dispatch => {
dispatch(bgLoadStart());
return axios.get(url, {
headers: {
Authorization: `Bearer ${process.env.REACT_APP_API_KEY}`
}
})
.then(res => dispatch(bgLoadSuccess(res.data.photos[pictureNumber], res.data.name, res.data.url)))
.catch(err => dispatch(bgLoadFailure(err)))
}
}
const bgLoadStart = () => {
return {
type: BG_LOAD_START
}
}
const bgLoadSuccess = (bgImage, name, url) => {
return {
type: BG_LOAD_SUCCESS,
payload: {
bgImage,
name,
url
}
}
}
const bgLoadFailure = error => {
return {
type: BG_LOAD_FAILURE,
payload: {
...error
}
}
}
and here is what I have in my test:
import configureStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import {BG_LOAD_START, BG_LOAD_SUCCESS} from '../types'
import {bgLoad} from '../bgLoad'
import moxios from 'moxios'
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
// jest.mock('axios');
describe(`async bgLoad action`, ()=> {
beforeEach(()=>{
moxios.install()
})
afterEach(()=>{
moxios.uninstall()
})
it(`creates BG_LOAD_SUCCESS when data has been fetched`, ()=> {
const fetchedData = [{
image: 'this is example image',
name: 'my name is image',
url: 'this is example link'
}]
moxios.wait(()=>{
const request = moxios.requests.mostRecent();
request.respondWith({
status: 200,
response: fetchedData
})
})
// axios.get.mockResolvedValue(fetchedData);
const expectedActions = [
{type: BG_LOAD_START},
{type: BG_LOAD_SUCCESS,
payload: {
bgImage: fetchedData[0].image,
name: fetchedData[0].name,
url: fetchedData[0].url,
}
}
]
const store = mockStore({});
return store.dispatch(bgLoad()).then(()=>{
expect(store.getActions()).toEqual(expectedActions)
})
})
})
Here is the response with which I am getting from the console:
Expected value to equal:
[{"type": "BG_LOAD_START"}, {"payload": {"bgImage": "this is example image", "name": "my name is image", "url": "this is example link"}, "type": "BG_LOAD_SUCCESS"}]
Received:
[{"type": "BG_LOAD_START"}, {"payload": {}, "type": "BG_LOAD_FAILURE"}]

Here is the solution use jest.mock:
actionCreators.ts:
import { BG_LOAD_START, BG_LOAD_SUCCESS, BG_LOAD_FAILURE } from './types';
import axios from 'axios';
export const bgLoad = (url, pictureNumber = 0) => {
return dispatch => {
dispatch(bgLoadStart());
return axios
.get(url, {
headers: {
Authorization: `Bearer ${process.env.REACT_APP_API_KEY}`
}
})
.then(res => dispatch(bgLoadSuccess(res.data.photos[pictureNumber], res.data.name, res.data.url)))
.catch(err => dispatch(bgLoadFailure(err)));
};
};
const bgLoadStart = () => {
return {
type: BG_LOAD_START
};
};
const bgLoadSuccess = (bgImage, name, url) => {
return {
type: BG_LOAD_SUCCESS,
payload: {
bgImage,
name,
url
}
};
};
const bgLoadFailure = error => {
return {
type: BG_LOAD_FAILURE,
payload: {
...error
}
};
};
actionCreators.spec.ts:
import configureStore from 'redux-mock-store';
import thunk, { ThunkDispatch } from 'redux-thunk';
import axios from 'axios';
import { BG_LOAD_START, BG_LOAD_SUCCESS } from './types';
import { bgLoad } from './actionCreators';
import { AnyAction } from 'redux';
const middlewares = [thunk];
const mockStore = configureStore<any, ThunkDispatch<{}, any, AnyAction>>(middlewares);
jest.mock('axios', () => {
return {
get: jest.fn()
};
});
describe(`async bgLoad action`, () => {
const fetchedData = [
{
image: 'this is example image',
name: 'my name is image',
url: 'this is example link'
}
];
afterEach(() => {
jest.resetAllMocks();
});
it(`creates BG_LOAD_SUCCESS when data has been fetched`, () => {
(axios.get as jest.MockedFunction<typeof axios.get>).mockResolvedValueOnce({
data: { photos: [fetchedData[0].image], name: fetchedData[0].name, url: fetchedData[0].url }
});
const expectedActions = [
{ type: BG_LOAD_START },
{
type: BG_LOAD_SUCCESS,
payload: {
bgImage: fetchedData[0].image,
name: fetchedData[0].name,
url: fetchedData[0].url
}
}
];
const store = mockStore({});
return store.dispatch(bgLoad('https://github.com/mrdulin')).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(axios.get).toBeCalledWith('https://github.com/mrdulin', {
headers: {
Authorization: `Bearer ${process.env.REACT_APP_API_KEY}`
}
});
});
});
});
Unit test result with coverage report:
PASS src/stackoverflow/55966274/actionCreators.spec.ts
async bgLoad action
✓ creates BG_LOAD_SUCCESS when data has been fetched (20ms)
-------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-------------------|----------|----------|----------|----------|-------------------|
All files | 88.89 | 50 | 71.43 | 88.24 | |
actionCreators.ts | 86.67 | 50 | 71.43 | 85.71 | 15,37 |
types.ts | 100 | 100 | 100 | 100 | |
-------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 4.774s, estimated 6s
Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/55966274

Related

How to pass authorized context type when doing a mutation with Nexus.js

I'd like to pass a authorized Context type while I am doing a mutation, but how can I do it with nexus.js?
./src/types/Context.ts
import { PrismaClient } from "#prisma/client";
export interface Context {
uid?: string | null;
prisma: PrismaClient;
}
export interface AuthorizedContext extends Context {
uid: string;
}
create Context function which is passed to Apollo Server
import prisma from "./prisma";
import { NextApiRequest } from "next";
import { loadIdToken } from "src/auth/firebaseAdmin";
import { Context } from "src/types/Context";
import { getAuth } from "firebase/auth";
export async function createContext({
req,
}: {
req: NextApiRequest;
}): Promise<Context> {
const uid = await loadIdToken(req);
const user = getAuth();
if (user.currentUser?.uid === null) {
console.log("user not logged in");
return { prisma };
}
return {
uid,
prisma,
};
}
This schema below is also passed to Apollo Server
src/graphql/schema.ts
import { makeSchema } from "nexus";
import { join } from "path";
import * as types from "./types";
const schema = makeSchema({
types,
contextType: {
module: join(process.cwd(), "./src/types/Context.ts"),
export: "Context",
},
outputs: {
schema: join(process.cwd(), "./generated/schema.graphql"),
typegen: join(process.cwd(), "./generated/nexus-typegen.d.ts"),
},
});
export { schema };
nexus mutation:
export const createCoalDepot = extendType({
type: "Mutation",
definition: (t) => {
t.field("createCoalDepot", {
type: CoalDepot,
args: { input: nonNull(CoalDepotInput), ctx: // pass AuthorizedContext Type here to use it in createCoalDepotResolver },
resolve: createCoalDepotResolver,
});
},
});
Here is the resolver where I got a error (1) got an userId: string | null | undefined Type 'string | null | undefined' is not assignable to type 'string'.
src/graphql/resolvers/coalDepotResolver.ts
export const createCoalDepotResolver: FieldResolver<
"Mutation",
"createCoalDepot"
> = async (_, { input }, { uid, prisma }) => {
const newCoalDepot = await prisma.coalDepot.create({
data: {
address: input.address,
image: input.image,
latitude: input.coordinates?.latitude,
longitude: input.coordinates?.longitude,
coalDepotName: input.coalDepotName,
mobilePhone: input.mobilePhone,
landline: input.landline,
coalDescAndAmount: input.coalDescAndAmount,
userId: uid, // the error (1)
},
});
};

can not call action in Pinia option API

I am using Vue3 option API and Pinia .
I want to call an action in Pinia option Api from component
component
import { mapActions } from "pinia";
import { useTableStore } from "../../../stores/table";
export default {
name: "LoggingForm",
data() {
return {
login: {
username: "",
password: "",
serverhost: "",
},
};
},
methods: {
submit(){
this.getData(this.login)
}
},
computed: {
...mapActions(useTableStore, ["getData"]),
},
};
and this is store/table.js
import { defineStore } from 'pinia'
import authService from "#/api/auth.js";
export const useTableStore = defineStore({
id: 'table',
state: () => ({
table: []
}),
getters: {
headers: (state) => state.table[0],
body: (state) => state.table.slice(1)
},
actions: {
async getData1(data) {
// do something
}
},
}
})
But I get this error
I can Use state and getters perfectly Just action don't work !
what's the problem ?
Here is what you need
https://pinia.vuejs.org/core-concepts/actions.html#without-setup
In short:
computed => mapGetters
methods => mapActions
You are using mapActions with computed so that will not work

How to Make http Request to My Project API from Firebase Cloud function?

Hello I am trying to make an API Post request using Firebase cloud function,Here are the code.
My effort is to get details from cloud and make an http request to my project's API. But i am getting an error of can not find module!!i have already put it.
so how to make an api call??
Here is my index.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import {TenantServiceProxy, CreateTenantInput} from '../../src/app/cloud/cloud-service';
let _tenantService: TenantServiceProxy;
const tenant = new CreateTenantInput();
admin.initializeApp();
export const onOrganizationUpdate =
functions.firestore.document('organizations/{id}').onUpdate(change => {
const after = change.after.data()
const payload = {
data: {
OrganizationId: String(after.OrganizationId),
Name: String(after.Name),
IsDeleted: String(after.IsDeleted)
}
}
console.log("updated", payload);
https.get('https://reqres.in/api/users?page=2', (resp: any) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk: any) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log("-------------------->",JSON.parse(data));
});
}).on("error", (err: any) => {
console.log("Error: " + err.message);
});
return admin.messaging().sendToTopic("OrganizationId", payload)
})
export const onOrganizationCreate =
functions.firestore.document('organizations/{id}').onCreate(change=>{
const onCreationTime =change.data()
const payload={
data:{
organizationId:String(onCreationTime.organizationId),
name:String(onCreationTime.name),
isDeleted:String(onCreationTime.isDeleted)
},
}
console.log("created",payload);
tenant.pkOrganization = payload.data.organizationId;
tenant.name = payload.data.name;
tenant.isDeleted = Boolean(payload.data.isDeleted);
_tenantService.createTenant(tenant).subscribe(()=>{
console.log("created",payload);
});
return admin.messaging().sendToTopic("OrganizationId",payload)
})
Here is the cloud.service.module.TS
//cloud service module
import { AbpHttpInterceptor } from '#abp/abpHttpInterceptor';
import { HTTP_INTERCEPTORS } from '#angular/common/http';
import { NgModule } from '#angular/core';
import * as ApiServiceProxies from '../../app/cloud/cloud-service';
#NgModule({
providers: [
ApiServiceProxies.TenantServiceProxy,
{ provide: HTTP_INTERCEPTORS, useClass: AbpHttpInterceptor, multi: true }
]
})
export class CloudServiceModule { }
Here is My api call service
#Injectable()
export class TenantServiceProxy {
private http: HttpClient;
private baseUrl: string;
protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
constructor(#Inject(HttpClient) http: HttpClient, #Optional() #Inject(API_BASE_URL) baseUrl?: string) {
this.http = http;
this.baseUrl = baseUrl ? baseUrl : '';
}
createTenant(input: CreateTenantInput | null | undefined): Observable<void> {
let url_ = this.baseUrl + '/api/services/app/Tenant/CreateTenant';
url_ = url_.replace(/[?&]$/, '');
const content_ = JSON.stringify(input);
const options_: any = {
body: content_,
observe: 'response',
responseType: 'blob',
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
};
return this.http.request('post', url_, options_).pipe(_observableMergeMap((response_: any) => {
return this.processCreateTenant(response_);
})).pipe(_observableCatch((response_: any) => {
if (response_ instanceof HttpResponseBase) {
try {
return this.processCreateTenant(<any>response_);
} catch (e) {
return <Observable<void>><any>_observableThrow(e);
}
} else {
return <Observable<void>><any>_observableThrow(response_);
}
}));
}
protected processCreateTenant(response: HttpResponseBase): Observable<void> {
const status = response.status;
const responseBlob =
response instanceof HttpResponse ? response.body :
(<any>response).error instanceof Blob ? (<any>response).error : undefined;
const _headers: any = {}; if (response.headers) { for (const key of response.headers.keys()) { _headers[key] = response.headers.get(key); } }
if (status === 200) {
return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => {
return _observableOf<void>(<any>null);
}));
} else if (status !== 200 && status !== 204) {
return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => {
return throwException('An unexpected server error occurred.', status, _responseText, _headers);
}));
}
return _observableOf<void>(<any>null);
}
}
I have defined the module in my services.

Is there a way to mock firebase modules in jest?

Code.js
saveToFirebase = () => {
let statusMsg = ""
firebase
.firestore()
.collection("messages")
.doc(this.state.field.email)
.set(this.state.field)
.then((statusMsg = "Your Message have been submitted successfully."))
this.clearFields(statusMsg)
}
Code.test.js
it("should call mock firebase module", () => {
const docData = {
field: {
name: "Rob Bob",
email: "rob#bob.com",
phone: "9999999999",
subject: "Test subject",
message: "Test message",
},
}
const docResult = {
data: () => docData,
}
const get = jest.fn(() => Promise.resolve(docResult))
const set = jest.fn()
const doc = jest.fn(() => {
return {
set,
get,
}
})
const colllection = jest.fn((messages) => {
return { doc }
})
const firestore = () => {
return colllection
}
firebase.firestore = firestore
const mockData = { fake: "data" }
jest.clearAllMocks()
wrapper.instance().saveToFirebase()
})
While running the Code.test.js, it throws an error that firebase.firestore().collection() is not a function. Please suggest proper mocking of the firebase module for the above code and to add a case to check if firebase has successfully returned then, clearFields() is invoked.
You can use jest.spyOn(object, methodName) to mock firebase.firestore() function.
E.g.
index.jsx:
import React, { Component } from 'react';
import firebase from 'firebase';
export default class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
field: { email: 'mock#example.com' },
};
}
clearFields(statusMsg) {
console.log(statusMsg);
}
saveToFirebase = () => {
let statusMsg = '';
return firebase
.firestore()
.collection('messages')
.doc(this.state.field.email)
.set(this.state.field)
.then(() => {
statusMsg = 'Your Message have been submitted successfully.';
this.clearFields(statusMsg);
});
};
render() {
return <div>my component</div>;
}
}
index.test.jsx:
import MyComponent from '.';
import { shallow } from 'enzyme';
import React from 'react';
import firebase from 'firebase';
describe('61358076', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('should pass', async () => {
const firestoreMock = {
collection: jest.fn().mockReturnThis(),
doc: jest.fn().mockReturnThis(),
set: jest.fn().mockResolvedValueOnce(),
};
const clearFieldsSpy = jest.spyOn(MyComponent.prototype, 'clearFields');
jest.spyOn(firebase, 'firestore').mockImplementationOnce(() => firestoreMock);
const wrapper = shallow(<MyComponent></MyComponent>);
await wrapper.instance().saveToFirebase();
expect(firestoreMock.collection).toBeCalledWith('messages');
expect(firestoreMock.doc).toBeCalledWith('mock#example.com');
expect(firestoreMock.set).toBeCalledWith({ email: 'mock#example.com' });
expect(clearFieldsSpy).toBeCalledWith('Your Message have been submitted successfully.');
});
});
unit test results with 100% coverage:
PASS stackoverflow/61358076/index.test.jsx (17.824s)
61358076
✓ should pass (39ms)
console.log stackoverflow/61358076/index.jsx:1611
Your Message have been submitted successfully.
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.jsx | 100 | 100 | 100 | 100 |
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 19.945s
source code: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/61358076
Hi recently I needed to mock jest module and this is my implementation,
note: I used eventEmitter3 to handle onAuthStateChange
import EventEmitter from 'eventemitter3';
const authEmitter = new EventEmitter();
let isSignIn = true;
const user = {
displayName: 'test name',
email: 'redirectTest#test.com',
emailVerified: true,
uid: 'id123',
providerData: [
{
email: 'redirectTest#test.com',
displayName: 'redirectResultTestDisplayName',
providerId: 'google',
},
],
};
const mockFirebase: any = {
initializeApp: jest.fn().mockReturnValue({
auth: jest.fn().mockReturnValue({
currentUser: isSignIn
? {
displayName: 'redirectResultTestDisplayName',
email: 'redirectTest#test.com',
emailVerified: true,
uid: 'id123',
providerData: [
{
email: 'redirectTest#test.com',
displayName: 'redirectResultTestDisplayName',
providerId: 'google',
},
],
sendEmailVerification: jest.fn(),
}
: null,
signInWithRedirect: jest.fn(),
getRedirectResult: jest.fn().mockReturnValue({
credential: {
providerId: 'Google',
},
user: {
getIdToken: jest.fn().mockResolvedValue('abc1234'),
},
additionalUserInfo: {
profile: {
email: '__tests__#__tests__.com',
name: 'John Doe',
},
},
}),
onAuthStateChanged: jest.fn(fn => {
// sign user on start
fn(user);
// sign-out user on start
authEmitter.on('sign-out', fn, undefined);
authEmitter.on('sign-in', fn, user);
}),
signOut: jest.fn(() => {
isSignIn = false;
authEmitter.emit('sign-out');
}),
signInWithEmailAndPassword: jest.fn(() => {
isSignIn = true;
authEmitter.emit('sign-in', user);
return Promise.resolve(true);
}),
sendPasswordResetEmail: jest.fn(() => Promise.resolve(true)),
sendEmailVerification: jest.fn(() => Promise.resolve(true)),
signInWithPopup: jest.fn(() => {
isSignIn = true;
authEmitter.emit('sign-in', user);
return Promise.resolve(true);
}),
}),
firestore: jest.fn().mockReturnValue({
collection: jest.fn().mockReturnValue({
doc: jest.fn().mockReturnValue({
add: jest.fn().mockResolvedValue({
id: 'abc123',
}),
set: jest.fn().mockResolvedValue({
uid: 'abc123',
}),
}),
}),
}),
}),
auth: {
GoogleAuthProvider: class {
addScope = jest.fn();
},
GithubAuthProvider: class {
addScope = jest.fn();
},
FacebookAuthProvider: class {
addScope = jest.fn();
},
},
};
jest.mock('firebase/app', () => mockFirebase);

React-Redux Testing with Jest: Received Payload = undefined

I am trying to learn/implement jest testing into my react-redux application. My test fails saying that the received does not equal what was expected, however, the actual thunk works and returns data to my application. So I've either written the test incorrectly (which i basically copy/pasted from the redux-docs) or I'm writing my thunk incorrectly.
ACTION
export const getOddGroups = () => {
return dispatch => {
return axios.get("/api/tables/oddgroups")
.then(results => {
dispatch({type: "GET_ODD_GROUPS", payload: results.data})
}).catch(err => {
dispatch({ type: "GET_ERRORS", payload: err.response.message })
})
}
}
TEST
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import * as oddActions from '../actions/OddActions';
import fetchMock from 'fetch-mock'
const middlewares = [thunk]
const mockStore = configureMockStore(middlewares)
describe('query preview async actions', () => {
afterEach(() => {
fetchMock.restore()
})
it('creates GET_ODD_GROUPS when successful', () => {
fetchMock.get("*", {
results: { data: [{ "row1": "some data" }] },
headers: { 'content-type': 'application/json' }
})
const expectedActions = [
{ type: "GET_ODD_GROUPS", results: { data: [{ "row1": "some data" }] } },
]
const store = mockStore({ oddGroups: [] })
return store.dispatch(oddActions.getOddGroups()).then(() => {
// return of async actions
expect(store.getActions()).toEqual(expectedActions)
})
})
})
TEST RESULT OUTPUT:
expect(received).toEqual(expected) // deep equality
- Expected
+ Received
Array [
Object {
- "results": Object {
- "data": Array [
- Object {
- "row1": "some data",
- },
- ],
- },
- "type": "GET_ODD_GROUPS",
+ "payload": undefined,
+ "type": "GET_ERRORS",
},
]
EDIT - UPDATE
At the suggestion of #CoryDanielson I reworked the test using axios-mock-adapter and this post but I'm still getting the same error as above.
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import * as oddActions from '../actions/oddActions';
import axios from "axios";
import MockAdapter from 'axios-mock-adapter';
const middlewares = [thunk]
const mockStore = configureMockStore(middlewares)
let mock = new MockAdapter(axios);
describe('query preview async actions', () => {
beforeEach(function () {
/*Not sure which one is best to use in this situation yet
* will test both
*/
mock.reset(); // reset both registered mock handlers and history items with reset
//mock.restore(); //restore the original adapter (which will remove the mocking behavior)
});
it("return data for GET_ODD_GROUPS when successful", function (done) {
mock.onGet("api/tables/oddGroups")
.reply(function () {
return new Promise(function (resolve, reject) {
resolve([200, { key: 'value' }]);
});
});
const store = mockStore({ oddGroups: [] })
store.dispatch(oddActions.getOddGroups()).then(() => {
let expectedActions = [{ type: "GET_ODD_GROUPS", payload: { key: 'value' } }]
console.log(store.getActions());
expect(store.getActions()).toEqual(expectedActions);
});
setTimeout(() => {
done();
}, 1000)
});
});
LOGGING:
When I return the console state console.log(store.getActions());
Its giving me back the error dispatch action
And this console.log(store.dispatch(oddActions.getOddGroups())); returns Promise { <pending> }
FINAL SOLUTION:
After trying and failing with several options, I dropped using axios-mock-adapter and used moxios instead. After following this article I was able to successfully create tests.
Here is the solution without axios-mock-adapter, don't add too many things in your code, keep it simple. You can mock axios module manually by yourself, look at below code:
actionCreators.ts:
import axios from 'axios';
export const getOddGroups = () => {
return dispatch => {
return axios
.get('/api/tables/oddgroups')
.then(results => {
dispatch({ type: 'GET_ODD_GROUPS', payload: results.data });
})
.catch(err => {
dispatch({ type: 'GET_ERRORS', payload: err.response.message });
});
};
};
actionCreators.spec.ts:
import { getOddGroups } from './actionCreators';
import createMockStore from 'redux-mock-store';
import thunk, { ThunkDispatch } from 'redux-thunk';
import axios from 'axios';
import { AnyAction } from 'redux';
const middlewares = [thunk];
const mockStore = createMockStore<any, ThunkDispatch<any, any, AnyAction>>(middlewares);
jest.mock('axios', () => {
return {
get: jest.fn()
};
});
describe('actionCreators', () => {
describe('#getOddGroups', () => {
let store;
beforeEach(() => {
const initialState = {};
store = mockStore(initialState);
});
it('should get odd groups correctly', () => {
const mockedResponse = { data: 'mocked data' };
(axios.get as jest.MockedFunction<typeof axios.get>).mockResolvedValueOnce(mockedResponse);
const expectedActions = [{ type: 'GET_ODD_GROUPS', payload: mockedResponse.data }];
return store.dispatch(getOddGroups()).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(axios.get).toBeCalledWith('/api/tables/oddgroups');
});
});
it('should get odd groups error', () => {
const mockedError = {
response: {
message: 'some error'
}
};
(axios.get as jest.MockedFunction<typeof axios.get>).mockRejectedValueOnce(mockedError);
const expectedActions = [{ type: 'GET_ERRORS', payload: mockedError.response.message }];
return store.dispatch(getOddGroups()).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(axios.get).toBeCalledWith('/api/tables/oddgroups');
});
});
});
});
Unit test result with 100% coverage:
PASS src/stackoverflow/57730153/actionCreators.spec.ts
actionCreators
#getOddGroups
✓ should get odd groups correctly (5ms)
✓ should get odd groups error (2ms)
-------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-------------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
actionCreators.ts | 100 | 100 | 100 | 100 | |
-------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 2.934s, estimated 4s
Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57730153

Resources