Expectations Error while unit testing Got Client - javascript

I need your help with this issue that I am having while unit testing a Got client hook
where I do logging of HTTP requests. I am using Jest.
I am getting an expectations error that is seeing the argument to .toBeCalledWith as object whereas it is a string when I console log it. Maybe I am doing something wrong here. Please let me know.
got-client.js below
const http = require('http');
const https = require('https');
const got = require('got');
const _ = require('lodash');
const { name: packageName, version: packageVersion } = require('../../package.json');
const keepAliveOptions = { keepAlive: true, keepAliveMsecs: 20000 };
let clients = {};
const allowedHeaders = ['user-agent', 'x-forwarded-for', 'referer', 'content-length'];
const filterHeaders = headers => _.pick(headers, allowedHeaders);
const gotLoggingHooks = (name, logger) => ({
hooks: {
beforeRequest: [
options => {
const { url, method, headers } = options;
logger.debug({
message: `${name} request ${options.method} ${options.url}`,
http_request: {
method,
target: url,
direction: 'OUT',
headers: filterHeaders(headers)
},
request: _.pick(options, ['url', 'method', 'headers', 'body', 'json'])
});
}
],
beforeRetry: [
(options, error, retryCount) => {
const {
response: { statusCode, ip } = {},
request: { options: { method, headers = {} } = {}, requestUrl: url } = {},
timings: {
// eslint-disable-next-line camelcase
phases: { total: duration_ms } = {}
} = {}
} = error;
logger.warn({
message: `${name} will retry request, attempt ${retryCount}/${options.retry.limit} ${method} ${url} (${error.code} ${error.message})`,
err: error,
http_request: {
method,
target: url,
status: statusCode,
server_ip: ip,
duration_ms,
direction: 'OUT',
protocol: headers.via,
headers: filterHeaders(headers)
}
});
}
],
beforeError: [
error => {
const {
response: { statusCode, ip } = {},
request: { options: { method, headers } = {}, requestUrl: url } = {},
timings: {
// eslint-disable-next-line camelcase
phases: { total: duration_ms } = {}
} = {}
} = error;
if (!statusCode) {
logger.error({
message: `${name} request error ${method} ${url} (${error.code} ${error.message})`,
err: error,
http_request: {
method,
target: url,
status: statusCode,
server_ip: ip,
duration_ms,
direction: 'OUT',
protocol: headers.via,
headers: filterHeaders(headers)
}
});
}
// eslint-disable-next-line no-param-reassign
error.serviceName = name;
return error;
}
],
afterResponse: [
response => {
const {
statusCode,
body,
url,
ip,
headers = {},
request: { options: { method } = {} } = {},
timings: {
// eslint-disable-next-line camelcase
phases: { total: duration_ms } = {}
} = {},
retryCount
} = response;
logger.debug({
message: `${name} response ${method} ${url}`,
response: { body, retryCount, headers },
http_request: {
method,
target: url,
status: statusCode,
server_ip: ip,
duration_ms,
direction: 'OUT',
protocol: headers.via,
headers: filterHeaders(_.get(response, 'request.options.headers'))
}
});
return response;
}
]
}
});
const gotClient = ({ name, logger, keepAlive = true, gotOptions = {} }) => {
if (!clients[name]) {
clients[name] = got
.extend({
headers: {
'user-agent': `${packageName} ${packageVersion}`
},
...(keepAlive && {
agent: {
http: new http.Agent(keepAliveOptions),
https: new https.Agent(keepAliveOptions)
}
}),
responseType: 'json',
timeout: 5000
})
.extend(gotLoggingHooks(name, logger))
.extend(gotOptions);
}
return clients[name];
};
gotClient.clearAll = () => {
clients = {};
};
module.exports = gotClient;
got-client.spec.js below
const nock = require('nock');
const { name: packageName, version: packageVersion } = require('../../../package.json');
const gotClient = require('../../../src/lib/got-client');
const BASE_URL = 'https://subdomain.domain.com/';
const BASE_ENDPOINT = 'path';
const logger = {
error: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
log: jest.fn(),
warn: jest.fn(),
};
describe('got client', () => {
afterEach(gotClient.clearAll);
test('should log requests', async () => {
const client = gotClient({
name: 'test',
logger,
gotOptions: {
prefixUrl: BASE_URL,
},
});
nock(BASE_URL).get(`/${BASE_ENDPOINT}`).reply(200, { success: true });
await client.get(BASE_ENDPOINT);
// console.log('mock call 0', logger.debug.mock.calls[0][0]);
// TODO: match message
expect(logger.debug).toBeCalled();
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`response GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
nock(BASE_URL).get(`/${BASE_ENDPOINT}/error`).reply(500, { success: false });
try {
await client.get(`${BASE_ENDPOINT}/error`, { retry: 0 });
} catch (e) {}
expect(logger.error).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request error GET ${BASE_URL}${BASE_ENDPOINT}/error`),
})
);
});
});
Failing Test Error below
Error: expect(jest.fn()).toBeCalledWith(...expected)
Expected: ObjectContaining {"message": StringContaining "request error GET https://subdomain.domain.com/path/error"}
Number of calls: 0
at Object.<anonymous> (/Users/user/Documents/company/teams/team/project/test/unit/lib/got-clients.spec.js:62:26)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
I will really appreciate help with this. Thank you very much in advance.

