Unable to mock CognitoIdentityServiceProvider functions from aws-sdk in jest - reactjs

Aws.config.js
import AWS from 'aws-sdk';
AWS.config.update({
region: process.env.REACT_APP_AWS_REGION,
credentials: new AWS.CognitoIdentityCredentials({
IdentityPoolId: process.env.REACT_APP_IDENTITY_POOL_ID
})
});
const AwsCognitoIdentityServiceProvider = new AWS.CognitoIdentityServiceProvider({ apiVersion: '2016-04-18' });
export default AwsCognitoIdentityServiceProvider;
I have a function in ListUser.js
import AwsCognitoIdentityServiceProvider from 'components/aws/AwsConfig';
const userList = () =>{
var params = {
UserPoolId: process.env.REACT_APP_USERPOOL_ID,
AttributesToGet: null,
Filter:""
};
AwsCognitoIdentityServiceProvider.listUsers(params,function (err, data) {
if(data) {
//fetching data here successfully
} else {
console.log("error",err);
}
})
}
My test file ListUser.test.js
const mockListUsers = jest.fn((params) => {
return {
promise() {
return Promise.resolve('mock response');
}
};
});
jest.mock('aws-sdk', () => {
return {
CognitoIdentityServiceProvider: jest.fn(() => ({
listUsers: mockListUsers
})),
config: {
update: jest.fn()
}
};
});
describe('ListUser', () => {
test('renders ListUser component', () => {
act(() => {
render(<ListUser />);
});
});
});
I am not able to mock this function and return response I am getting error below:
TypeError: _AwsConfig.default.listUsers is not a function
90 | Filter:""
91 | };
> 92 | AwsCognitoIdentityServiceProvider.listUsers(params,function (err, data) {
I have also tried with keeping aws.sdk.js file inside mocks folder but no luck
_mocks_/aws.sdk.js
class AWS {
CognitoIdentityServiceProvider = class {
listUsers = jest.fn(() =>{
return { promise: ()=> Promise.resolve({mockresponse})}
});
};
}
module.exports = AWS;
I need to mock listUsers function but not able to do so. I have followed so many links but no luck :(

This one works for me
const AWS = require('aws-sdk');
jest.mock('aws-sdk');
AWS.CognitoIdentityServiceProvider.prototype.listUsers = jest.fn().mockReturnValue({
promise: jest.fn().mockResolvedValue({})
});

I have tried this way and worked for me.
jest.mock("aws-sdk", () => {
const cognito = { listUsers: jest.fn() };
return {
CognitoIdentityServiceProvider: jest.fn(() => cognito),
config: {
update: jest.fn(),
},
};
});
const mCognitoIdentityServiceProvider = new AWS.CognitoIdentityServiceProvider();
mCognitoIdentityServiceProvider.listUsers.mockImplementationOnce(() => {
return {
promise() {
return Promise.resolve('your mock data');
},
};
});

Related

How to test custom hooks with event listener inside useEffect?

I'm using react native and jest to create my tests. I'm facing problems to test an event listener that listens to url events from expo-linking. This event listenner is inside an useEffect hook.
Below is the code from my custom hook with my useEffect and an event listener inside:
useEffect(() => {
isMounted.current = true;
Linking.addEventListener('url', async () => {
try {
if (!navigation.isFocused() || !isMounted.current) return;
setIsLoading(true);
const response = await api.get('sessions/auth/success');
if (!response.data) return;
console.log('aqui');
const { notRegisteredUser, token } = response.data;
api.defaults.headers.authorization = `Bearer ${token}`;
if (notRegisteredUser && token) {
setIsLoading(false);
navigation.navigate('BirthDateScreen');
dispatch(
updateUser({
...notRegisteredUser,
}),
);
}
} catch (err) {
Alert.alert('Error', `${translate('loginRegisterError')}: `, err);
}
});
return () => {
isMounted.current = false;
};
}, [dispatch, navigation]);
In my test file I have the following mocks:
jest.mock('expo-linking', () => {
return {
addEventListener: (event: string, callback: () => void) => callback(),
};
});
jest.mock('#react-navigation/native', () => {
return {
useNavigation: () => ({
isFocused: mockedNavigationFocus,
navigate: mockedNavigation,
}),
};
});
jest.mock('react-redux', () => {
return {
useDispatch: jest.fn(),
};
});
jest.mock('../../../store/modules/user/actions', () => {
return {
updateUser: jest.fn(),
};
});
jest.mock('i18n-js', () => {
return {
locale: 'en',
t: () => 'any key',
};
});
Finally this is how my test looks in my first try:
it('should pass the test', async done => {
mockedNavigationFocus.mockImplementation(() => true);
apiMock.onGet('sessions/auth/success').reply(200, {
notRegisteredUser: { name: 'Logan' },
token: '123',
});
render(<LoginScreen />);
await waitFor(() =>
expect(mockedNavigation).toHaveBeenCalledWith('BirthDateScreen'),
);
done();
});
In my second try this is how my test looked (I used renderHooks from #testing-library/react-hooks):
it('should pass the test', async () => {
mockedNavigationFocus.mockImplementation(() => true);
apiMock.onGet('sessions/auth/success').reply(200, {
notRegisteredUser: { name: 'Logan' },
token: '123',
});
const { result, waitForValueToChange } = renderHook(() => useLoginButton());
const { isLoading } = result.current;
await waitForValueToChange(() => isLoading);
await waitForValueToChange(() => isLoading);
expect(mockedNavigation).toHaveBeenCalledWith('BirthDateScreen');
});
With both tests I get the following error:
test error
Another error I get is that my callback function inside useEffect runs many times before it stops and this does not happen when I am not testing.
Does anyone knows how can I write this test?

How can i test downloading excel file with jest?

I am new to testing react components with jest and enzyme. I have this example
generateExcelFile = () => {
const {actions, state} = this.props;
const dateFrom = state.getIn(['config', 'marketingQuestionReport', 'dateFrom']);
const dateTo = state.getIn(['config', 'marketingQuestionReport', 'dateTo']);
this.setState({isLoading: true, isLoadingFinished: false});
fetch(`${env.MARKETING_QUESTION_REPORT}?dateFrom=${dateFrom}&dateTo=${dateTo}`)
.then((resp) => resp.blob())
.then((blob) => {
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(
blob,
`Marketing Question Report from ${dateFrom} to ${dateTo}.xlsx`
);
}
const url = window.URL.createObjectURL(blob);
const tempLink = document.createElement('a');
tempLink.style.display = 'none';
tempLink.href = url;
tempLink.setAttribute(
'download',
`Marketing Question Report from ${dateFrom} to ${dateTo}.xlsx`
);
if (typeof tempLink.download === 'undefined') {
tempLink.setAttribute('target', '_blank');
}
document.body.appendChild(tempLink);
tempLink.click();
window.URL.revokeObjectURL(url);
toastr.success('Sucessfully generated marketing question report');
this.setState({isLoading: false, isLoadingFinished: true});
actions.clearMarketingQuestionReportDates();
})
.catch(() =>
toastr.error('An error occurred while generating marketing question report')
);
};
I am struck on .then part i don't know how to test after that the whole fetch call
What i have sofar
describe('<MarketingQuestionReportPage />', () => {
beforeEach(() => {
const fecthSpy = jest.spyOn(window, 'fetch').mockReturnValue(() =>
Promise.resolve({
blob: () =>
Promise.resolve({
size: 6682,
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
}),
})
);
});
test('generateExcelFile', () => {
const props = {
state: fromJS({
config: {
marketingQuestionReport: {
dateFrom: '2019-01-01',
dateTo: '2021-03-21',
},
},
}),
actions: {
clearMarketingQuestionReportDates: jest.fn(),
},
};
const tree = shallowSetup(props);
tree.instance().generateExcelFile();
tree.fecthSpy.toHaveBeenCalled();
});
});
i maked a instance of my component - i got prepaired the needed props for that call to work and i am sending them to my instance.After that i call my method - generateExcelFile();
On my coverage everything is freen except the fetch call. I don't know how to fix this. Please help
You need to create a spy of fetch before rendering the component with jest.spyOn(object, methodName):
test('generateExcelFile', () => {
const fetchSpy = jest.spyOn(window, "fetch").mockReturnValue(Promise.resolve({
blob: () =>
Promise.resolve({
size: 6682,
type:
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
}),
})
);
//...
const tree = shallowSetup(props);
tree.instance().generateExcelFile();
expect(fetchSpy).toHaveBeenCalled();
});
In your test you can check if fecthSpy have been called

Rematch/Effects- Error running test cases written with react testing Library

I am trying to write unit test cases for my models using react testing library but i am facing some issues executing the test cases.
My effects.js
export async function getStoredData(param1, store, param2) {
try {
dispatch(setLoading(true, 'getStoredData'));
// Check if key exists in store
const inputKeyCode = getInputKeyCode([param1, param2]);
let response = getUserDataState(store)[inputKeyCode];
if (!response) {
response = await getUserApi(param1, param2);
this.setUserData({ keyCode: inputKeyCode, keyValue: response });
}
return response;
} catch (error) {
// dispatch error
} finally {
dispatch(setLoading(false, 'getStoredData'));
}
}
My reducers.js
const INITIAL_STATE = {
userData: {},
};
const setUserData = (state, { key, value }) => ({ // {key: value}
...state,
userData: {
...state.userData,
[key]: value,
},
});
effects.test.js
import { getUserApi } from '../../../api/common';
jest.mock('../../../store', () => ({ dispatch: jest.fn() }));
jest.mock('../../../api/common', () => ({ getUserApi: jest.fn() }));
describe('getStoredData', () => {
const responseData = {};
setWith(responseData, 'data.userInformation', 12345);
const setUserData = jest.fn();
test('success', async () => {
getUserApi.mockResolvedValue(responseData);
await testModel.effects().getStoredData.call({ setuserData });
expect(setuserData).toHaveBeenCalled();
expect(setuserData).toHaveBeenCalledWith(12345);
});
test('failure', async () => {
getUserApi.mockRejectedValue(errorMsg);
await testModel.effects().getStoredData.call({ setuserData });
expect(showNotification).toHaveBeenCalled();
expect(showNotification).toHaveBeenCalledWith('error');
});
});
This gives me below error-
Expected mock function to have been called, but it was not called.
At line- expect(setuserData).toHaveBeenCalled();
Can someone help me understand what i am doing wrong? I guess i am doing some mistake in calling the setuserData. Any help is much appreciated.

How can I test the async actions which using 'superagent' in my react project with 'Enzyme' and 'Jest'?

I'm new to the test part of a project.
I got a problem in my personal project. I use 'superagent' to get the information from Api and now I want to write test for it. But I cannot use 'fetch-mock' package which used in the Enzyme example.
Here is my action file.
// getRecommendedProductsActions.js
import request from 'superagent';
export const getRecommendedProducts = () => (dispatch) => {
dispatch(fetchProducts());
return request
.get(URL_PRODUCT_BASE)
.set('Content-Type', 'application/json')
.then(res => dispatch(receiveProducts(res.body)))
.catch(err => dispatch(receiveFailure(err)));
};
Here is my test file.
// test/getRecommendedProducts.test.js
import configureMockStore from 'redux-mock-store';
import fetchMock from 'fetch-mock';
import thunk from 'redux-thunk';
import { getRecommendedProducts } from '../../src/actions/products';
describe('async actions', () => {
afterEach(() => {
fetchMock.reset();
fetchMock.restore();
});
it('creates RECEIVE_PRODUCTS when fetching products has been done', () => {
fetchMock
.get('/products', {
body: httpBody,
headers: { 'content-type': 'application/json' },
});
const expectedActions = successResponse;
const store = mockStore();
return store.dispatch(getRecommendedProducts())
.then(() => expect(store.getActions()).toEqual(expectedActions));
});
And I find that 'superagent' is not fetch based and 'fetch-mock' doesn't work.
I also find a __mocks__/superagent.js file.
// mock for superagent - __mocks__/superagent.js
let mockDelay;
let mockError;
let mockResponse = {
status() {
return 200;
},
ok() {
return true;
},
body: {
walla: true,
},
get: jest.fn(),
toError: jest.fn(),
};
const Request = {
post() {
return this;
},
get() {
return this;
},
send() {
return this;
},
query() {
return this;
},
field() {
return this;
},
set() {
return this;
},
accept() {
return this;
},
timeout() {
return this;
},
end: jest.fn().mockImplementation(function (callback) {
if (mockDelay) {
this.delayTimer = setTimeout(callback, 0, mockError, mockResponse);
return;
}
callback(mockError, mockResponse);
}),
// expose helper methods for tests to set
__setMockDelay(boolValue) {
mockDelay = boolValue;
},
__setMockResponse(mockRes) {
mockResponse = mockRes;
},
__setMockError(mockErr) {
mockError = mockErr;
},
};
module.exports = Request;
Thanks for all help from you guys.

How do I mock a promise in reactjs?

I want to write a test which mocks a promise in reactjs
I just need a mocked implementation of getHeaders() to return a string
export const loadAllProjects = () => {
return (dispatch) => {
getHeaders()
.then(headers => {
...do stuff
})
}
}
to clarify my original function was...
export const loadAllProjects = () => {
return (dispatch) => {
...do stuff
}
}
...and my test was...
it('should create SET_ALL_PROJECTS action when fetching projects', () => {
fetchMock
.getOnce('http://test.projects.api/api/projects',
{
body: [{name: "x"}],
headers: { 'content-type': 'application/json' }
}).spy()
const expectedActions = [
{ type: "SET_ALL_PROJECTS", json: [{name:"x"}] },
]
checkAsyncActionsWereDispatched(expectedActions, actions.loadAllProjects)
});
I want the test to work with the mocked header
const getHeaders = () => {
return new Promise((resolve, reject) => {
resolve("some string");
});
};
a = await getHeaders(); //some string
Use Promise.resolve
return Promise.resolve("your headers here");
You can use jest to mock a promise for testing
Example for the eventual completion:
const mockPostSpy = jest
.spyOn(axios, 'post')
.mockImplementation(() => {
return new Promise((resolve) => {
return resolve({
data: {},
});
});
});
Example for the operation failed:
const mockPostSpy = jest
.spyOn(axios, 'post')
.mockImplementation(() => {
return new Promise((resolve) => {
return reject({});
});
});
Good luck to you ^^

Resources