Intern ajax testing with node.js - ajax

I'm using intern with node.js, trying to set up intern for ajax testing. The server code below serves direct GET requests, but XHR request by Intern doesn't seem to reach to it. I suspect the problem is something to do with proxyUrl setup for the Node.
server/main.js: Node/express
...
app.get('/data', function(request, response, next){
if(request.xhr)
{
var data = dfs.readFileSync("src/server/data.json");
response.render(data, {
root: root,
error: new Error('Cant read file')
});
}
else
next();
});
...
app.listen(8001);
http_proxy.createServer(function(req,res, proxy){
proxy.proxyRequest(req,res, {host:'localhost', port:8001});
}).listen(9000);
intern.hello.js: (unit test code)
...
'async test': function () {
var dfd = this.async(1000);
request('/data').then(dfd.callback(function (data) {
assert.strictEqual(data, 'hello world');
}, dfd.reject.bind(dfd)));
}
intern config:
...
proxyPort:9000,
proxyUrl: 'http://localhost:8001/',
...
intern error:
Warning: FAIL: async test (1015ms)
Error: Timeout reached on main - wait - async test
at Error (<anonymous>)
at new ErrorCtor (.../node_modules/intern/node_modules/dojo/errors/create.js:13:21)
at null._onTimeout (.../node_modules/intern/lib/Test.js:164:21)
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
2/3 tests passed
2/3 tests passed Use --force to continue.

Related

How to locally test a serverless lambda function?

Background
I was thrown on this project to help alleviate some stress. The trouble is no one else has done this either so I'm pioneering the cause.
What I know
I can get lambda function output locally with:
serverless invoke local -f getArticlesById -p localfile.json -s dev
and it returns a JSON article as expected.
Question
I'm using Jasmine to test my javascript lambda functions. How can I unit test these serverless environment functions locally?
Current Attempt
My lambda function is in articles/articleHandler.js. I have a test/articles.js that runs jasmine tests leveraging lambda-tester functions. Whenever I run one of these tests I get the error
TypeError: Invalid hosts config. Expected a URL, an array of urls, a host config object, or an array of host config objects.
at new Transport (/Users/Jackson/Sites/serverless-content/node_modules/elasticsearch/src/lib/transport.js:59:13)
at new EsApiClient (/Users/Jackson/Sites/serverless-content/node_modules/elasticsearch/src/lib/client.js:57:22)
at Function.Client (/Users/Jackson/Sites/serverless-content/node_modules/elasticsearch/src/lib/client.js:101:10)
at Object.<anonymous> (/Users/Jackson/Sites/serverless-content-distribution-api-v2/elasticSearch.js:6:42)
at Module._compile (module.js:635:30)
at Object.Module._extensions..js (module.js:646:10)
at Module.load (module.js:554:32)
at tryModuleLoad (module.js:497:12)
at Function.Module._load (module.js:489:3)
at Module.require (module.js:579:17)
I've found that this is caused by including the lambda function into the test. When I comment out that line I don't get the error. I'm guessing that because this is not a serverless call, Elasticsearch knows nothing of my environment.
test/article.js
console.log("testing articles")
const LambdaTester = require("lambda-tester");
const articleHandler = require("../articles/articleHandler.js");
describe("articles getID()", function() {
it("test success", function() {
return LambdaTester(articleHandler.getID)
.event({pathParameters:{id:5633415102001}})
.expectResult(result => {
expect(result.body.data.id).to.be(5633415102001)
});
});
})
describe("articles getList()", function() {
it("test success", function() {
return LambdaTester(articleHandler.getList)
.event()
.expectResult(reset => {
expect(result.body.data.length).to.be(10);
});
});
});
** ADDITIONAL **
It's looking like lambda-tester is supposed to alleviate the problem I'm encountering. Will find out more today.
Use lamba-tester, there are examples on the github page.
I wrote a simple lambda test function and then tested the output with jasmine + lambda-tester
As for my code, I'll need to refactor the handler someone else wrote before it will work. My simple test looks like:
Serverless yml
testLambda:
handler: test/testLambda.getValueOfA
role: arn:aws:iam::367839381035:role/CodeStarWorker-fx-srch-api-v1-Lambda
events:
- http:
path: test/testLambda/{a}
method: get
Lambda Function
module.exports.getValueOfA = (event, context, callback) => {
let a = 2;
if(event
&& event.pathParameters
&& !isNaN(event.pathParameters.a)
) a = event.pathParameters.a;
a = a+a;
let ret = "the value of a is " + a;
callback(null, ret);
}
Test
const LambdaTester = require("lambda-tester");
const TestLambda = require("./testLambda.js");
describe("testLambda()", function() {
it("test success", function() {
let ret;
LambdaTester(TestLambda.getValueOfA)
.event()
.expectResult(result => {
console.log(result);
expect(result).toEqual("the value of a is 4");
});
});
});
I was going to set this up for parameters but didn't get there. Granted this is enough to get anyone moving forward.
another option you have is to call the function directly from your test. In the end, it's nothing more than a function, so you can import the module and call it, passing the right parameters.

