Im learning using Jest and i faced this function,
but not sure how to start testing, it has inside an http.request({}, (res) => {})
and not sure how can i mock this http.request inside the current function:
also the resolve and reject from the current promise,
in advance Thank You!
const options = {
hostname: 'myHostName'
port: 'myPort',
path: 'myPath',
method: 'GET'
};
function myRequest(options) {
return new Promise((resolve, reject) => {
const req = http.request(options, (res) => {
if (res.statusCode === 200) {
let responseData = '';
res.on('data', (data) => {
responseData += data;
});
res.on('end', () => {
const response = JSON.parse(responseData);
resolve([response, true]);
});
} else {
reject(`res.message`);
}
});
req.on('error', (error) => {
reject(error);
});
req.end();
});
}
Related
I am currently learning how to connect my Amazon Lambda function (in js) to an API. I found the following code which works but I am new to javascript and APIs in general and am not sure what it is doing. Could someone explain to me what this function does and how it works? Thanks!
function httpGet() {
return new Promise(((resolve, reject) => {
var options = {
host: 'api.icndb.com',
port: 443,
path: '/jokes/random',
method: 'GET',
};
const request = https.request(options, (response) => {
response.setEncoding('utf8');
let returnData = '';
response.on('data', (chunk) => {
returnData += chunk;
});
response.on('end', () => {
resolve(JSON.parse(returnData));
});
response.on('error', (error) => {
reject(error);
});
});
request.end();
}));
}
Here the response object is a node.js stream, a 'push' stream in particular. (This article does a good job of explaining push/pull streams).
const request = https.request(options, (response) => {
// Your request has been successfully made and you are
// handed a response object which is a stream, which will emit
// a 'data' event when some data is available.
response.setEncoding('utf8');
let returnData = '';
// A chunk of data has been pushed by the stream,
// append it to the final response
response.on('data', (chunk) => {
returnData += chunk;
});
// All the data has been pushed by the stream.
// 'returnData' has all the response data. Resolve the
// promise with the data.
response.on('end', () => {
resolve(JSON.parse(returnData));
});
// Stream has thrown an error.
// Reject the promise
response.on('error', (error) => {
reject(error);
});
});
request.end();
I found a better solution. Create a function to getRemoteData and/or postRemoteData.
getRemoteData (url) {
return new Promise((resolve, reject) => {
axios
.get(url)
.then(res => {
console.log(res.data);
resolve(res.data);
})
.catch(error => {
console.error(error);
});
})
},
postRemoteData (url, body) {
return new Promise((resolve, reject) => {
axios
.post(url, body)
.then(res => {
console.log(res.data);
resolve(res.data);
})
.catch(error => {
console.error(error);
});
})
},
Then use these functions in your IntentsHandlers.
//Get
const url = "https://anydir.com"
let speakOutput = "No data";
await logic.getRemoteData(url)
.then((data) => {
speakOutput = data.results.toString();
})
//Post
const url = "https://anydir.com"
let speakOutput = "No data";
await logic.getRemoteData(url, {param1:valueParam1,param2:valueParam2})
.then((data) => {
speakOutput = data.results.toString();
})
Example.
const NumberCharactersIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'NumberCharactersIntent';
},
async handle(handlerInput) {
const url = "https://rickandmortyapi.com/api/character"
let speakOutput = "No data";
await logic.getRemoteData(url)
.then((data) => {
speakOutput = `There are ${data.results.length.toString()} in the Rick and Morty serie`
})
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
I want to mock the result of a function within a node module so that i can run assertions.
Considering the following node module:
const doPostRequest = require('./doPostRequest.js').doPostRequest;
const normalizeSucessResult = require('./normalizer.js').normalizeSucessResult;
const normalizeErrorResult = require('./normalizer.js').normalizeErrorResult;
exports.doPost = (params, postData) => {
return doPostRequest(params, postData).then((res) => {
const normalizedSuccessResult = normalizeSucessResult(res);
return normalizedSuccessResult;
}).catch((err) => {
const normalizedErrorResult = normalizeErrorResult(err);
return normalizedErrorResult;
})
}
The function doPostRequest returns a promise. How can i fake the return value of this promise so that i can assert if normalizeSucessResult has been called?
So for i have tried:
const normalizeSucessResult = require('./normalizer.js');
const doPostRequest = require('./doPostRequests.js');
const doPost = require('./doPost.js');
it('runs a happy flow scenario', async () => {
let normalizeSucessResultStub = sinon.stub(normalizeSucessResult, 'normalizeSucessResult');
let postData = { body: 'Lorum ipsum' };
let params = { host: 'someUrl', port: 433, method: 'POST', path: '/' };
sinon.stub(doPostRequest, 'doPostRequest').resolves("some response data"); //Fake response from doPostRequest
return doPost.doPost(params, postData).then((res) => { //res should be equal to some response data
expect(normalizeSucessResultStub).to.have.been.calledOnce;
expect(normalizeSucessResultStub).to.have.been.with("some response data");
});
});
The doPostRequest module looks like this:
const https = require('https')
module.exports.doPostRequest = function (params, postData) {
return new Promise((resolve, reject) => {
const req = https.request(params, (res) => {
let body = []
res.on('data', (chunk) => {
body.push(chunk)
})
res.on('end', () => {
try {
body = JSON.parse(Buffer.concat(body).toString())
} catch (e) {
reject(e)
}
resolve(body)
})
})
req.on('error', (err) => {
reject(err)
})
if (postData) {
req.write(JSON.stringify(postData))
}
req.end()
})
}
You can use Promise.resolve to return a promise with any given value.
Promise.resolve(“hello world”);
For stub your func you need to do like this
sinon.stub({doPostRequest}, 'doPostRequest').resolves("some response data")
Okay, i figured it out. The function doPostRequest was loaded using require, on the top of the file using const doPostRequest = require('./doPostRequest.js').doPostRequest;
In order to mock the data that comes back from a function that is loaded using require i had to use a node module called mock-require. There are more modules that can take care of this (proxyquire is a populair one) but i picked mock-require (i did not have a specific reason for choosing mock-require).
For anyone else that is stuck with a similar problem, try mock-require to mock the respose from files that are loaded using require.
In my code I try to assign a value to json variable to return it after (because I can't return it from the anon. function).
As my function is async, because it sends requests (maybe someone knows how to make it sync? I didn't plan to make it asynchronous), I've added await before the request (https.get).
I've been trying to get value from the Promise, but it's always undefined, even though I've awaited the async function.
Here's a code:
async function get_users() {
const https = require('https');
var token = '...';
var json = undefined;
await https.get('...', (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
json = JSON.parse(data)['response']['items'];
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
return json;
}
get_users().then(function(result) {
console.log(result);
});
Return a Promise and resolve it, when the end event is called, otherwise reject it in case of an error occurred:
async function get_users() {
const https = require('https');
const token = '...';
return new Promise((resolve, reject) => {
https.get('...', resp => {
let data = '';
resp.on('data', chunk => {
data += chunk;
});
resp.on('end', () => {
let json;
try {
json = JSON.parse(data)['response']['items'];
} catch (e) {
reject(e);
};
resolve(json);
});
}).on("error", err => reject(err));
});
}
get_users().then(result => console.log(result));
Please refer my below code.I had issues with getting responses from Promises too.But i finally got it to work.Here's the code:
var output;
var rp = require('request-promise-native');
var myJSONObject = {
"inputs": [{
"name": "<name>",
"value": < value >
}]
};
var orchName = 'TEST05';
postData = JSON.stringify(myJSONObject);
return networkCall(postData, orchName).then((response) => {
console.log('response is' + response)
}).catch((response) => {
console.log(`ERROR: ` + response);
});
function networkCall(postData, orchName) {
return new Promise((resolve, reject) => {
var options = {
method: 'post',
uri: '<URL>',
body: postData,
auth: {
'user': 'usr',
'pass': 'pwd'
},
json: true
};
return rp(options)
.then(body => {
var response = body;
resolve(response);
})
.catch(err => {
console.log('FAILED' + err);
reject(err);
});
});
}
This way your code can run in Synchronous Flow.If the return value is undefined,then,what might have probably happened is that the calling function would have finished executing even before the called function returns its response.But the above approach would work just fine.
I have a class, how I can create await for key value, that should be requested from http request in another method?
I don't know how to correct use await in this situation.
Here code, it returns only undefined:
class MyClass {
constructor(key = null) {
if (!!key)
this.key = key;
else
(async () => { this.key = await this.getKey(); })();
}
getKey(input) {
return new Promise((resolve, reject) => {
let options,
request,
data = '';
try {
options = {
host: '...',
port: '80',
path: '/',
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
request = http.request(options, (response) => {
response.setEncoding('utf8');
response.on('data', (chunk) => {
data += chunk.toString();
});
response.on('end', () => {
resolve(new RegExp('<div id="...".*>(.*)<\/div>', 'g').exec(data)[1]);
});
});
request.end();
} catch (error) {
reject(error);
}
});
}
}
a better usage would be to use await for the var you'll put in parameter :
let key = await getKey();
let myClass = new MyClass(key);
Perhaps I'm as confused about async await as you are, but it doesn't really seem necessary in this scenario.
class MyClass {
initKey() {
this.getKey().then(d => { this.key = d })
}
getKey(){
return new Promise((resolve, reject) => {
resolve("the promised value")
})
}
}
let t = new MyClass()
t.initKey()
I am learning Node. I have a console app that must make requests to web services in order. Specifically, I need to make three requests in order. In an attempt to make these requests, I'm using the built-in HTTPS module. I have one request successfully executing. But, I need to make three in succession. I'm not sure how to do this. Right now, I have:
console.log('Running Request #1...');
var options = {
host: 'example.com',
path: '/api/service',
port: 443,
method: 'GET',
headers: {
'api-key': '[Hidden]'
}
};
var req = https.request(options, (res) => {
res.on('data', (d) => {});
});
req.end();
req.on('error', (e) => {
console.error(e);
});
I'm not sure how to call my three requests in order. Yet, at the same time, gracefully handling an error. If I had promises, I would know how to chain them together and just use the catch handler. But, I'm not sure how to chain together requests since the HTTPS module uses the Arrow function syntax.
Any help is appreciated it.
Try this:
var https = require('https');
var urls = ['url1', 'url2', 'url3'];
var request = function(url) {
console.log(url);
return new Promise((resolve, reject) => {
https.get(url, (res) => {
res.on('end', () => {
resolve('what');
});
res.on('data', data =>{
});
}).on('error', e => {
reject(e);
});
});
};
var promise = request(urls.shift());
while(urls.length > 0) {
let url = urls.shift();
promise = promise.then(function() {
return request(url);
});
}
promise.catch(e => console.log);
consider use promise with reduce,something like this
var urls=['u1','u2','u3'];
var er=0
function getPromise(url) {
return new Promise(function (resolve,reject) {
setTimeout(function () {
console.log(url+ " is resolved in 2 sec")
er++
if(er==1)
{
reject(url)
}else{
resolve(url)
}
},2000)
})
}
urls.reduce(function (pre,cur) {
return pre.then(function () {
return getPromise(cur)
})
},new Promise(function (resolve,reject) {
resolve(null)
}))
.then(function (result) {
console.log("final result is "+result)
},function (e) {
console.log("something wrong happens : "+e)
})
Play with the code,I think it is want you want