Working got-client.spec.js
const nock = require('nock');
const { name: packageName, version: packageVersion } = require('../../../package.json');
const gotClient = require('../../../src/lib/got-client');
const BASE_URL = 'https://subdomain.domain.com/';
const BASE_ENDPOINT = 'path';
const logger = {
error: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
log: jest.fn(),
warn: jest.fn(),
};
const defaultClient = gotClient({
name: 'test',
logger,
gotOptions: {
prefixUrl: BASE_URL,
},
});
describe('got client', () => {
afterEach(gotClient.clearAll);
test('should log requests', async () => {
nock(BASE_URL).get(`/${BASE_ENDPOINT}`).reply(200, { success: true });
await defaultClient.get(BASE_ENDPOINT);
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
});
test('should log responses', async () => {
nock(BASE_URL).get(`/${BASE_ENDPOINT}`).reply(200, { success: true });
await defaultClient.get(BASE_ENDPOINT);
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`response GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
});
test('should log errors', async () => {
const endpoint = `${BASE_ENDPOINT}/error`;
nock(BASE_URL).get(`/${endpoint}`).replyWithError({
message: 'something awful happened',
code: 'ECONNRESET',
});
try {
await defaultClient.get(endpoint, { retry: 0 });
} catch (e) {}
expect(logger.error).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request error GET ${BASE_URL}${endpoint}`),
})
);
});
test('should log retries', async () => {
nock(BASE_URL)
.get(`/${BASE_ENDPOINT}`)
.replyWithError({
message: 'something awful happened',
code: 'ECONNRESET',
})
.get(`/${BASE_ENDPOINT}`)
.reply(500, { success: false })
.get(`/${BASE_ENDPOINT}`)
.reply(500, { success: false })
.get(`/${BASE_ENDPOINT}`)
.reply(200, { success: true });
await defaultClient.get(BASE_ENDPOINT, { retry: { limit: 3, calculateDelay: () => 1 } });
expect(logger.warn).toBeCalledTimes(3);
expect(logger.warn).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`will retry request`),
})
);
});
});

Related

How can I handle token change when both useQuery and useLazyQuery are used from Apollo/client

