From 79098f0c932d84d8a1dcdf333f13b5c3fb5cb0b4 Mon Sep 17 00:00:00 2001 From: goferito Date: Sun, 24 May 2015 00:50:48 +0200 Subject: [PATCH] Some refactoring --- lib/bing.js | 201 +++++++++++++++++++++++++------------------- test/basic.js | 155 ++++++++++++++++++---------------- test/integration.js | 158 ++++++++++++++++++---------------- 3 files changed, 282 insertions(+), 232 deletions(-) diff --git a/lib/bing.js b/lib/bing.js index 7529183..9414b9f 100644 --- a/lib/bing.js +++ b/lib/bing.js @@ -16,81 +16,94 @@ var request = require('request'), */ var Bing = function (options) { - if (!(this instanceof Bing)) return new Bing(options); + if (!(this instanceof Bing)) return new Bing(options); - var defaults = { + var defaults = { - //Bing Search API URI - rootUri: "https://api.datamarket.azure.com/Bing/Search/v1/", + //Bing Search API URI + rootUri: "https://api.datamarket.azure.com/Bing/Search/v1/", - //Account Key - accKey: null, + //Account Key + accKey: null, - //Bing UserAgent - userAgent: 'Bing Search Client for Node.js', + //Bing UserAgent + userAgent: 'Bing Search Client for Node.js', - //Request Timeout - reqTimeout: 5000, + //Request Timeout + reqTimeout: 5000, - // Number of results (limited to 50 by API) - top: 50, + // Number of results (limited to 50 by API) + top: 50, - // Number of skipped results (pagination) - skip: 0 + // Number of skipped results (pagination) + skip: 0 - }; + }; - //merge options passed in with defaults - this.options = _.extend(defaults, options); + //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!"; - } + this.searchVertical = function (query, vertical, options, callback) { - // Create a copy of the options, to avoid permanent overwrites - var opts = JSON.parse(JSON.stringify(this.options)); + if (typeof options === 'function') { + callback = options; + } + if (typeof callback != 'function') { + throw "Error: Callback function required!"; + } - if (typeof options === 'object') { - _.extend(opts, options); - } + // Create a copy of the options, to avoid permanent overwrites + var opts = JSON.parse(JSON.stringify(this.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 + "'" - }) : ''); + if (typeof options === 'object') { + _.extend(opts, options); + } - request({ - uri: reqUri, - method: opts.method || "GET", - headers: { - "User-Agent": opts.userAgent - }, - auth: { - user: opts.accKey, - pass: opts.accKey - }, - timeout: opts.reqTimeout + 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 + "'" }) + : ''); - }, function (err, res, body) { + request({ + uri: reqUri, + method: opts.method || "GET", + headers: { + "User-Agent": opts.userAgent + }, + auth: { + user: opts.accKey, + pass: opts.accKey + }, + timeout: opts.reqTimeout - if (res && res.statusCode !== 200) { - err = new Error(body); - } else { + }, function (err, res, body) { - // Parse body, if body - body = typeof body === 'string' ? JSON.parse(body) : body; - } + if (res && res.statusCode !== 200) { + err = new Error(body); + } else { - callback(err, res, body); - }); - }; + // Parse body, if body + body = typeof body === 'string' ? JSON.parse(body) : body; + } + + callback(err, res, body); + }); + }; }; @@ -118,7 +131,7 @@ var Bing = function (options) { * @function */ Bing.prototype.web = function (query, options, callback) { - this.searchVertical(query, "Web", options, callback); + this.searchVertical(query, "Web", options, callback); }; // Alias Bing.search to Bing.web @@ -140,7 +153,7 @@ Bing.prototype.search = Bing.prototype.web; * @function */ Bing.prototype.composite = function (query, options, callback) { - this.searchVertical(query, "Composite", options, callback); + this.searchVertical(query, "Composite", options, callback); }; /** @@ -157,7 +170,7 @@ Bing.prototype.composite = function (query, options, callback) { * @function */ Bing.prototype.news = function (query, options, callback) { - this.searchVertical(query, "News", options, callback); + this.searchVertical(query, "News", options, callback); }; /** @@ -174,18 +187,21 @@ Bing.prototype.news = function (query, options, callback) { * @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); + if (options + && typeof options === 'object' + && options.videofilters + && typeof options.videofilters === 'object') { + + var filterQuery = Object.keys(options.videofilters) + .map(function(key){ + return capitalise(key) + ':' + + capitalise(options.videofilters[key]); + }) + .join('+'); + + options.videofilters = filterQuery; + } + this.searchVertical(query, "Video", options, callback); }; @@ -205,22 +221,35 @@ Bing.prototype.video = function (query, options, callback) { * @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); + if (options + && typeof options === 'object' + && options.imagefilters + && typeof options.imagefilters === 'object') { + + var filterQuery = Object.keys(options.imagefilters) + .map(function(key){ + return capitalise(key) + ':' + + capitalise(options.imagefilters[key]); + }) + .join('+'); + + options.imagefilters = filterQuery; + } + this.searchVertical(query, "Image", options, callback); }; -function capitalizeFirstLetter(s) { - return s.charAt(0).toUpperCase() + s.slice(1); + +/** + * Capitalises the first word of the passed string + * + * @param {String} s String to be capitalised + * + * @funtion + */ +function capitalise(s) { + return s.charAt(0).toUpperCase() + s.slice(1); } + module.exports = Bing; + diff --git a/test/basic.js b/test/basic.js index cd8e0ea..485a8e8 100644 --- a/test/basic.js +++ b/test/basic.js @@ -1,28 +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'), @@ -32,62 +32,69 @@ var should = require('should'), bing = require('../lib/bing'); describe('Bing', function () { - var server; - var app; - var port = 4321; + var server; + var app; + var port = 4321; - before(function (done) { - app = express(); - server = http.createServer(app); - server.listen.apply(server, [port, - function (err, result) { - if (err) { - done(err); - } else { - done(); - } - } - ]); + before(function (done) { + app = express(); + server = http.createServer(app); + server.listen.apply(server, [port, + function (err, result) { + if (err) { + done(err); + } else { + done(); + } + } + ]); + }); + + after(function (done) { + server.close(); + app = null; + server = null; + done(); + }); + + it('should cope with valid responses', function (done) { + + app.get('/hello/Web', function (req, res) { + res.status(200).send(JSON.stringify(validWebResponse)); }); - after(function (done) { - server.close(); - app = null; - server = null; - done(); + var bingClient = bing({ + rootUri: 'http://localhost:' + port + '/hello/', + accKey: '123' }); - 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' - }); - bingClient.search('xbox', function (error, response, body) { - response.statusCode.should.eql(200); - body.should.eql(validWebResponse); - done(); - }); + bingClient.search('xbox', function (error, response, body) { + response.statusCode.should.eql(200); + body.should.eql(validWebResponse); + done(); + }); + }); + + it('should cope with errors', function (done) { + + // No actual data on what the failure looks like. + var failure = { + message: 'Failed request' + }; + + app.get('/hello/Image', function (req, res) { + res.status(500).send(failure); + }); + + var bingClient = bing({ + rootUri: 'http://localhost:' + port + '/hello/', + accKey: '123' }); - it('should cope with errors', function (done) { - // No actual data on what the failure looks like. - var failure = { - message: 'Failed request' - }; - app.get('/hello/Image', function (req, res) { - res.status(500).send(failure); - }); - 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)); - done(); - }); + bingClient.images('xbox', function (error, response, body) { + response.statusCode.should.eql(500); + body.should.eql(JSON.stringify(failure)); + done(); }); + }); }); diff --git a/test/integration.js b/test/integration.js index 1c01717..a88f4bb 100644 --- a/test/integration.js +++ b/test/integration.js @@ -3,131 +3,145 @@ // should still run the basic tests; thus throwing an exception must // be avoided. try { - var accKey = require('./secrets').accKey; + var accKey = require('./secrets').accKey; } catch (e) { - console.log(e); + console.log(e); } if (!accKey) { - return console.error("Need to include an access key in your secrets.js"); + return console.error("Need to include an access key in your secrets.js"); } -var Bing = require('../')({ - accKey: accKey -}); -var should = require('should'); +var Bing = require('../')({ accKey: accKey }) + , should = require('should') 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) { - body.d.results.should.have.length(5); + should.not.exist(err); + should.exist(res); + should.exist(body); - done(); - }); + body.d.results.should.have.length(5); + + done(); }); + }); }); 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) { - body.d.results.should.have.length(3); + should.not.exist(err); + should.exist(res); + should.exist(body); - done(); - }); + body.d.results.should.have.length(3); + + done(); }); + }); }); 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) { - should.not.exist(err); - should.exist(res); - should.exist(body); + //TODO try unaccepted options like imagefilters - body.d.results.should.have.length(10); + should.not.exist(err); + should.exist(res); + should.exist(body); - done(); - }); + body.d.results.should.have.length(10); + + done(); }); + }); }); 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, + videofilters: { + duration: 'short', + resolution: 'high' + } + }, + function (err, res, body) { - body.d.results.should.have.length(10); + should.not.exist(err); + should.exist(res); + should.exist(body); - //TODO try here unaccepted options like imagefilters + body.d.results.should.have.length(10); - done(); - }); + //TODO try here unaccepted options like imagefilters + + done(); }); - + }); }); +