Should testing, Javascript webservice API - javascript

I am testing my REST API with should.
At the moment i have tested my methods to work as intended via the browser, and console testing.
My test cases are turning out to work just fine when testing with should, on the GET methods from my API.
Are there any way to test the delete and post methods in should, og would i be better of to use another testing enviroment ?
Following is a snippet from my API
router.delete('/deleteProfile/:id', function (req, res) {
var toDelete = req.params.id;
dataLayer.deleteProfile(toDelete, function (err, result) {
if(err) res.status(500).send('Person + ' + toDelete+ ' not deleted')
else{
console.log(result);
res.json(result);
}
});
Following is a snippet of my test :
it("Should delete the user With the userName FrækFyr91", function (done) {
http.get("http://localhost:"+testPort+"/profileApi/deleteProfile/FrækFyr91",function(res){
res.setEncoding("utf8");//response data is now a string
res.on("data",function(chunk){
var n = JSON.parse(chunk);
n.length.should.equal(4);
done();
});
})
});
I know the http.delete wont work.
Any suggestions ?

Rather than using http, I'd recommend using one of the specialized REST client libs, like restler, which are specifically designed to communicate with RESTful routes.
You might also consider using chai for your testing assertions as it provides very comprehensive BDD-style assertions.
So instead of your:
http.get(endpointUrl,function(res){
res.on('data',...);
});
I'd use:
var mocha=require('mocha'),
should=require('chai').should(),
client=require('restler');
describe('deletions',function(){
it('should delete something',function(done){
client.del(deleteEndpointUrl).on('complete',function(result){
// if the request failed, result will be an Error
if(result instanceof Error) {
return done(result); // return error
}
// test result here
result.should.be.an.object; // chai.should extends objects with assertions
// etc.
done();
});
});
});

Related

nodejs recursively fetch all pages from different REST end points

I am kind of struggling with my JavaScript. Still getting my head around the callbacks. I have a function which recursively fetches the next link page from an REST endpoint.which works fine for a single url
Now i need to use the same recrusive function to do same for other end points. thats where iam struggling now. It is obvious that iam missing a point or i badly understood callback concept.
please excuse the formatting What i have done so far ..
function getFullLoad(rest_url,callback){
mongoose.connect(url, function(err) {
console.log(url);
if (err) throw err;
console.log("successfully connected");
getToken(function(err, token) {
if (err) throw console.error(err);
console.log('using access token to retrieve data :', token[0]
['access_token']);
var options = {
'auth': {
'bearer': token[0]['access_token']
}
}
request.get(rest_url, options, function(error, response, body) {
if (!error && response.statusCode === 200) {
var data = JSON.parse(body);
//save data in mongo
});
}
var next_page = JSON.parse(body)["_links"]["next"]
if (next_page) {
var next_page_url = JSON.parse(body)["_links"]["next"]["href"];
console.log("Fetching data from ", next_page);
//recrusively call back with next url
getFullLoad(next_page_url,callback);
} else {
callback();
} else {
if (error) throw error;
}
});
rest_url= "http://myrest_url"
//this bit is working if there is a single url
getFullLoad(rest_url, function() {
console.log('done , got all data');
});
this works great ,now i need to call the same function with different urls . It may be some urls may not have not pagination.
so far this is my effort , it only takes the first url and then does nothing.
This bit is not working . what iam doing wrong? i tried creating another callback function. i guess my knowledge is quite limited on callbacks. any help very much appreciated
api_endpoints =[ {"url1": "http://url1"},{"url2": "http://url2"}]
api_endpoints.forEach(function(Item, endpoint) {
var endpoint_name = Object.keys(api_endpoints[endpoint]).toString());
var rest_url = api_config.BASE_URL + api_endpoints[endpoint]
[endpoint_name];
getFullLoad(rest_url, function) {
console.log('done');
});
});
Thank you for looking my question
With a bit of refactoring I think you can get something to work.
I would change your getFullLoad method to return a promise (the request.get) then in your foreach loop I would build up an array of promises that call the getFullLoad with the different urls.
Then use promises.all(arrayOfPromises) to execute them and manage the results.
It will be easier to understand and maintain long term.
Check out the promise documentation here:
Promise.all

Mocha Unit Test Error Handling from Library

I have the following code below that basically gets a user from a database. The code below is using Dynamoose but I'm assuming there is something similar in many other libraries and packages.
User.get(searchid, function(err, user) {
if (err) {
console.log(err);
return res.send('error');
} else {
//DO LOGIC
}
});
I have written unit tests to handle all the logic inside the else statement above. But I'm trying to figure out if there is a way to write unit tests to handle the if (err) section of the code. Basically I want to write unit tests to make sure that if there is an error it returns the correct stuff tho I would be up for any suggestions of other tests I should write. How can I write tests in this case and cover this code with unit tests?
You should mock User.get to make it execute the callback directly, with the parameters you want.
To do that, you may have multiple possibility depending on your test setup.
I use rewire https://github.com/jhnns/rewire
If your code look like :
//myCode.js
var User = require('./model/User');
module.exports = function(){
User.get(searchid, function(err, user) {
if (err) {
console.log(err);
return res.send('error');
} else {
//DO LOGIC
}
});
}
Basicaly your test look like :
var myCode = rewire("../lib/myCode.js");
...
var UserMock = {
get: function (searchid, cb) {
cb(new Error(), null);
}
};
myCode.__set__("User", UserMock);
myCode.myFunctionCallingUserGet(function (err, data) {
// Test that you send error.
});

Handle successful HTTP promise if one fails in Bluebird

I'm fairly new to Promises and have been attempting to get this piece of code to work properly. Here's what I have.
var Promise = require('bluebird');
Promise.join(getProducts, getPricing, function(products, pricing) {
console.log('products: ' + products.body);
console.log('pricing: ' + pricing.body);
// Add pricing to products here
res.send(products.body);
})
.catch(function(e) {
console.log(e);
res.sendStatus(500);
});
Requirements...
I want to call both APIs at the exact same time and process the results when both complete.
If the Pricing API fails, I still want to return the Products with no pricing.
If the Products API fails, I want to error out and send 500 back to the client.
My code seems to work if both API calls are successful, but will always go into the catch if either fail and ignore any successful calls.
I can get this working fine if I use a synchronous Promise chain, but I'd like to call both APIs at the same time.
How can I call both APIs asynchronously and process the results outside of the catch?
You'll want to put a catch on exactly the promise whose failure you want to handle - i.e. getPricing.
Promise.join(getProducts, getPricing.catch(function(err) {
// ignore or log?
return null;
}, function(products, pricing) {
console.log('products: ' + products.body);
if (pricing) {
console.log('pricing: ' + pricing.body);
// Add pricing to products here
} // else?
res.send(products.body);
}).catch(function(e) {
console.log(e);
res.sendStatus(500);
});
You can also use getPricing.reflect() if you want to more explicitly distinguish the two cases.
Forewarning: I'm decent with promises, but not this particular library.
var Promise = require('bluebird');
var pricing = getPricing().catch(function(e) {
return null;
})
Promise.join(getProducts, pricing, function(products, pricing) {
console.log('products: ' + products.body);
console.log('pricing: ' + pricing ? pricing.body : '<null>');
// Add pricing to products here
res.send(products.body);
}).catch(function(e) {
console.log(e);
res.sendStatus(500);
});
Modify getPricing() such that it never fails. The easiest way to do this is by adding a top-level .catch(). The example code below wraps the getPricing() method
var Promise = require('bluebird');
function getProducts(){/* add implementation */};
function originalGetPricing(){/* add implementation */};
function getPricing(){
return originalGetPricing()
.catch(function(err) {
return Promise.resolve(/* replace this comment with empty object or some other suitable response */);
});
};
Promise.join(getProducts, getPricing, function(products, pricing) {
console.log('products: ' + products.body);
console.log('pricing: ' + pricing.body);
// Add pricing to products here
res.send(products.body);
})
.catch(function(e) {
console.log(e);
res.sendStatus(500);
});

Handling a GET request in Node.js Express server: res.render(file.ejs, data) not working because data is not defined

In a server made with Express in Node.js, I have the following code for handling a GET request:
function articleReturner(celien) { // function querying a database (celien is a string, cetarticle is a JSON)
Article.findOne({ lien: celien}, function (err, cetarticle){
console.log(cetarticle); // it works
return cetarticle;
});
}
app.get('/selection/oui/', function(req, res) { // the URL requested ends with ?value=http://sweetrandoms.com, for example
var celien = req.param("value"); //
console.log(celien); // it works
articleReturner(celien); // calling the function defined above
res.render('selection_form.ejs', cetarticle); // doesn't work!
});
I know that data from the URL routing is correctly obtained by the server since the console correctly displays celien (a string). I also know that the function articleReturner(celien) is correctly querying the database because the console correctly displays cetarticle (a JSON).
But res.render('selection_form.ejs', cetarticle); is not working and the console displays ReferenceError: cetarticle is not defined... What am I missing? Thanks!
Function articleReturner is executed asynchronously and return cetarticle; doesn't make a lot of sense. You need to use callbacks or promises. Here is the code that uses callback to return result from articleReturner:
function articleReturner(celien, callback) {
Article.findOne({ lien: celien}, function (err, cetarticle){
console.log(cetarticle);
callback(err,cetarticle);
});
}
app.get('/selection/oui/', function(req, res) {
var celien = req.param("value"); //
console.log(celien); // it works
articleReturner(celien, function(err, cetarticle){
res.render('selection_form.ejs', cetarticle);
});
});

Testing ajax requests using jasmine returns TypeError

The description of the task. I want to test the code that loads a list of resources using $.get.
So, the source code:
fetchTemplates: function(list, cb){
var promises = [],
$container = $('#templates');
Object.keys(list).forEach(function(tplSelector){
if($(tplSelector).length > 0){ return; }
var promise = $.get(list[tplSelector]);
promise
.done(function(tplHtml){
$container.append(tplHtml);
})
.fail(function(){
console.warn('Template "' + tplSelector + " not found by url:" + list[tplSelector]);
});
promises.push( promise );
});
return $.when.apply($,promises).done(cb);
}
The test suite:
it("Correct template fetching", function (done) {
var fetchResult = viewManager.fetchTemplates({
'#helpTpl': 'somecorrectaddress'
});
fetchResult.done(function () {
expect(true).toBeTruthy();
done();
});
fetchResult.fail(function () {
expect(false).toBeTruthy();
done();
});
});
What it generates. Test passes, but generates an error:
TypeError: 'null' is not an object (evaluating 'this.results_.addResult')
at jasmine.js?2348
So, the test case marks as passed. But whole test suite still generates the error above (and this method is the only one async, other parts are trivial to test). My thought was that since the tested method contains async operations and promises - results were not properly handled and thus TypeError. So I added jasmine async "done()" to handle the issue - unfortunately nothing changed. Also worth noting that if I leave only one test in the suite using "iit" - no error is generated. Search didn't find similar cases. Any ideas?
You need to wrap your async calls in 'runs()' with 'waitsFor()' after, read the documentation here. I've never worked with jquery, but try something like the following inside your it function:
var done = false;
var that = this;
runs( function() {
//your async test goes here
that.done = true;
});
waitsFor( function() {
return that.done;
}, "async code failed", 2000);

Categories

Resources