Mocha Chai HTTP post request not working

The following test is not working with mocha-chai, it is able to to get the input request but throws the error message.
it('/hb : ', function (done) {
return chai.request(app)
.post('/hb')
.send({"a":1 })
.then(function (res) {
expect(err).to.be.null;
expect(res).to.have.status(200);
// { ah: { rt: [Object] }, ad: { mojo: 1 } } }
//console.log("CAlling DOne ........... +");
done();
}, function (err) {
//console.log(err);
throw err;
});
});
Output:
Web Requests : /hb : :
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
The functions that chai-http adds to chai return promises. In your code you return the promise, which is good. However, you also declare your test to take the a parameter: function (done). This would be fine if you did not return the promise, but returning the promise is really the better mechanism here. When you declare your test to take a parameter, Mocha ignores the return value from the test, and so the promise is ignored. So just remove your use of done.
Here's an example that reproduces the error you had in your original code with err being undefined in the function you pass to then.
'use strict';
var app = require('./server');
var chai = require('chai');
chai.use(require('chai-http'));
var expect = chai.expect;
it('/hb', function () {
return chai.request(app)
.post('/hb')
.send({a: 1})
.then(function (res) {
expect(err).to.be.null;
expect(res).to.have.status(200);
});
});
If the server returns a 200 status, then you'll get this on the console:
1) /hb
0 passing (26ms)
1 failing
1) /hb:
ReferenceError: err is not defined
at test.js:13:20
If the server returns a 400 status, the output would be:
1) /hb
0 passing (24ms)
1 failing
1) /hb:
Error: Bad Request
at Test.Request.callback (node_modules/superagent/lib/node/index.js:792:17)
at IncomingMessage.<anonymous> (node_modules/superagent/lib/node/index.js:990:12)
at endReadableNT (_stream_readable.js:913:12)
you need to add following:
.set('content-type', 'application/x-www-form-urlencoded')
you can reference this question over Post request via Chai

Karma+Jasmine: ajax call with real(not mocked) response

I'd like getting real response from server when send XmlHttpRequest in karma env + Jasmine. Test case
it('get data from server', function (done) {
var request = new XMLHttpRequest();
request.open('GET', 'my_working_backPoint');
request.onload = function (resp) {
console.log(resp);
done();
};
request.send();
});
But I get this:
Error: Timeout - Async callback was not invoked within timeout
specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
I couldn't find any helpful answers. Please explain me how I could test real ajax call.

Problems with $httpBackend.verifyNoOutstandingExpectation()