I hope you are doing well!
In our website, we are using graphQL and for that we are using apollo/client.
Our problem comes when it comes to the Access Token.
Here are my components:
import { useState } from "react";
import { useMutation, useQuery } from "#apollo/client";
import useAuth from "./useAuth";
import { useSnackbar } from "notistack";
import { LOGOUT_USER } from "graphql/user";
import useMutationAuth from "./useMutationAuth";
const useQueryAuth = (QUERY, objAccess = "", params = {}, statusFunctions = {}) => {
//holds custom error thrown by backend
const [customError, setCustomError] = useState("");
const { jwtToken, logout, updateToken } = useAuth();
// Snackbar hook
const { enqueueSnackbar } = useSnackbar();
//holds custom loading
const [customLoading, setCustomLoading] = useState(false);
//to not all the useQuery if data has already been fetched before
const [skip, setSkip] = useState(false);
const { mfunction: logsOutUser } = useMutationAuth(LOGOUT_USER, "Logout");
// Get data using GraphQL API
const { loading, error, data, refetch } = useQuery(QUERY, {
skip: skip,
fetchPolicy: "no-cache",
nextFetchPolicy: "no-cache",
context: {
headers: {
authorization: `${jwtToken ? "Bearer " + jwtToken : ""}`,
},
},
...params,
onCompleted: (data) => {
if (data[objAccess].errorCode === "UnauthErr") {
logsOutUser({ variables: { aToken: jwtToken } }, () => { logout() });
enqueueSnackbar(data[objAccess].errorMessage, {
variant: "error",
autoHideDuration: 5000,
anchorOrigin: {
vertical: "top",
horizontal: "right",
},
});
} else if (data[objAccess].errorCode === "NewToken") {
updateToken(data[objAccess].errorMessage.trim());
refetch({
context: {
headers: {
authorization: `${data[objAccess].errorMessage.trim() ? "Bearer " + data[objAccess].errorMessage.trim() : ""}`,
},
}
});
} else if (data[objAccess].errorCode !== null && data[objAccess].errorCode !== "") {
enqueueSnackbar(data[objAccess].errorMessage, {
variant: "error",
autoHideDuration: 5000,
anchorOrigin: {
vertical: "top",
horizontal: "right",
},
});
setCustomError(data[objAccess].errorMessage);
} else {
if (statusFunctions.onCompleted !== undefined) statusFunctions.onCompleted(data);
}
},
onError: ({ graphQLErrors, networkError }) => {
// if (graphQLErrors)
// graphQLErrors.forEach(({ message, locations, path }) =>
// console.log(
// `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
// )
// );
// if (networkError) console.log(`[Network error]: ${networkError}`);
enqueueSnackbar("System Error", {
variant: "error",
autoHideDuration: 5000,
anchorOrigin: {
vertical: "top",
horizontal: "right",
},
});
if (statusFunctions.onError !== undefined) statusFunctions.onError(data);
},
});
return { loading, error, data, customError, refetch, customLoading, setSkip };
};
export default useQueryAuth;
and
import { useState } from "react";
import { useLazyQuery } from "#apollo/client";
import { useSnackbar } from "notistack";
import useAuth from "./useAuth";
import { LOGOUT_USER } from "graphql/user";
import useMutationAuth from "./useMutationAuth";
const useLazyQueryAuth = (QUERY, objAccess, params, statusFunctions) => {
const [customError, setCustomError] = useState("");
// Snackbar hook
const { enqueueSnackbar } = useSnackbar();
const { jwtToken, logout, updateToken } = useAuth();
const { mfunction: logsOutUser } = useMutationAuth(LOGOUT_USER, "Logout")
//defines mutation function
const [call_function, { loading, error }] = useLazyQuery(QUERY, {
fetchPolicy: "no-cache",
nextFetchPolicy: "no-cache",
context: {
headers: {
authorization: `${jwtToken ? "Bearer " + jwtToken : ""}`,
},
},
...params,
});
const mfunction = (params, onCompletedFunc = undefined, onErrorFunc = undefined) => {
call_function({
...params,
onCompleted: (data) => {
if (data[objAccess].errorCode === "UnauthErr") {
logsOutUser({ variables: { aToken: jwtToken } }, () => { logout() });
enqueueSnackbar(data[objAccess].errorMessage, {
variant: "error",
autoHideDuration: 5000,
anchorOrigin: {
vertical: "top",
horizontal: "right",
},
});
} else if (data[objAccess].errorCode === "NewToken") {
updateToken(data[objAccess].errorMessage.trim());
mfunction({
...params, context: {
headers: {
authorization: `${data[objAccess].errorMessage.trim() ? "Bearer " + data[objAccess].errorMessage.trim() : ""}`,
},
}
}, onCompletedFunc, onErrorFunc);
} else if (data[objAccess].errorCode !== null && data[objAccess].errorCode !== "") {
enqueueSnackbar(data[objAccess].errorMessage, {
variant: "error",
autoHideDuration: 5000,
anchorOrigin: {
vertical: "top",
horizontal: "right",
},
});
setCustomError(data[objAccess].errorMessage);
} else if (onCompletedFunc !== undefined) onCompletedFunc(data);
},
onError: ({ graphQLErrors, networkError }) => {
// if (graphQLErrors)
// graphQLErrors.forEach(({ message, locations, path }) =>
// console.log(
// `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
// )
// );
// if (networkError) console.log(`[Network error]: ${networkError}`);
enqueueSnackbar("System Error", {
variant: "error",
});
if (onErrorFunc !== undefined) onErrorFunc(error);
},
});
};
const cfunction = (params, onCompletedFunc = undefined, onErrorFunc = undefined) => {
call_function({
...params,
onCompleted: (data) => {
if (data[objAccess].errorCode === "UnauthErr") {
logsOutUser({ variables: { aToken: jwtToken } }, () => { logout() });
enqueueSnackbar(data[objAccess].errorMessage, {
variant: "error",
autoHideDuration: 5000,
anchorOrigin: {
vertical: "top",
horizontal: "right",
},
});
} else if (data[objAccess].errorCode === "NewToken") {
updateToken(data[objAccess].errorMessage.trim());
cfunction({
...params, context: {
headers: {
authorization: `${data[objAccess].errorMessage.trim() ? "Bearer " + data[objAccess].errorMessage.trim() : ""}`,
},
}
}, onCompletedFunc, onErrorFunc);
} else if (onCompletedFunc !== undefined) onCompletedFunc(data);
},
onError: ({ graphQLErrors, networkError }) => {
// if (graphQLErrors)
// graphQLErrors.forEach(({ message, locations, path }) =>
// console.log(
// `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
// )
// );
// if (networkError) console.log(`[Network error]: ${networkError}`);
enqueueSnackbar("System Error", {
variant: "error",
autoHideDuration: 5000,
anchorOrigin: {
vertical: "top",
horizontal: "right",
},
});
if (onErrorFunc !== undefined) onErrorFunc(error);
},
});
};
return { mfunction, loading, error, call_function, customError, cfunction };
};
export default useLazyQueryAuth;
useLazyQueryAuth.defaultProps = {
QUERY: null,
objAccess: "",
params: {},
statusFunctions: {},
};
I created 2 custom hooks to handle useQuery and useLazyQuery calls because there are some functions that will be re-used in our code on every call.
The way our token handling is working is:
A call is made to the backend
2 The backend checks that the token is valid first
If not, we get an errorCode of "UnauthError"
If the token was expired, we get an errorCode of "NewToken" and have the token returned to us
We update the new Token and redo our call based on the new Token
My problem is, we have a page like this one
//get user types list
const {
loading: userTypesLoading,
error: userTypesError,
customError: userTypesCustomError,
} = useQueryAuth(
GET_USER_TYPES_LIST,
"getAllUserTypes",
{
variables: {
req: {
userID: storeUserGuid,
},
},
},
{
onCompleted: (data) => {
setUserTypesList(data.getAllUserTypes.userTypesList.userTypes);
},
}
);
//get user types list
const {
loading: userStatusLoading,
error: userStatusError,
customError: userStatusCustomError,
} = useQueryAuth(GET_USERS_STATUSES_LIST, "getAllUserStatuses", [,], {
onCompleted: (data) => {
setUserStatusList(data.getAllUserStatuses.userStatusList.userStatuses);
},
});
// Get users GraphQL API
const { loading, error, mfunction, customError } = useLazyQueryAuth(
GET_USERS_LIST,
"GetAllUsersList"
);
//Delete users GraphQL API
const {
mfunction: deleteUsers,
error: deleteError,
customError: deleteCustomError,
loading: deleteLoading,
} = useMutationAuth(DELETE_USERS_LIST, "deleteUsers");
//get Users function
useEffect(() => {
mfunction(
{
variables: {
usersListModel: {
keys: {
page: page + 1,
pageSize: rowsPerPage,
},
drivers: false,
userID: storeUserGuid,
keyword: search,
filters: filtersState,
orderColumn: orderColumn,
orderDirection: orderDirection,
},
},
},
(data) => {
setData(data);
}
);
}, [page, rowsPerPage, orderColumn, orderDirection, refetchData]);
we are having to add the call in a useEffect because we want to fetch data on a state change, but some state is changed after a delay (basically create a timer).
What is happening is:
Our useQueryAuth (which are useQuery) calls are made
We get that a new token is made, so we recall it with the new token
Our useEffect call is made and the useLazyQueryAuth (useLazyQuery) is made on the old token because it hasn't been updated yet when it comes to rendering
Backend has the new token
We get Unauthorized for the useLazyQuery call
How can we handle this? I can't use too many variables because it has been implemented in more than one page so I'd have to go over too many pages to change how they work.
Is there a way to handle this? How can I make my useLazyQueryAuth either use the new token or at least make it call the function again with the new token if it isn't the one returning with the NewToken error Code?
Thank you in advanced!

