I am writing test cases for code coverage using typescript. I am using Jasmine spyOn, but it is not covered. But some of the methods are covered and I am not getting any error. I need your guidance to resolve this. I provide below the actual code.
import {IncomingMessage} from "http";
import * as https from "https";
import * as logger from "winston";
export class ApiUtil {
public static async authenticate(params: object): Promise<string> {
let response: Promise<string> = null;
response = new Promise((resolve) => {
try {
const req: any = https.request(params, (res) => {
ApiUtil.getAuthResponse(res).then((resstr) => {
resolve(resstr);
})
.catch((error) => {
logger.info("Internal unexpected authentication error: ", error);
if (error === "NOT_FOUND") {
resolve("NOT_FOUND");
} else {
resolve("Error");
}
});
});
req.on("error", (error: any) => {
logger.info("Internal unexpected authentication error for unknown host: ", error);
resolve("Error");
});
req.end();
} catch (error) {
logger.info("Unexpected Authentication Error: ", error);
logger.info("To DO");
}
});
return response;
}
public static getAuthParams(host: string, userName: string, pwc: string): object {
const base64Credential = ApiUtil.getBase64EncodeCredential(userName, pwc);
logger.info("Base64 Credential successfully received");
const params: object = {
agent: false,
headers: {
Authorization: base64Credential,
accepts: "application/json",
},
hostname: host,
method: "POST",
path: "/LOGIN_REST_URI",
rejectUnauthorized: false,
};
return params;
}
public static async getAuthResponse(res: IncomingMessage): Promise<string> {
return new Promise((resolve, reject) => {
ApiUtil.getRestAPIResponseText(res).then((resstr) => {
resolve(resstr.value);
})
.catch((e) => {
logger.info("Unexpected error while getting authentication response: ", e);
reject(e);
});
});
}
public static async getRestAPIResponseText(res: IncomingMessage): Promise<any> {
return new Promise((resolve, reject) => {
if (res && res.statusCode === 200) {
res.on("data", (dataChunk: string) => {
logger.info("Actual API call response");
const body = JSON.parse(dataChunk);
logger.info("Actual Body received");
resolve(body);
});
} else if (res && res.statusCode === 404) {
reject(res.statusMessage);
} else {
reject(null);
}
});
}
public static getBase64EncodeCredential(userName: string, pwc: string): string {
let b64Encvalue: string = null;
b64Encvalue = "Basic " + new Buffer(userName + ":" + pwc).toString("base64");
return b64Encvalue;
}
public static getApiParams(vmwareSessionId: string, host: string, restApiURI: string): object {
logger.info("vCenter Session Id received");
const options: object = {
headers: {
"vmware-api-session-id": vmwareSessionId,
},
hostname: host,
method: "GET",
path: restApiURI,
rejectUnauthorized: false,
requestCert: true,
};
return options;
}
public static async getApiResponse(vmwareSessionId: string, host: string, restAPIURI: string): Promise<any> {
let doesExist: Promise<any> = null;
const params: object = ApiUtil.getApiParams(vmwareSessionId, host, restAPIURI);
doesExist = new Promise((resolve, reject) => {
try {
const req: any = https.request(params, (res) => {
ApiUtil.getRestAPIResponseText(res).then((resstr) => {
resolve(resstr);
})
.catch((e) => {
logger.info("Inner Unexpected error while calling getApiResponse(): ", e);
reject(null);
});
});
req.on("error", (error: any) => {
logger.info("Internal unexpected authentication error for unknown host: ", error);
resolve(null);
});
req.end();
} catch (error) {
logger.info("Outer Unexpected error while calling getApiResponse(): ", error);
reject(error);
}
});
return doesExist;
}
public static async getVersionApiResponse(vmwareSessionId: string, host: string, restAPIURI: string):
Promise<string> {
let versionDetails: Promise<string> = null;
const params: object = ApiUtil.getApiParams(vmwareSessionId, host, restAPIURI);
versionDetails = new Promise((resolve, reject) => {
try {
const req: any = https.request(params, (res) => {
ApiUtil.getRestAPIResponseText(res).then((resstr) => {
resolve(resstr.value.version);
})
.catch((e) => {
logger.info("Internal Unexpected Error while calling getVersionApiResponse(): ", e);
resolve(null);
});
});
req.on("error", (error: any) => {
logger.info("Internal unexpected authentication error for unknown host: ", error);
resolve(null);
});
req.end();
} catch (error) {
logger.info("Unexpected Error while calling getVersionApiResponse(): ", error);
reject(error);
}
});
return versionDetails;
}
public static async getVersionNBuildApiResponse(vmwareSessionId: string, host: string, restAPIURI: string):
Promise<any> {
const versionNBuild: any = {version: null, build: null};
let versionInfo: Promise<any> = null;
const params: object = ApiUtil.getApiParams(vmwareSessionId, host, restAPIURI);
versionInfo = new Promise((resolve, reject) => {
try {
const req: any = https.request(params, (res) => {
ApiUtil.getRestAPIResponseText(res).then((resstr) => {
versionNBuild.version = resstr.value.version;
versionNBuild.build = resstr.value.build;
resolve(versionNBuild);
})
.catch((e) => {
logger.info("Internal Unexpected Error while calling getVersionApiResponse(): ", e);
versionNBuild.version = null;
versionNBuild.build = null;
resolve(versionNBuild);
});
});
req.on("error", (error: any) => {
logger.info("Internal unexpected authentication error for unknown host: ", error);
versionNBuild.version = null;
versionNBuild.build = null;
resolve(versionNBuild);
});
req.end();
} catch (error) {
logger.info("Unexpected Error while calling getVersionApiResponse(): ", error);
reject(error);
}
});
return versionInfo;
}
}
I am writing below the spec code.
import { ApiUtil } from "./api.util";
describe("API Utility", () => {
it("should not validate authentication", ((done) => {
// spyOn(https, "request").and.returnValue(Promise.resolve("someValue"));
spyOn(ApiUtil, "getBase64EncodeCredential").and.returnValue("someValue1");
spyOn(ApiUtil, "getAuthParams").and.returnValue(Promise.resolve("someValue"));
spyOn(ApiUtil, "getRestAPIResponseText").and.returnValue("clusterName");
spyOn(ApiUtil, "getAuthResponse").and.returnValue(Promise.resolve("someResponse"));
spyOn(ApiUtil, "getApiResponse").and.returnValue("[]");
const params: object = {};
ApiUtil.authenticate(params).then( (response) => {
expect(response).toBe("Error");
done();
});
}), 30000);
});
I also provide below the screenshot which is not covered.
You maybe should have a look here => Code Coverage issue when spyon is used
That said, I'm going to replicate the content here and anticipate a little bit to make it easier.
"Because the spy actually replaces the function call. You have to make two tests : the first will test if the function is actually called (what you did), and the second will test your onNext function" By – user4676340.
So, do ApiUtil.YouFunction() to let it have been called indeed.
Related
Error: function uses multiple asynchronous interfaces: callback and
promise
to use the callback interface: do not return a promise
to use the promise interface: remove the last argument to the function
I'm trying to write a cucumber test to one of my GET node API, and keep getting the above, looked at few GitHub and stack-overflow posts, and could not understand the issue, below are my test method details.
App.ts
async getSsoId(refId: any): Promise<string> {
let ssoId = '';
const secrets = await this.vaultService.getClientSecrets();
this.decrypt(refId, secrets.encryption_secret, secrets.encryption_Id).then((value: any) => {
ssoId = value;
});
return ssoId;
}
api.get('/status', async (req, res) => {
let id;
const statusCode = 200;
try {
id = await this.getId(String('123456'));
} catch (err: any) {
throw new ApiError('Error fetching id');
}
try {
const item = await dbService.getItem(id);
if (item) {
statusCode = 201;
} else {
statusCode = 202;
}
} catch (err: any) {
throw new ApiError(
'The API encountered an error while attempting to communicate with the DB service.'
);
}
res.status(statusCode).send(statusCode);
});
Step Definition:
Given('a valid customer', function () {});
When("I call the get-id api", { timeout: 2 * 5000 }, async function (val) {
util.callGetIdAPI().then((response) => {
this.setApiResponseStatus(response.status);
this.setResponseBody(JSON.stringify(response.body));
});
});
Then("the apiResponseStatus should be <apiResponseStatus>", function (status) {
assert.strictEqual(status, this.apiResponseStatus);
});
Then("the responseBody should be {string}", function (responseBody) {
assert.equal(responseBody, this.responseBody);
});
Util Function
callGetIdAPI = async () => {
const headers = {
'Content-Type': 'application/json;v=1',
Accept: 'application/json;v=1'
}
const client = await getClient('url');
const options = {
method: 'GET',
headers: headers,
version: 3
};
let response;
try {
response = await client.get('/status', options);
return {
status: response.statusCode,
body: response.body
};
} catch(error) {
return {
status: error.statusCode,
body: {
error: {
id: error.id,
message: error.message
}
}
}
}
};
I'm new to this and trying to understand how multiple Premisses and Callbacks works in parallel, any thoughts or inputs on what possibly cause the error, or am I missing anything ??
I want to call a function in usercontroller which is placed in another controller. I have used async function but still receiving
SyntaxError: await is only valid in async function
My code is as follow.
UserController.js
exports.adduser = async function (req, pic, type, res) {
await adduser(req, pic, type)
.then(data => { result = data; res(result) })
.catch(err => {
result.success = false;
if (err.status != undefined) {
result.status = err.status
result.message = err.message
} else {
result.status = 500
result.message = "Server Error " + String(err)
}
res(result)
});
};
async function adduser(req, pic, type) {
await schoolController.checkSchool(req.body)
.then(resp => {}).catch((err)=>{
..................
})
})
SchoolController.js
exports.checkSchool = async function (formdata) {
return new Promise(async (resolve, reject) => {
finder = { _id: formdata.school_id, is_deleted: false, is_blocked: false }
School.findOne(finder, function (err, res) {
if (res != null) {
reject({ status: false, message: "School" })
}
else {
resolve({ status: true, cityId: res.cityId })
}
})
});
}
I don't know what I could be doing wrong to get this error:
I've tried different promises, await, async combinations and nothing.
I've tried Promise.resolve()) and also .then(function().
Nothing stopped that error, what can I change to fix it?
#Controller()
export class AppController {
constructor(private httpSoap: HttpClient,
#InjectModel('product') private readonly productModel: Model<any>,
private xmlUtils: XmlUtils) { }
#EventPattern("next")
async handleMessagePrinted(data: Record<any, any>) {
let result = data;
this.createproduct(result);
this.insertproduct(result);
}
insertproduct(data: any) {
stringify(data);
this.productModel.insertMany(data);
}
async createproduct(job: any): Promise<any> {
return new Promise((async (resolve, reject) => {
// if (this.soapService.productCreate) {
const payload = job;
const xmlPayload = this.xmlUtils.parseJSONtoXML(payload);
this.insertproduct(stringify(xmlPayload)); //gravar na mongo
console.log("xmlPayload "+xmlPayload);
const headerRequest = {
'Content-Type': ContentTypeEnum.XML,
SOAPAction: SoapActionEnum.CREATE_SERVICE_product
};
const soap: ResponseInterface = await this.request("localhost:8080", xmlPayload, headerRequest, SoapType.product);
if (soap.error) {
reject(soap.error);
}
if (soap.status) {
if (soap.status.firewall.code === '000-000' || soap.status.firewall.code === '000-001') {
resolve(`product ${soap.body.Number} created successfully`);
} else if (soap.status.firewall.code === '000-998' && soap.status.fireWall.code === '623') {
reject({ error: soap.status.fireWall.description });
} else if (soap.status.firewall.code === '000-500' && soap.status.fireWall.code === 'BWENGINE-100029') {
const payloadSearch: productSearchDocument = new productSearchDocument();
payloadSearch.IsOperational = undefined;
payloadSearch.IsHistory = undefined;
payloadSearch.Qualification = `id='${job.data.id_ID}'`;
const search = await this.searchproduct(payloadSearch);
if (search.status) {
if (search.status.firewall.code === '000-000' || search.status.firewall.code === '000-001') {
resolve(`product ${soap.body.Number} created successfully`);
}
} else {
reject({ error: search.status.firewall.description, fireWallError: soap.status.fireWall.description });
}
} else {
reject({ error: soap.status.firewall.description, fireWallError: soap.status.fireWall.description });
}
}
}));
}
public async searchproduct(data: any): Promise<any> {
return new Promise((async (resolve, reject) => {
// if (this.soapService.productSearch) {
const payload = data;
const xmlPayload = this.xmlUtils.parseJSONtoXML(payload);
const headerRequest = {
'Content-Type': ContentTypeEnum.XML,
SOAPAction: SoapActionEnum.SEARCH_SERVICE_product
};
const soap: ResponseInterface = await this.request("localhost:8080", xmlPayload, headerRequest, SoapType.product);
if (soap.error) {
reject(soap.error);
}
if (soap.status) {
if (soap.status.firewall.code === '000-000' || soap.status.firewall.code === '000-001') {
resolve(soap);
} else {
reject({ error: soap.status.fireWall.description });
}
} else {
reject({ error: soap });
}
}));
}
public request(uri: string, data: any, headers: IHeaders, type: SoapType): Promise<any> {
return new Promise(((resolve) => {
this.httpSoap.request(uri, data, (async (err, res) => {
if (err) {
resolve({ error: err });
} else {
try {
console.log("fireWall response: "+data);
const bodyJson = await this.xmlUtils.formatXmlToJson(res.body);
const status: StatusInterface = await this.xmlUtils.formatStatusXML(bodyJson);
let body;
if (type === SoapType.product) {
body = await this.xmlUtils.formatproductServiceBodyXml(bodyJson);
this.insertproduct(stringify(bodyJson)); //gravar na mongo
} else if (type === SoapType.UNAVAILABILITY) {
body = await this.xmlUtils.formatImpactServiceBodyToXML(bodyJson);
} else if (type === SoapType.TASK) {
body = await this.xmlUtils.formatTaskServiceBodyXML(bodyJson);
} else {
body = '';
}
const response: ResponseInterface = {
status,
body,
};
resolve(response);
} catch (e) {
resolve(e);
}
}
}), headers);
}));
}
public simpleRequest(connection, payload): Promise<any> {
return new Promise<any>((resolve, reject) => {
const headers = {
};
this.httpSoap.request("localhost:8080", payload, (async (err, res) => {
if (err) {
resolve({ error: err });
} else {
try {
if (res.statusCode === 500) {
// const bodyJson = await this.xmlUtils.formatXmlToJson(res.body);
resolve(res.body);
} else {
const bodyJson = await this.xmlUtils.formatXmlToJson(res.body);
resolve(bodyJson);
}
} catch (e) {
reject(e);
}
}
}), headers);
});
}
}
My goal is to be able to save to mongo and also be able to make the http call to the SOAP api
This warning is shown when you don't add a rejection handler to a Promise, and it's rejected. It can be rejected when an error is occurred inside a promise, or reject() is called.
reject called:
const aa = new Promise((resolve, reject) => {
reject(new Error('whoops'));
});
aa.then(v => {
console.log(v);
});
// Running this script gives unhandled rejection warning
an error is occurred:
const aa = new Promise((resolve, reject) => {
const a = {};
// "cannot read property 'unexistingProperty' of undefined" error is thrown here
const b = a.b.unexistingProperty;
// alternatively, when an is thrown with throw
// throw new Error('oops')
});
aa.then(v => {
console.log(v);
});
// Running this script also gives unhandled rejection warning
You can add a rejection handler via then (the second argument to then() is rejection handler) or catch. For async/await you can add a try/catch block to catch error.
In node.js you can also add rejection handler to all unhandled rejected promises with process.on('unhandledRejection') like this:
process.on('unhandledRejection', error => {
console.log(error);
});
You can also see where the error is thrown with unhandledRejection event handler shown above, or you can run node.js with --trace-warnings like this.
node --trace-warnings index.js
References:
https://thecodebarbarian.com/unhandled-promise-rejections-in-node.js.html
https://nodejs.org/dist/latest-v14.x/docs/api/process.html
I have found out that my and my colleagues lambda doesn't return data we anticipate.
After what I have already found, we used deprecated invokeAsync which returnes only statusCode.
I have upgraded aws-sdk to the newest version and change the invocation code to use invoke with
InvocationType: 'RequestResponse'
as that should give us the returned value.
Lambdas code itself looks good, its an async function without arguments.
Im not using the callback here (3rd argument of handler), as we are doing some async stuff and it would require a small refactor to not use async/await, also i have read that just returning value is ok as well.
Earlier lambda was returning array, but after some investigation and googling I have changed it to
return {
statusCode: 200,
body: JSON.stringify(result)
}
where result is the mentioned array, as this was recurring pattern in search results.
Overall result is in our service where we do the invocation, we get timeout, lambda logs that it is returning value, but then retries itself again and again.
Dumping code
invocation in our service:
const lambda = new AWS.Lambda({ httpOptions: { timeout: 600000 } })
const results = await new Promise((resolve, reject) => {
lambda.invoke(
{
FunctionName: `lambda-name`,
InvocationType: 'RequestResponse',
Payload: '""'
},
(err, data) => {
if (err) {
reject(err)
} else {
resolve(data)
}
}
)
})
lambda handler
import { parallelLimit } from 'async'
const PARALLEL_FETCHERS_NUMBER = 2
export async function runTasksInParallel (
tasks,
limit,
) {
return new Promise(
(
resolve,
reject,
) => {
parallelLimit(tasks, limit, (error, results) => {
if (error === null) {
resolve(results)
} else {
reject(error)
}
})
},
)
}
async function connectToDB(logger) {
const MONGO_URL = process.env.MONGO_URL || 'mongodb://localhost:27017/'
let db
logger.debug('Connecting to mongo')
try {
db = await MongoClient.connect(
MONGO_URL,
{
sslValidate: false,
}
)
} catch (error) {
logger.error('Could not connect to Mongo', { error })
throw error
}
logger.debug('Connected')
return db
}
async function fetchAndStore(
list,
sources,
logger
) {
const results = []
const tasks = sources.map((source) => async (callback) => {
const { fetchAdapter, storageAdapter } = source
try {
const { entries, timestamp } = await fetchAdapter.fetchLatest(list)
await storageAdapter.storeMany(timestamp, entries)
results.push(['fetch.success', 1, [ `fetcher:${fetchAdapter.name}` ] ])
} catch (error) {
const errorMessage = `Failed to fetch and store from adapter ${fetchAdapter.name}`
const { message, name, stack } = error
logger.error(errorMessage, { error: { message, name, stack } })
results.push(['fetch.error', 1, [ `fetcher:${fetchAdapter.name}` ] ])
}
callback && callback(null)
})
await runTasksInParallel(tasks, PARALLEL_FETCHERS_NUMBER)
return results
}
export async function handle() {
const logger = createLambdaLogger() // just a wrapper for console.log to match interface in service
logger.debug('Starting fetching data')
const db: Db = await connectToDB(logger)
const primaryCollection = db.collection(PRIMARY_COLLECTION)
const itemsColletion = db.collection(ITEMS_COLLECTION)
const secondaryCollection = db.collection(SECONDARY_PRICING_COLLECTION)
const primaryStorageAdapter = new StorageAdapter(
Promise.resolve(primaryCollection),
logger
)
const itemsStorageAdapter = new ItemsStorageAdapter(
Promise.resolve(itemsColletion),
logger
)
const secondaryStorageAdapter = new StorageAdapter(
Promise.resolve(secondaryCollection),
logger
)
const primaryFetchAdapter = new PrimaryFetchAdapter(getFetcherCredentials('PRIMARY'), logger)
const secondaryFetchAdapter = new SecondaryFetchAdapter(getFetcherCredentials('SECONDARY'), logger)
const sources = [
{ fetchAdapter: primaryFetchAdapter, storageAdapter: primaryStorageAdapter },
{ fetchAdapter: secondaryFetchAdapter, storageAdapter: secondaryStorageAdapter },
]
try {
const list = await itemsStorageAdapter.getItems()
logger.debug(`Total items to fetch ${list.length}`)
const result = await fetchAndStore(list, sources, logger)
logger.debug('Returning: ', { result })
return {
statusCode: 200,
body: JSON.stringify(result)
}
} catch (error) {
const errorMessage = 'failed to do task'
const { message, name, stack } = error
logger.error(errorMessage, { error: { message, name, stack } })
return {
statusCode: 500,
body: JSON.stringify(new Error(errorMessage))
}
} finally {
await db.close()
}
}
Edit:
I have changed the way i'm invoking the lambda to this below. Basically I tried to listen for every possible event that can say me something. Result is that i get a error event, with response message being Converting circular structure to JSON. Thing is I don't really know about which structure this is, as the value I'm returning is a two elements array of 3 elements (strings and number) arrays.
const lambda = new AWS.Lambda({
httpOptions: { timeout: 660000 },
maxRetries: 0
})
const request = lambda.invoke(
{
FunctionName: `${config.get('env')}-credit-rubric-pricing-fetching-lambda`,
InvocationType: 'RequestResponse',
Payload: '""'
},
(err, data) => {
if (err) {
reject(err)
} else {
resolve(data)
}
}
)
const results = await request
.on('send', () => {
logger.debug('Request sent to lambda')
})
.on('retry', response => {
logger.debug('Retrying.', { response })
})
.on('extractError', response => {
logger.debug('ExtractError', { response })
})
.on('extractData', response => {
logger.debug('ExtractData', { response })
})
.on('error', response => {
logger.debug('error', { response })
})
.on('succes', response => {
logger.debug('success', { response })
})
.on('complete', response => {
logger.debug('complete', { response })
})
.on('httpHeaders', (statusCode, headers, response, statusMessage) => {
logger.debug('httpHeaders', { statusCode, headers, response, statusMessage })
})
.on('httpData', (chunk, response) => {
logger.debug('httpData', { response, chunk })
})
.on('httpError', (error, response) => {
logger.debug('httpError', { response, error })
})
.on('httpDone', response => {
logger.debug('httpDone', { response })
})
.promise()
I'm getting the following error:
TypeError: Converting circular structure to JSON
at JSON.stringify (<anonymous>)
at stringify (/usr/local/lib/node_modules/firebase-tools/node_modules/express/lib/response.js:1123:12)
at ServerResponse.json (/usr/local/lib/node_modules/firebase-tools/node_modules/express/lib/response.js:260:14)
at cors (/Users/landing-page-backend/functions/zohoCrmHook.js:45:43)
at process._tickCallback (internal/process/next_tick.js:68:7)
for the HTTP response in my createLead function, despite the fact that the function is executed properly and does what it's supposed to do (which is to create an entry in my CRM).
I've pointed out in the following code where the error occurs:
const axios = require('axios');
const functions = require('firebase-functions');
const cors = require('cors')({ origin: true })
const clientId = functions.config().zoho.client_id;
const clientSecret = functions.config().zoho.client_secret;
const refreshToken = functions.config().zoho.refresh_token;
const baseURL = 'https://accounts.zoho.com';
module.exports = (req, res) => {
cors(req, res, async () => {
const newLead = {
'data': [
{
'Email': String(req.body.email),
'Last_Name': String(req.body.lastName),
'First_Name': String(req.body.firstName),
}
],
'trigger': [
'approval',
'workflow',
'blueprint'
]
};
const { data } = await getAccessToken();
const accessToken = data.access_token;
const leads = await getLeads(accessToken);
const result = checkLeads(leads.data.data, newLead.data[0].Email);
if (result.length < 1) {
try {
return res.json(await createLead(accessToken, newLead)); // this is where the error occurs
} catch (e) {
console.log(e);
}
} else {
return res.json({ message: 'Lead already in CRM' })
}
})
}
function getAccessToken () {
const url = `https://accounts.zoho.com/oauth/v2/token?refresh_token=${refreshToken}&client_id=${clientId}&client_secret=${clientSecret}&grant_type=refresh_token`;
return new Promise((resolve, reject) => {
axios.post(url)
.then((response) => {
return resolve(response);
})
.catch(e => console.log("getAccessToken error", e))
});
}
function getLeads(token) {
const url = 'https://www.zohoapis.com/crm/v2/Leads';
return new Promise((resolve, reject) => {
axios.get(url, {
headers: {
'Authorization': `Zoho-oauthtoken ${token}`
}
})
.then((response) => {
return resolve(response);
})
.catch(e => console.log("getLeads error", e))
})
}
function createLead(token, lead) {
const url = 'https://www.zohoapis.com/crm/v2/Leads';
return new Promise((resolve, reject) => {
const data = JSON.stringify(lead);
axios.post(url, data, {
headers: {
'Authorization': `Zoho-oauthtoken ${token}`
}
})
.then((response) => {
console.log("response in createLead", response)
return resolve(response);
})
.catch(e => reject(e))
})
}
function checkLeads(leads, currentLead) {
return leads.filter(lead => lead.Email === currentLead)
}
Console.logging all the parameters indicate that the they are not the issue. The configuration of the Zoho API is, also, not the issue considering the fact that the entries are being properly made into the CRM. My assumption is that it would have to do with the HTTP response in the JSON format.
You're trying to convert a promise to JSON, not going to work. Your createLead function returns a promise, not a JSON. The promise is the 'circular object'.