I have recently started writting unit tests using Karma + Karma-jasmine but I am having problems with the following tests:
describe("WEBSERVICE:", function () {
var webservice,
$httpBackend,
authRequestHandler,
webserviceURL = "http://localhost:8006/";
beforeEach(inject(function (Webservice, $injector) {
webservice = Webservice;
$httpBackend = $injector.get("$httpBackend");
authRequestHandler = $httpBackend
.when("GET", webserviceURL + "users/login")
.respond(200, "ok");
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it("should EXISTS", function () {
expect(webservice).toBeDefined();
});
it("should throw a WebserviceError if we are not logged in" , function () {
expect(function () {
webservice.item("negs", "RPT");
}).toThrow(webserviceAuthenticationError);
});
it("should NOT HAVE credentials when instantiated", function () {
expect(webservice.hasCredentials()).toBeFalsy();
});
it("should log in when valid credentials are given", function () {
$httpBackend.expectGET("users/login");
webservice.withCredentials("sam", "password");
});
});
It appears to be the following which creates the problem since all tests pass when I remove it:
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
I was just wondering if anyone could help me with this.
Thanks a lot.
The reason you having problems is with
$httpBackend.verifyNoOutstandingExpectation();
is due to your last test
it("should log in when valid credentials are given", function () {
$httpBackend.expectGET("users/login");
webservice.withCredentials("sam", "password");
});
having unsatisfied requests which you can see in this jsfiddle
Error: Unsatisfied requests: GET users/login
If you comment out
$httpBackend.verifyNoOutstandingExpectation()
your first three tests pass but the last one is amber as there is no expectations, see this fiddle.
WEBSERVICE:
should EXISTS
should throw a WebserviceError if we are not logged in
should NOT HAVE credentials when instantiated
SPEC HAS NO EXPECTATIONS should log in when valid credentials are given
In the AngularJS documentation it says
verifyNoOutstandingExpectation();
Verifies that all of the requests defined via the expect api were made. If any of the requests were not made, verifyNoOutstandingExpectation throws an exception.
You will need to restructure that test so that
webservice.withCredentials("sam", "password");
makes a request through $httpBackend

Cannot submit form with supertest and mocha

I am using supertest and mocha to test a nodejs application. One of the things users can do is to submit a very simple form, which is picked up by the node server and parsed using formidable.
Here is the mocha test code:
var should = require('should'),
express = require('express'),
app = require('../app.js'),
request = require('supertest'),
csrfToken,
sessionId,
cookies = [];
describe('Post Handler', function(){
it('Uploads new post', function(done){
var req = request(app).post('/post?_csrf=' + csrfToken);
req.cookies = cookies;
req
.type('form')
.send({fieldTitle: 'autopost'})
.send({fieldContent: 'autocontent'})
.send({contentType: 'image/png'})
.send({blobId: 'icon_23943.png'})
.expect(200)
.end(function(error, res){
console.log('here');
done();
});
});
csrfToken retrieves a csrf token from the server, since I am using the csurf module and every POST method requires a csrf token. cookies stores the session cookie that is provided by the node server so I can persist the session between requests.
The form is processed by the following code:
//Takes HTTP form posted by client and creates a new post in the Db
exports.postPostUpload = function (req, res) {
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
console.log(err);
if (err) res.redirect(303, '/error');
else {
var new_post = new post_model.Post().createNewPost(fields);
new_post.setUserId(req.session.passport.user.userId);
new_post.uploadPostToDb(function (error, result) {
if (error) return res.status(500).end();
else {
if (new_post.media.contentType.indexOf('video') !== -1) {
addMessageToEncodingQueue(new_post, function (error, result, response) {
if (error) {
errorHelper.reportError({
stack: new Error().stack,
error: error
});
res.status(500).end();
}
else res.status(200).send(new_post.cuid);
});
}
else return res.status(200).send(new_post.cuid);
}
});
}
});
}
My current problem is, that once the form handler executes the line form.parse(req, function (err, fields, files) {, nothing happens. Formidable does not return error, it just does not return anything. Consequently, the mocha test never receives a reply from the server, and eventually the socket hangs and the test crashes. Needless to say, the form is successfully submit if you do it manually via the website.
There must be an error in the way supertest/mocha are executing this test, but I have not been able to find it. Any pointers are highly appreciated.

Resources