URQL WSS connection with GraphQL-WS says error 4500

import {
createClient,
defaultExchanges,dedupExchange, cacheExchange, fetchExchange,
subscriptionExchange,
gql
} from "#urql/core";
import { createClient as createWSClient } from "graphql-ws";
import { pipe, subscribe } from "wonka";
import { getToken, setToken } from "./helper";
const wsClient = createWSClient({
url: 'wss://**********/subscriptions',
reconnect: true,
});
const client = createClient({
url: "https://***********/",
fetchOptions: () => {
const token = getToken()
return token ? { headers: { authorization: `Bearer "${token}"` } } : {}
},
// the default:
exchanges: [
...defaultExchanges,
subscriptionExchange({
forwardSubscription(operation) {
return {
subscribe: (sink) => {
const dispose = wsClient.subscribe(operation, sink);
return {
unsubscribe: dispose,
};
},
};
},
}),
]
});
SUB_TO_MESSAGES = async () => {
console.log('sub')
const token = getToken();
console.log(String(token))
const { unsubscribe } = pipe(
await client.subscription(messageAdded,{ jwt: token }),
subscribe((result) => {
console.log(result)
})
)
};
I dont get the same issue with try and catch using GraphQL-WS but I still dont get any data from the server. The assignment is a vanillaJS project using GraphQL.I didndt post the url, jwt token,or the GET, POST, REgG as they work as intended. The rendering is done with a proxy. The error message is:
Connection Closed: 4500 Cannot read properties of undefined (reading 'Authorization')
Even playground doesnt work. Something wrong with the endpoint. It worked 2 weeks ago but admin says it still work yet I can find the problem. It used to work for me.
Here is the try and catch version:
import { createClient} from "graphql-ws";
import pStore from "./handler.js";
import { getToken } from "./helper";
const client = createClient({
url: "wss://******/subscriptions",
reconnect: true,
connectionParams:{
headers: {
"Authorization":`Bearer ${getToken()}`
}
},
})
async SUB_MESSAGE() {
try {
console.log('called Gql server')
const onNext = (res) => {
let obj = res.data.messageAdded
console.log(obj)
pStore[obj.id] = obj
pStore.render(obj)
};
let unsubscribe = () => {
/* complete the subscription */
};
new Promise((resolve, reject) => {
client.subscribe({
query: `subscription{messageAdded(jwt:"${getToken()}"){id text fromAgent createdAt updatedAt}}`,
},
{
next: (data)=> onNext(data),
error: reject,
complete: () => resolve(true),
})
})
}catch(error){
console.error('There has been a problem with your ws operation:', error);
}
}
Either way I think its a ad character, scope issue but I dont know where.

