From 5a8dcf8d59dd7f13e612cf13089582ae97a4f064 Mon Sep 17 00:00:00 2001 From: noodlefrenzy Date: Mon, 29 Sep 2014 08:12:08 -0700 Subject: [PATCH 1/2] Adding images vertical, some refactoring. Adding Gruntfile for jshint, jsdoc, mocha. Adding basic mocha test for sunny-day case. --- Gruntfile.js | 33 ++++++++++++++ lib/bing.js | 120 +++++++++++++++++++++++++++++++++------------------ package.json | 11 ++++- test/test.js | 73 +++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 42 deletions(-) create mode 100644 Gruntfile.js create mode 100644 test/test.js diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..008716f --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,33 @@ +module.exports = function(grunt) { + grunt.initConfig({ + simplemocha: { + options: { + globals: ['should'], + timeout: 3000, + ignoreLeaks: false, + ui: 'bdd', + reporter: 'list' + }, + all: { src: ['test/**/*.js'] } + }, + + jshint: { + all: [ 'Gruntfile.js', 'index.js', 'lib/**/*.js', 'test/**/*.js'] + }, + + jsdoc: { + all: { + src: ['index.js', 'lib/**/*.js'], + dest: 'doc' + } + } + }); + + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-simple-mocha'); + grunt.loadNpmTasks('grunt-jsdoc'); + + grunt.registerTask('test', ['simplemocha:all']); + grunt.registerTask('build', ['jshint', 'test']); + grunt.registerTask('default', ['build', 'jsdoc']); +}; diff --git a/lib/bing.js b/lib/bing.js index 1ce78f8..3d35016 100644 --- a/lib/bing.js +++ b/lib/bing.js @@ -9,7 +9,12 @@ var request = require('request'), _ = 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 ); @@ -17,7 +22,7 @@ var Bing = function( options ) { var defaults = { //Bing Search API URI - rootUri: "https://api.datamarket.azure.com/Bing/Search/Web", + rootUri: "https://api.datamarket.azure.com/Bing/Search/", //TODO move the web part, to choose also Images //Account Key @@ -31,49 +36,82 @@ var Bing = function( options ) { }; //merge options passed in with defaults - this.options = _.extend(defaults, options) -} + this.options = _.extend(defaults, options); + this.searchVertical = function(query, vertical, callback, options) { + if(typeof callback != 'function') { + throw "Error: Callback function required!"; + } + // TODO check if valid options + + var opts = this.options; + + if (options !== null) { + opts = _.extend(this.options, options); + } + + debugger; + var reqUri = opts.rootUri + vertical + + "?$format=json&" + + qs.stringify({ "Query": "'" + query + "'" }); + + 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){ + + // 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 {requestCallback} callback Callback called with (potentially json-parsed) response. + * @param {Object} options Options to command, allows overriding of rootUri, + * accKey (Bing API key), userAgent, reqTimeout + * @function + */ Bing.prototype.search = function(query, callback, options) { + this.searchVertical(query, "Web", callback, options); +}; - if(typeof callback != 'function') { - throw "Error: Callback function required!"; - } - - // TODO check if valid options - - var opts = this.options; - - if(options != null) { - opts = _.extend(this.options, options) - } - - var reqUri = opts.rootUri - + "?$format=json&" - + qs.stringify({ "Query": "'" + query + "'" }) - - 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){ - - // Parse body, if body - body = typeof body === 'string' - ? JSON.parse(body) - : body; - - callback(err, res, body); - }); +/** + * Performs a Bing search in the Images vertical. + * + * @param {String} query Query term to search for. + * @param {requestCallback} callback Callback called with (potentially json-parsed) response. + * @param {Object} options Options to command, allows overriding of rootUri, + * accKey (Bing API key), userAgent, reqTimeout + * @function + */ +Bing.prototype.images = function(query, callback, options) { + this.searchVertical(query, "Image", callback, options); }; module.exports = Bing; diff --git a/package.json b/package.json index 72821c3..5f674ea 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "author": "Mr. Goferito", "license": "MIT", - "repository" : { + "repository": { "type": "git", "url": "https://github.com/goferito/node-bing-api" }, @@ -15,5 +15,14 @@ "dependencies": { "request": "^2.44.0", "underscore": "^1.6.0" + }, + "devDependencies": { + "express": "^4.9.5", + "grunt": "^0.4.5", + "grunt-contrib-jshint": "^0.10.0", + "grunt-jsdoc": "^0.5.7", + "grunt-simple-mocha": "^0.4.0", + "mocha": "^1.21.4", + "should": "^4.0.4" } } diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..0b7a057 --- /dev/null +++ b/test/test.js @@ -0,0 +1,73 @@ +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" + } +}; + +var should = require('should'), + express = require('express'), + http = require('http'), + request = require('request'), + bing = require('../lib/bing'); + +describe('Bing', function() { + 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(); + } + }]); + }); + + 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)); + }); + 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(); + }); + }); +}); \ No newline at end of file From 42cfdfeb903b17c93016c32e070680f77e0e9ba2 Mon Sep 17 00:00:00 2001 From: noodlefrenzy Date: Mon, 29 Sep 2014 08:18:59 -0700 Subject: [PATCH 2/2] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5f674ea..e4b3ec9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-bing-api", - "version": "0.1.2", + "version": "0.1.3", "description": "Node.js module for the Azure Bing Search API", "main": "index.js", "author": "Mr. Goferito",