For example suppose I have the following
app.get('/', function(req, res) {
var ip;
if(req.headers['x-forwarded-for']){
ip = req.headers['x-forwarded-for'];
}
else {
ip = req.connection.remoteAddress;
}
});
I would like to unit test to see whether ip is being properly retrieved. One way is as follows
function getIp(req) {
var ip;
if(req.headers['x-forwarded-for']){
ip = req.headers['x-forwarded-for'];
}
else {
ip = req.connection.remoteAddress;
}
return ip;
}
app.get('/', function(req, res) {
var ip = getIp(req);
});
Now I have a function getIp that I can unit test. However I'm still stuck. How can I feed a simulated req object into getIp?
I would just write integration-tests for that. Node.js is fast enough for that. Especially when you use something like Mocha's watch-mode. You could use something like superagent or request to perform http requests.
There is also something like for example nock to mock out your http requests. Although I have never used it because integration-tests test the real thing and are fast enough for my tast.
I'd recommend using mocha to write your unit tests in which case you'll use 'request' as your http client. But the simplest way to get started is to use the following:
var http = require('http');
//Change to the ip:port of your server
var client = http.createClient(3000, 'localhost');
var request = client.request('GET', '/',
{'host': 'localhost'});
request.end();
request.on('response', function (response) {
console.log('STATUS: ' + response.statusCode);
console.log('HEADERS: ' + JSON.stringify(response.headers));
response.setEncoding('utf8');
response.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
Related
I am trying to run a few automated testing using the Postman tool. For regular scenarios, I understand how to write pre-test and test scripts. What I do not know (and trying to understand) is, how to write scripts for checking 409 error (let us call it duplicate resource check).
I want to run a create resource api like below, then run it again and ensure that the 2nd invocation really returns 409 error.
POST /myservice/books
Is there a way to run the same api twice and check the return value for 2nd invocation. If yes, how do I do that. One crude way of achieving this could be to create a dependency between two tests, where the first one creates a resource, and the second one uses the same payload once again to create the same resource. I am looking for a single test to do an end-to-end testing.
Postman doesn't really provide a standard way, but is still flexible. I realized that we have to write javascript code in the pre-request tab, to do our own http request (using sendRequest method) and store the resulting data into env vars for use by the main api call.
Here is a sample:
var phone = pm.variables.replaceIn("{{$randomPhoneNumber}}");
console.log("phone:", phone)
var baseURL = pm.variables.replaceIn("{{ROG_SERVER}}:{{ROG_PORT}}{{ROG_BASE_URL}}")
var usersURL = pm.variables.replaceIn("{{ROG_SERVICE}}/users")
var otpURL = `${baseURL}/${phone}/_otp_x`
// Payload for partner creation
const payload = {
"name": pm.variables.replaceIn("{{username}}"),
"phone":phone,
"password": pm.variables.replaceIn("{{$randomPassword}}"),
}
console.log("user payload:", payload)
function getOTP (a, callback) {
// Get an OTP
pm.sendRequest(otpURL, function(err, response) {
if (err) throw err
var jsonDaata = response.json()
pm.expect(jsonDaata).to.haveOwnProperty('otp')
pm.environment.set("otp", jsonDaata.otp)
pm.environment.set("phone", phone);
pm.environment.set("username", "{{$randomUserName}}")
if (callback) callback(jsonDaata.otp)
})
}
// Get an OTP
getOTP("a", otp => {
console.log("OTP received:", otp)
payload.partnerRef = pm.variables.replaceIn("{{$randomPassword}}")
payload.otp = otp
//create a partner user with the otp.
let reqOpts = {
url: usersURL,
method: 'POST',
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify(payload)
}
pm.sendRequest(reqOpts, (err, response) => {
console.log("response?", response)
pm.expect(response).to.have.property('code', 201)
})
// Get a new OTP for the main request to be executed.
getOTP()
})
I did it in my test block. Create your normal request as you would send it, then in your tests, validate the original works, and then you can send the second command and validate the response.
You can also use the pre and post scripting to do something similar, or have one test after the other in the file (they run sequentially) to do the same testing.
For instance, I sent an API call here to create records. As I need the Key_ to delete them, I can make a call to GET /foo at my API
pm.test("Response should be 200", function () {
pm.response.to.be.ok;
pm.response.to.have.status(200);
});
pm.test("Parse Key_ values and send DELETE from original request response", function () {
var jsonData = JSON.parse(responseBody);
jsonData.forEach(function (TimeEntryRecord) {
console.log(TimeEntryRecord.Key_);
const DeleteURL = pm.variables.get('APIHost') + '/bar/' + TimeEntryRecord.Key_;
pm.sendRequest({
url: DeleteURL,
method: 'DELETE',
header: { 'Content-Type': 'application/json' },
body: { TimeEntryRecord }
}, function (err, res) {
console.log("Sent Delete: " + DeleteURL );
});
});
});
Next JS. I am trying to set some cookies in my /api/tokencheck endpoint. Here is a very simplified version of the code:
import { serialize } from 'cookie';
export default (req, res) => {
/* I change this manually to simulate if a cookie is already set */
let cookieexists = 'no';
async function getToken() {
const response = await fetch('https://getthetokenurl');
const data = await response.json();
return data.token;
}
if (cookieexists === 'no') {
getToken().then((token) => {
res.setHeader('Set-Cookie', serialize('token', token, { path: '/' }));
});
return res.status(200).end();
} else {
return res.status(200).end();
}
};
I have tried a ton of variations as to where to put my return.res.status... code, and tried many different ways to return a success code, but depending on where I put the code I variously end up with either of the following errors:
"API resolved without sending a response for /api/checkguestytoken, this may result in stalled requests."
or
"unhandledRejection: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client"
I seem to have some gap in my knowledge about how the API works in Next JS because I cannot figure out how to just run the async function, get a result, set a couple of cookies and then exit with a 200. Could someone please tell me what I'm doing wrong?
I am using node.js as my endpoint for SNS (this is my first one , correct aws terms may be missing)
The node code is pretty simple
I am using express and in my route i have
router.post('/bounce',
bodyParser.urlencoded({extended: true}),
bodyParser.json(), function (req, res, next) {
console.log("Recieving a new post ");
console.log(req.body);
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({success: true}));
});
When i subscribe via the SNS console i see the incoming post but it is always an empty object. To verify the endpoint is working i post from postman with a json object and it displays what i would expect
I have the node amazon sdk , but I do not understand where that fits in the picture
I assume i must be missing a step??
thanks for any help
This is what i had to do to get what i needed
var express = require('express');
var bodyParser = require('body-parser');
var http = require('http');
var router = express.Router();
var app = express();
app.use(bodyParser.json());
app.use(router);
router.post('/bounce', function(req, res){
var chunks = [];
req.on('data', function (chunk) {
chunks.push(chunk);
});
req.on('end', function () {
var message = JSON.parse(chunks.join(''));
console.log(message);
});
res.end();
});
http.createServer( app).listen(4040, function () {
console.log("server listening on port " + 4040);
});
// global
var ws = null;
var msgCount = 0;
var onMessageHandler = null;
// test #1 - this test passes successfully
describe('connect to wsserver test', function() {
it('should successfully connect to wsserver', function(done) {
this.timeout(0);
ws = new FayeWebSocket.Client('wss://server.com', null, {
headers: {
"authToken": "someToken"
}
});
ws.on('open', function() {
done();
});
ws.on('message', function(msg) {
if (onMessageHandler && typeof onMessageHandler === 'function') {
onMessageHandler(msg);
}
});
ws.on('close', function(event) {
console.log('closing websocket!');
});
ws.on('error', function(err) {
console.log("error!: " + err.message);
});
});
});
// test #2 - this test blocks indefinitely
describe('send request and get back 3 response messages', function() {
it('should get back 3 response messages from the wsserver', function(done) {
this.timeout(0);
// this function is called ONLY once, although the server is sending 3 messages
onMessageHandler = function(msg) {
msgCount++;
console.log(msg);
if (msgCount >= 3) {
done();
}
}
var sendThisRequest = {
'some': 'json',
'with': 'some key/value pairs'
}
// this line sends a request to the wsserver
ws.send(JSON.stringify(sendMsg));
});
});
I'm trying to write some basic unit tests to test my websocket apis. These mocha tests are simulating the client, NOT the websocket server.
In the first test I just connect to the websocket server using a websocket, this test passes successfully.
In the second test I'm sending a request to the server ( from ws.send(message) ), the server does get this request correctly, does some processing and sends 3 websocket messages to the client. (Looking at the server logs, I can say that this part is working fine on the server)
The test should complete after getting the 3 messages and some expect(something).to.equal(something) assertions
I haven't been able to figure out so far why the 2nd and 3rd messages are never picked up by the onMessageHandler(). I've tried placing the ws.on('message',function(msg){..}) block at different places in the code but to no avail.
If someone could point me in the right direction for this problem, that would be great. Thanks
I think you are not able to do streaming of data with current unit test with mocha.
ws.send(JSON.stringify(sendMsg));
You are calling this statement only once which means only one time data is streamed. You need to call it multiple time to check n time streaming.
This code works correctly. There was some problem with the inputs that I was passing to the server. Sorry!
Http-Proxy, like adapter, adds "/store-name" at the last of the proxy target that I specify.
I want to have complete control of the URL ,or atleast I should be able to add suffix to the url.
The file server/proxies/members.js looks like this for me.
var proxyPath = '/members';
module.exports = function(app) {
// For options, see:
// https://github.com/nodejitsu/node-http-proxy
var proxy = require('http-proxy').createProxyServer({});
proxy.on('error', function(err, req) {
console.error(err, req.url);
});
app.use(proxyPath, function(req, res, next){
// include root path in proxied request
req.url = proxyPath + '/' + req.url;
proxy.web(req, res, { target: 'http://localhost:8082/connection/testdb?tablename=' });
});
};
As the final url is this case looks like
"http://localhost:8082/connection/testdb?tablename=/members/"
instead i want
http://localhost:8082/connection/testdb?tablename=storename
P.S.: Is something like "buildURL=url" , possible in http-proxy
I'm unclear on exactly what you're trying to do, but take a look at the prependPath and ignorePath options to proxy.createProxysServer() (https://github.com/nodejitsu/node-http-proxy#options)
Update: Setup a proxyReq handler on the proxy object and you can manipulate the path any way you want. For example:
proxy.on('proxyReq', function(proxyReq, req, res, options) {
proxyReq.path = '/custom/path/here';
});