Jest custom axios interceptor

i am trying to use jest with nextJS to test API. I am using a custom interceptor for all http request to have authorization token on header. Here is my interceptor code
Api.ts
import axios from 'axios';
import config from '../config/index';
const Api = () => {
const defaultOptions = {
baseURL: config.APIENDPOINT,
method: 'get',
headers: {
'Content-Type': 'application/json',
},
};
// Create instance
let instance = axios.create(defaultOptions);
// Set the AUTH token for any request
instance.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
//#ts-ignore
config.headers.Authorization = token ? `${token}` : '';
return config;
});
instance.interceptors.response.use((res) => {
return res
});
return instance;
};
export default Api();
Here is the code to call the API
export const loadMerchants = async (id: any) => {
const data = await Api.get(config.APIENDPOINT + "/merchants/company/" + id)
console.log("data" ,data);
return (data)
}
And here is my test code
const axios = require('axios');
jest.mock('axios', () => {
return {
get: jest.fn(),
create: jest.fn(() => ({
interceptors: {
request: { use: jest.fn(() => Promise.resolve({ data: { foo: 'bar' } })) },
response: { use: jest.fn(() => Promise.resolve({ data: { foo: 'bar' } })) },
}
}))
}
})
it('Merchant API call', async () => {
axios.get.mockResolvedValue({
data: [
{
userId: 1,
id: 1,
title: 'My First Album'
},
{
userId: 1,
id: 2,
title: 'Album: The Sequel'
}
]
});
const merchants = await loadMerchants("1")
console.log(merchants) //always undefined
// expect(merchants).toEqual('some data');
});
on my API call if use axios.get instead of Api.get i get the correct results. I have looked into google and haven`t found any solutions.
Any help would be appreciated. Thank you.

Mock axios request using jest

I tried following:
jest.mock('axios', () => jest.fn(() => Promise.resolve({ data: testData })));
also tried adding __mocks__/axios.ts:
export default {
default: jest.fn(),
request: jest.fn(),
};
but it returns:
TypeError: Cannot read property 'request' of undefined
7 | const CLIENT_ROUTER_REQUIRED_HEADER = { 'Content-Type': 'application/json' };
8 |
> 9 | axiosRetry(axios, { retries: 3 });
| ^
10 |
11 | const responseData = axios({
12 | baseURL: baseUrl ? baseUrl : '',
AxiosService.ts
import axios, { AxiosResponse } from 'axios';
import axiosRetry from 'axios-retry';
export const axiosRequest = (data: object, baseUrl?: string): Object => {
const CLIENT_ROUTER_END_POINT = '/client-router';
const CLIENT_ROUTER_HTTP_METHOD = 'POST';
const CLIENT_ROUTER_REQUIRED_HEADER = { 'Content-Type': 'application/json' };
axiosRetry(axios, { retries: 3 });
const responseData = axios({
baseURL: baseUrl ? baseUrl : '',
url: CLIENT_ROUTER_END_POINT,
method: CLIENT_ROUTER_HTTP_METHOD,
headers: CLIENT_ROUTER_REQUIRED_HEADER,
data: data,
})
.then(function (response: AxiosResponse) {
return response.data;
})
.catch((e) => {
return JSON.stringify(e);
});
return responseData;
};
index.ts
import { axiosRequest } from './AxiosService';
export const retrieveDataFromServer = async (
httpMethod: string,
gatewayPath: string,
requestParameters: object,
baseUrl?: string
): Promise<Object> => {
const data = {
httpMethod: httpMethod,
gatewayPath: gatewayPath,
requestParameters: requestParameters,
};
const responseData = axiosRequest(data, baseUrl);
return responseData;
};
index.test.ts
import { retrieveDataFromServer } from '../src';
describe('Frontend Client Router React Component', () => {
test('Retrieve data from job-search endpoint', async () => {
// The purpose of this test is to show an example on how to use retrieveDataFromServer()
const data = {
query: 'strawberry',
//...other data
};
const testData = {
responseBody:
'["1", "2", "3"]',
responseCode: 200,
};
jest.mock('axios', () => jest.fn(() => Promise.resolve({ data: testData })));
expect(
await retrieveDataFromServer(
'GET',
'/search',
data,
'http://localhost:8881/'
)
).toMatchObject(testData);
});
});
I ended up adding:
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
const mock = new MockAdapter(axios);
test('Retrieve data from autocomplete endpoint', async () => {
const data: AutocompleteData = {
query: 'strawberry',
};
const testData = [
'strawberry',
];
mock.onPost().replyOnce(200, {
testData,
});
await expect(autocomplete(AutocompleteType.where, data)).resolves.toEqual({
testData: testData,
});
}
to my test code.

AWS Cognito adminCreateUser from Lambda, created with Amplify CLI

I created a Lambda function using Amplify CLI, when executing the Lambda function executes without errors but the Cognito User isn't created.
What am I missing here?
I have checked the CloudWatch Logs but not errors that I can pick up either.
I have been following this documentation: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#adminCreateUser-property
/* Amplify Params - DO NOT EDIT
AUTH_XXXXXXXXXXXXXXXXXXXX_USERPOOLID
ENV
REGION
Amplify Params - DO NOT EDIT */
const AWS = require('aws-sdk');
AWS.config.update({ region: process.env.AWS_REGION,accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY });
const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider({ apiVersion: '2016-04-18' });
//console.log(process.env);
exports.handler = async (event) => {
let retailerid = event.pathParameters.retailerid;
let params = {
UserPoolId: process.env.AUTH_XXXXXXXXXXXXXXXXXXXX_USERPOOLID, /* required */
Username: 'testtest', /* required */
ClientMetadata: {
},
DesiredDeliveryMediums: [
'EMAIL'
],
ForceAliasCreation: false,
MessageAction: 'SUPPRESS',
TemporaryPassword: 'mynuw000000000TTS',
UserAttributes: [
{
Name: 'custom:app_role', /* required */
Value: 'retail'
},
{
Name: 'email_verified', /* required */
Value: 'true'
},
{
Name: 'email', /* required */
Value: 'usersname#someemail.co.za'
},
{
Name: 'phone_number', /* required */
Value: '27833260000'
},
/* more items */
],
ValidationData: [
/* more items */
]
};
await cognitoidentityserviceprovider.adminCreateUser(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log('SUCCESS', data); // successful response
});
// TODO implement
const response = {
statusCode: 200,
// Uncomment below to enable CORS requests
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(retailerid),
};
return response;
};
Test event
{
"request": {
"userAttributes": {
"custom:name": "Ajay",
"email": "ajay#gmail.com",
"custom:role": "Admin"
}
},
"response": {}
}
Lambda Function
var AWS = require('aws-sdk');
var resp200ok = { statusCode: 200, headers: {'Content-Type': 'application/json'}, body: {} };
var cognitoidentityserviceprovider = new
AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18'});
exports.handler = function(event, context, callback){
const attributes = event.request.userAttributes; // read user attributes from event
console.log('User Role : ',attributes['custom:role'])
var params = {
UserPoolId:'*********',
Username: attributes.email,
//TemporaryPassword: 'Password!1',
DesiredDeliveryMediums: ["EMAIL"],
UserAttributes: [
{
Name: "email",
Value: attributes.email
},
{
Name: 'email_verified', /* required */
Value: 'true'
},
{
Name: 'custom:name', /* required */
Value: attributes['custom:name']
},
{
Name: 'custom:role', /* required */
Value: attributes['custom:role']
},
],
};
cognitoidentityserviceprovider.adminCreateUser(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log('SUCCESS', data); // successful response
});
};
I'm not sure that await is working. How about this.
var createUserPromise = cognitoidentityserviceprovider.adminCreateUser(params).promise();
createUserPromise.then(results => {
// TODO implement
const response = {
statusCode: 200,
// Uncomment below to enable CORS requests
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(retailerid),
};
return response;
})
.catch(err => {
console.log("Error: ", err);
return "err"
});
await cognitoidentityserviceprovider.adminCreateUser(params).promise()
.then((data) => {
console.log('SUCCESS', data);
})
.catch((error) => {
console.log('ERROR', error);
});
This will work

Categories

Resources