From 9312aca8a1c7059f98d510c28438efd3005a8c24 Mon Sep 17 00:00:00 2001 From: Jacob Marttinen Date: Thu, 7 May 2015 20:13:17 -0400 Subject: [PATCH] Adding jsbeautifier grunt task --- Gruntfile.js | 74 ++++--- lib/bing.js | 472 +++++++++++++++++++++----------------------- package.json | 1 + test/basic.js | 78 ++++---- test/integration.js | 149 +++++++------- 5 files changed, 389 insertions(+), 385 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 75e70c9..e881015 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,36 +1,48 @@ -module.exports = function(grunt) { - grunt.initConfig({ - simplemocha: { - options: { - globals: ['should'], - timeout: 3000, - ignoreLeaks: false, - ui: 'bdd', - reporter: 'list' - }, - all: { src: ['test/**/*.js'] } - }, +module.exports = function (grunt) { + grunt.initConfig({ + simplemocha: { + options: { + globals: ['should'], + timeout: 3000, + ignoreLeaks: false, + ui: 'bdd', + reporter: 'list' + }, + all: { + src: ['test/**/*.js'] + } + }, - jshint: { - options: { - laxbreak: true - }, - all: [ 'Gruntfile.js', 'index.js', 'lib/**/*.js', 'test/**/*.js'] - }, + jsbeautifier: { + files: ['Gruntfile.js', 'index.js', 'lib/**/*.js', 'test/**/*.js'], + options: { + js: { + jslintHappy: true + } + } + }, - jsdoc: { - all: { - src: ['index.js', 'lib/**/*.js'], - dest: 'doc' - } - } - }); + jshint: { + options: { + laxbreak: true + }, + all: ['Gruntfile.js', 'index.js', 'lib/**/*.js', 'test/**/*.js'] + }, - grunt.loadNpmTasks('grunt-contrib-jshint'); - grunt.loadNpmTasks('grunt-simple-mocha'); - grunt.loadNpmTasks('grunt-jsdoc'); + jsdoc: { + all: { + src: ['index.js', 'lib/**/*.js'], + dest: 'doc' + } + } + }); - grunt.registerTask('test', ['simplemocha:all']); - grunt.registerTask('build', ['jshint', 'test']); - grunt.registerTask('default', ['build', 'jsdoc']); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-jsbeautifier'); + grunt.loadNpmTasks('grunt-simple-mocha'); + grunt.loadNpmTasks('grunt-jsdoc'); + + grunt.registerTask('test', ['simplemocha:all']); + grunt.registerTask('build', ['jsbeautifier', 'jshint', 'test']); + grunt.registerTask('default', ['build', 'jsdoc']); }; diff --git a/lib/bing.js b/lib/bing.js index 590782d..7529183 100644 --- a/lib/bing.js +++ b/lib/bing.js @@ -1,246 +1,226 @@ - -/********************************************************* - * Simple Node.js module for using the Bing Search API * - *********************************************************/ - -// Require dependencies -var request = require('request'), - url = require('url'), - _ = require('underscore'), - qs = require('querystring'); - -/** - * @param {Object} options Options to all Bing calls, allows overriding of - * rootUri, accKey (Bing API key), userAgent, reqTimeout - * @returns {Bing} - * @constructor - */ -var Bing = function( options ) { - - if( !(this instanceof Bing) ) return new Bing( options ); - - var defaults = { - - //Bing Search API URI - rootUri: "https://api.datamarket.azure.com/Bing/Search/v1/", - - //Account Key - accKey: null, - - //Bing UserAgent - userAgent: 'Bing Search Client for Node.js', - - //Request Timeout - reqTimeout: 5000, - - // Number of results (limited to 50 by API) - top: 50, - - // Number of skipped results (pagination) - skip: 0 - - }; - - //merge options passed in with defaults - this.options = _.extend(defaults, options); - - this.searchVertical = function(query, vertical, options, callback) { - if (typeof options === 'function') { - callback = options; - } - if(typeof callback != 'function') { - throw "Error: Callback function required!"; - } - - // Create a copy of the options, to avoid permanent overwrites - var opts = JSON.parse(JSON.stringify(this.options)); - - if (typeof options === 'object') { - _.extend(opts, options); - } - - var reqUri = opts.rootUri - + vertical - + "?$format=json&" - + qs.stringify({ "Query": "'" + query + "'" }) - + "&$top=" + opts.top - + "&$skip=" + opts.skip - + (opts.sources ? "&Sources=%27" + opts.sources + "%27" : '') - + (opts.newssortby ? "&NewsSortBy=%27" + opts.newssortby + "%27" : '') - + (opts.newscategory ? "&NewsCategory=%27" + opts.newscategory + "%27" : '') - + (opts.newslocationoverride ? "&NewsLocationOverride=%27" + opts.newslocationoverride + "%27" : '') - + (opts.market ? "&Market=%27" + opts.market + "%27" : '') - + (opts.adult ? "&Adult=%27" + opts.adult + "%27" : '') - + (opts.imagefilters - ? '&' + qs.stringify({ "ImageFilters": "'" + opts.imagefilters + "'" }) - : '') - + (opts.videofilters - ? '&' + qs.stringify({ "VideoFilters": "'" + opts.videofilters + "'" }) - : ''); - - request({ - uri: reqUri, - method: opts.method || "GET", - headers: { - "User-Agent": opts.userAgent - }, - auth: { - user: opts.accKey, - pass: opts.accKey - }, - timeout: opts.reqTimeout - - }, function(err, res, body){ - - if(res && res.statusCode !== 200){ - err = new Error(body); - }else{ - - // Parse body, if body - body = typeof body === 'string' - ? JSON.parse(body) - : body; - } - - callback(err, res, body); - }); - }; - -}; - - -/** - * @callback requestCallback - * @param {String} error Error evaluates to true when an error has occurred. - * @param {Object} response Response object from the Bing call. - * @param {Object} body JSON of the response. - */ - - -/** - * Performs a Bing search in the Web vertical. - * - * @param {String} query Query term to search for. - * - * @param {Object} options Options to command, allows overriding - * of rootUri, accKey (Bing API key), - * userAgent, reqTimeout, top, skip - * - * @param {requestCallback} callback Callback called with (potentially - * json-parsed) response. - * - * @function - */ -Bing.prototype.web = function(query, options, callback) { - this.searchVertical(query, "Web", options, callback); -}; - -// Alias Bing.search to Bing.web -// Note: Keep this for compatibility with older versions -Bing.prototype.search = Bing.prototype.web; - - -/** - * Performs a Bing search in the Composite vertical. - * - * @param {String} query Query term to search for. - * - * @param {Object} options Options to command, allows overriding - * of rootUri, accKey (Bing API key), - * userAgent, reqTimeout, top, skip, - * - * @param {requestCallback} callback Callback called with (potentially - * json-parsed) response. - * @function - */ -Bing.prototype.composite = function(query, options, callback) { - this.searchVertical(query, "Composite", options, callback); -}; - -/** - * Performs a Bing search in the News vertical. - * - * @param {String} query Query term to search for. - * - * @param {Object} options Options to command, allows overriding - * of rootUri, accKey (Bing API key), - * userAgent, reqTimeout, top, skip, - * - * @param {requestCallback} callback Callback called with (potentially - * json-parsed) response. - * @function - */ -Bing.prototype.news = function(query, options, callback) { - this.searchVertical(query, "News", options, callback); -}; - -/** - * Performs a Bing search in the Video vertical. - * - * @param {String} query Query term to search for. - * - * @param {Object} options Options to command, allows overriding - * of rootUri, accKey (Bing API key), - * userAgent, reqTimeout, top, skip, - * - * @param {requestCallback} callback Callback called with (potentially - * json-parsed) response. - * @function - */ -Bing.prototype.video = function(query, options, callback) { - if (options - && typeof options === 'object' - && options.videofilters - && typeof options.videofilters === 'object') { - var filterQuery = ''; - var filters = Object.keys(options.videofilters); - filters.map(function(key, i) { - filterQuery += capitalizeFirstLetter(key) + ':'; - filterQuery += capitalizeFirstLetter(options.videofilters[key]); - if (i < filters.length - 1) - filterQuery += '+'; - }); - options.videofilters = filterQuery; - } - this.searchVertical(query, "Video", options, callback); -}; - - - -/** - * Performs a Bing search in the Images vertical. - * - * @param {String} query Query term to search for. - * - * @param {Object} options Options to command, allows overriding of - * rootUri, accKey (Bing API key), - * userAgent, reqTimeout, top, skip, - * imagefilters - * - * @param {requestCallback} callback Callback called with (potentially - * json-parsed) response. - * @function - */ -Bing.prototype.images = function(query, options, callback) { - if (options - && typeof options === 'object' - && options.imagefilters - && typeof options.imagefilters === 'object') { - var filterQuery = ''; - var filters = Object.keys(options.imagefilters); - filters.map(function(key, i) { - filterQuery += capitalizeFirstLetter(key) + ':'; - filterQuery += capitalizeFirstLetter(options.imagefilters[key]); - if (i < filters.length - 1) - filterQuery += '+'; - }); - options.imagefilters = filterQuery; - } - this.searchVertical(query, "Image", options, callback); -}; - -function capitalizeFirstLetter(s) { - return s.charAt(0).toUpperCase() + s.slice(1); -} - -module.exports = Bing; +/********************************************************* + * Simple Node.js module for using the Bing Search API * + *********************************************************/ + +// Require dependencies +var request = require('request'), + url = require('url'), + _ = require('underscore'), + qs = require('querystring'); + +/** + * @param {Object} options Options to all Bing calls, allows overriding of + * rootUri, accKey (Bing API key), userAgent, reqTimeout + * @returns {Bing} + * @constructor + */ +var Bing = function (options) { + + if (!(this instanceof Bing)) return new Bing(options); + + var defaults = { + + //Bing Search API URI + rootUri: "https://api.datamarket.azure.com/Bing/Search/v1/", + + //Account Key + accKey: null, + + //Bing UserAgent + userAgent: 'Bing Search Client for Node.js', + + //Request Timeout + reqTimeout: 5000, + + // Number of results (limited to 50 by API) + top: 50, + + // Number of skipped results (pagination) + skip: 0 + + }; + + //merge options passed in with defaults + this.options = _.extend(defaults, options); + + this.searchVertical = function (query, vertical, options, callback) { + if (typeof options === 'function') { + callback = options; + } + if (typeof callback != 'function') { + throw "Error: Callback function required!"; + } + + // Create a copy of the options, to avoid permanent overwrites + var opts = JSON.parse(JSON.stringify(this.options)); + + if (typeof options === 'object') { + _.extend(opts, options); + } + + var reqUri = opts.rootUri + vertical + "?$format=json&" + qs.stringify({ + "Query": "'" + query + "'" + }) + "&$top=" + opts.top + "&$skip=" + opts.skip + (opts.sources ? "&Sources=%27" + opts.sources + "%27" : '') + (opts.newssortby ? "&NewsSortBy=%27" + opts.newssortby + "%27" : '') + (opts.newscategory ? "&NewsCategory=%27" + opts.newscategory + "%27" : '') + (opts.newslocationoverride ? "&NewsLocationOverride=%27" + opts.newslocationoverride + "%27" : '') + (opts.market ? "&Market=%27" + opts.market + "%27" : '') + (opts.adult ? "&Adult=%27" + opts.adult + "%27" : '') + (opts.imagefilters ? '&' + qs.stringify({ + "ImageFilters": "'" + opts.imagefilters + "'" + }) : '') + (opts.videofilters ? '&' + qs.stringify({ + "VideoFilters": "'" + opts.videofilters + "'" + }) : ''); + + request({ + uri: reqUri, + method: opts.method || "GET", + headers: { + "User-Agent": opts.userAgent + }, + auth: { + user: opts.accKey, + pass: opts.accKey + }, + timeout: opts.reqTimeout + + }, function (err, res, body) { + + if (res && res.statusCode !== 200) { + err = new Error(body); + } else { + + // Parse body, if body + body = typeof body === 'string' ? JSON.parse(body) : body; + } + + callback(err, res, body); + }); + }; + +}; + + +/** + * @callback requestCallback + * @param {String} error Error evaluates to true when an error has occurred. + * @param {Object} response Response object from the Bing call. + * @param {Object} body JSON of the response. + */ + + +/** + * Performs a Bing search in the Web vertical. + * + * @param {String} query Query term to search for. + * + * @param {Object} options Options to command, allows overriding + * of rootUri, accKey (Bing API key), + * userAgent, reqTimeout, top, skip + * + * @param {requestCallback} callback Callback called with (potentially + * json-parsed) response. + * + * @function + */ +Bing.prototype.web = function (query, options, callback) { + this.searchVertical(query, "Web", options, callback); +}; + +// Alias Bing.search to Bing.web +// Note: Keep this for compatibility with older versions +Bing.prototype.search = Bing.prototype.web; + + +/** + * Performs a Bing search in the Composite vertical. + * + * @param {String} query Query term to search for. + * + * @param {Object} options Options to command, allows overriding + * of rootUri, accKey (Bing API key), + * userAgent, reqTimeout, top, skip, + * + * @param {requestCallback} callback Callback called with (potentially + * json-parsed) response. + * @function + */ +Bing.prototype.composite = function (query, options, callback) { + this.searchVertical(query, "Composite", options, callback); +}; + +/** + * Performs a Bing search in the News vertical. + * + * @param {String} query Query term to search for. + * + * @param {Object} options Options to command, allows overriding + * of rootUri, accKey (Bing API key), + * userAgent, reqTimeout, top, skip, + * + * @param {requestCallback} callback Callback called with (potentially + * json-parsed) response. + * @function + */ +Bing.prototype.news = function (query, options, callback) { + this.searchVertical(query, "News", options, callback); +}; + +/** + * Performs a Bing search in the Video vertical. + * + * @param {String} query Query term to search for. + * + * @param {Object} options Options to command, allows overriding + * of rootUri, accKey (Bing API key), + * userAgent, reqTimeout, top, skip, + * + * @param {requestCallback} callback Callback called with (potentially + * json-parsed) response. + * @function + */ +Bing.prototype.video = function (query, options, callback) { + if (options && typeof options === 'object' && options.videofilters && typeof options.videofilters === 'object') { + var filterQuery = ''; + var filters = Object.keys(options.videofilters); + filters.map(function (key, i) { + filterQuery += capitalizeFirstLetter(key) + ':'; + filterQuery += capitalizeFirstLetter(options.videofilters[key]); + if (i < filters.length - 1) + filterQuery += '+'; + }); + options.videofilters = filterQuery; + } + this.searchVertical(query, "Video", options, callback); +}; + + + +/** + * Performs a Bing search in the Images vertical. + * + * @param {String} query Query term to search for. + * + * @param {Object} options Options to command, allows overriding of + * rootUri, accKey (Bing API key), + * userAgent, reqTimeout, top, skip, + * imagefilters + * + * @param {requestCallback} callback Callback called with (potentially + * json-parsed) response. + * @function + */ +Bing.prototype.images = function (query, options, callback) { + if (options && typeof options === 'object' && options.imagefilters && typeof options.imagefilters === 'object') { + var filterQuery = ''; + var filters = Object.keys(options.imagefilters); + filters.map(function (key, i) { + filterQuery += capitalizeFirstLetter(key) + ':'; + filterQuery += capitalizeFirstLetter(options.imagefilters[key]); + if (i < filters.length - 1) + filterQuery += '+'; + }); + options.imagefilters = filterQuery; + } + this.searchVertical(query, "Image", options, callback); +}; + +function capitalizeFirstLetter(s) { + return s.charAt(0).toUpperCase() + s.slice(1); +} + +module.exports = Bing; diff --git a/package.json b/package.json index cdcbe42..ea9561d 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "express": "^4.9.5", "grunt": "^0.4.5", "grunt-contrib-jshint": "^0.10.0", + "grunt-jsbeautifier": "~0.2.10", "grunt-jsdoc": "^0.5.7", "grunt-simple-mocha": "^0.4.0", "mocha": "^1.21.4", diff --git a/test/basic.js b/test/basic.js index cd59137..cd8e0ea 100644 --- a/test/basic.js +++ b/test/basic.js @@ -1,31 +1,28 @@ var validWebResponse = { - "d": { - "results": [ - { - "__metadata": { - "uri": "https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query='xbox'&$skip=0&$top=1", - "type": "WebResult" - }, - "ID": "26888c2a-d245-47dc-87de-dc3551249de7", - "Title": "Xbox | Games and Entertainment on All Your Devices", - "Description": "Experience the new generation of games and entertainment with Xbox. Play Xbox games and stream video on all your devices.", - "DisplayUrl": "www.xbox.com", - "Url": "http://www.xbox.com/" - }, - { - "__metadata": { - "uri": "https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query='xbox'&$skip=1&$top=1", - "type": "WebResult" - }, - "ID": "ff23e110-31c2-44f9-be21-f213bcd4c654", - "Title": "Amazon.com: Xbox - More Systems: Video Games: Games ...", - "Description": "Online shopping for Video Games from a great selection of Games, Hardware, Computer And Console Video Game Products & more at everyday low prices.", - "DisplayUrl": "www.amazon.com/Xbox-Games/b?ie=UTF8&node=537504", - "Url": "http://www.amazon.com/Xbox-Games/b?ie=UTF8&node=537504" - } - ], - "__next": "https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query='xbox'&$skip=2" - } + "d": { + "results": [{ + "__metadata": { + "uri": "https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query='xbox'&$skip=0&$top=1", + "type": "WebResult" + }, + "ID": "26888c2a-d245-47dc-87de-dc3551249de7", + "Title": "Xbox | Games and Entertainment on All Your Devices", + "Description": "Experience the new generation of games and entertainment with Xbox. Play Xbox games and stream video on all your devices.", + "DisplayUrl": "www.xbox.com", + "Url": "http://www.xbox.com/" + }, { + "__metadata": { + "uri": "https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query='xbox'&$skip=1&$top=1", + "type": "WebResult" + }, + "ID": "ff23e110-31c2-44f9-be21-f213bcd4c654", + "Title": "Amazon.com: Xbox - More Systems: Video Games: Games ...", + "Description": "Online shopping for Video Games from a great selection of Games, Hardware, Computer And Console Video Game Products & more at everyday low prices.", + "DisplayUrl": "www.amazon.com/Xbox-Games/b?ie=UTF8&node=537504", + "Url": "http://www.amazon.com/Xbox-Games/b?ie=UTF8&node=537504" + }], + "__next": "https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query='xbox'&$skip=2" + } }; var should = require('should'), @@ -34,7 +31,7 @@ var should = require('should'), request = require('request'), bing = require('../lib/bing'); -describe('Bing', function() { +describe('Bing', function () { var server; var app; var port = 4321; @@ -43,13 +40,14 @@ describe('Bing', function() { app = express(); server = http.createServer(app); server.listen.apply(server, [port, - function(err, result) { + function (err, result) { if (err) { done(err); } else { done(); } - }]); + } + ]); }); after(function (done) { @@ -59,11 +57,14 @@ describe('Bing', function() { done(); }); - it('should cope with valid responses', function(done) { + it('should cope with valid responses', function (done) { app.get('/hello/Web', function (req, res) { res.status(200).send(JSON.stringify(validWebResponse)); }); - var bingClient = bing({ rootUri: 'http://localhost:'+port+'/hello/', accKey: '123' }); + var bingClient = bing({ + rootUri: 'http://localhost:' + port + '/hello/', + accKey: '123' + }); bingClient.search('xbox', function (error, response, body) { response.statusCode.should.eql(200); body.should.eql(validWebResponse); @@ -71,13 +72,18 @@ describe('Bing', function() { }); }); - it('should cope with errors', function(done) { + it('should cope with errors', function (done) { // No actual data on what the failure looks like. - var failure = { message: 'Failed request' }; + var failure = { + message: 'Failed request' + }; app.get('/hello/Image', function (req, res) { - res.status(500).send(failure); + res.status(500).send(failure); + }); + var bingClient = bing({ + rootUri: 'http://localhost:' + port + '/hello/', + accKey: '123' }); - var bingClient = bing({ rootUri: 'http://localhost:'+port+'/hello/', accKey: '123' }); bingClient.images('xbox', function (error, response, body) { response.statusCode.should.eql(500); body.should.eql(JSON.stringify(failure)); diff --git a/test/integration.js b/test/integration.js index 673e03b..1c01717 100644 --- a/test/integration.js +++ b/test/integration.js @@ -1,128 +1,133 @@ - // Try to get an access key to run all this test. // If the file doesn't exist or it doesn't contain an access key, it // should still run the basic tests; thus throwing an exception must // be avoided. -try{ - var accKey = require('./secrets').accKey; +try { + var accKey = require('./secrets').accKey; +} catch (e) { + console.log(e); } -catch(e){ console.log(e); } -if(!accKey){ - return console.error("Need to include an access key in your secrets.js"); +if (!accKey) { + return console.error("Need to include an access key in your secrets.js"); } -var Bing = require('../')({ accKey: accKey}); +var Bing = require('../')({ + accKey: accKey +}); var should = require('should'); -describe("Bing Search", function(){ +describe("Bing Search", function () { - this.timeout(1000 * 10); + this.timeout(1000 * 10); - it('works without options', function(done){ + it('works without options', function (done) { - Bing.search('monkey vs frog', function(err, res, body){ + Bing.search('monkey vs frog', function (err, res, body) { - should.not.exist(err); - should.exist(res); - should.exist(body); + should.not.exist(err); + should.exist(res); + should.exist(body); - body.d.results.should.have.length(50); + body.d.results.should.have.length(50); - //TODO check it contains the right fields - done(); + //TODO check it contains the right fields + done(); + }); }); - }); - it('finds only 5 results', function(done){ - Bing.search('monkey vs frog', { - top: 5, - market: 'en-US', - adult: 'Strict' - }, function(err, res, body){ - should.not.exist(err); - should.exist(res); - should.exist(body); + it('finds only 5 results', function (done) { + Bing.search('monkey vs frog', { + top: 5, + market: 'en-US', + adult: 'Strict' + }, function (err, res, body) { + should.not.exist(err); + should.exist(res); + should.exist(body); - body.d.results.should.have.length(5); + body.d.results.should.have.length(5); - done(); + done(); + }); }); - }); }); -describe("Bing Images", function(){ +describe("Bing Images", function () { - this.timeout(1000 * 10); + this.timeout(1000 * 10); - it('finds images with specific options', function(done){ - Bing.images('pizza', { - top: 3, - adult: 'Off', - imagefilters: { size: 'small', color: 'monochrome' } - }, function(err, res, body){ - should.not.exist(err); - should.exist(res); - should.exist(body); + it('finds images with specific options', function (done) { + Bing.images('pizza', { + top: 3, + adult: 'Off', + imagefilters: { + size: 'small', + color: 'monochrome' + } + }, function (err, res, body) { + should.not.exist(err); + should.exist(res); + should.exist(body); - body.d.results.should.have.length(3); + body.d.results.should.have.length(3); - done(); + done(); + }); }); - }); }); -describe("Bing News", function(){ +describe("Bing News", function () { - this.timeout(1000 * 10); + this.timeout(1000 * 10); - it('finds news with specific options', function(done){ + it('finds news with specific options', function (done) { - Bing.news('ps4', { - top: 10, - skip: 1, - newsortby: 'Date' - }, function(err, res, body){ - //TODO try unaccepted options like imagefilters + Bing.news('ps4', { + top: 10, + skip: 1, + newsortby: 'Date' + }, function (err, res, body) { + //TODO try unaccepted options like imagefilters - should.not.exist(err); - should.exist(res); - should.exist(body); + should.not.exist(err); + should.exist(res); + should.exist(body); - body.d.results.should.have.length(10); + body.d.results.should.have.length(10); - done(); + done(); + }); }); - }); }); -describe("Bing Video", function(){ +describe("Bing Video", function () { - this.timeout(1000 * 10); + this.timeout(1000 * 10); - it('finds videos with specific options', function(done){ + it('finds videos with specific options', function (done) { - Bing.video('monkey vs frog', { - top: 10 - }, function(err, res, body){ - should.not.exist(err); - should.exist(res); - should.exist(body); + Bing.video('monkey vs frog', { + top: 10 + }, function (err, res, body) { + should.not.exist(err); + should.exist(res); + should.exist(body); - body.d.results.should.have.length(10); + body.d.results.should.have.length(10); - //TODO try here unaccepted options like imagefilters + //TODO try here unaccepted options like imagefilters - done(); + done(); + }); }); - }); });