From 343756b7d66ceb99e4a8fffecc4573852402a1a7 Mon Sep 17 00:00:00 2001 From: pat310 Date: Sat, 22 Oct 2016 14:54:58 -0400 Subject: [PATCH 1/9] adding an optional parameter 'timePeriod' to 'trendData' method --- examples.js | 13 +++++++++++-- src/resources/timePeriodConverter.js | 18 ++++++++++++++++++ src/utils/trendData.js | 9 +++++---- 3 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 src/resources/timePeriodConverter.js diff --git a/examples.js b/examples.js index 7ccccc9..6730a03 100644 --- a/examples.js +++ b/examples.js @@ -7,7 +7,7 @@ var util = require('util'); /* ~=~=~=~=~=~=~=~=~=~= EXAMPLE 1 =~=~=~=~=~=~=~=~=~=~ */ /* ~=~=~=~=~=~=~=~=~=~= trendData =~=~=~=~=~=~=~=~=~=~ */ // // Parameters: array of key words (required) -// // optionally as the first argument pass an object: {keywords: ['dog']} +// // optionally as the first argument pass an object instead: {keywords: ['dog']} // googleTrends.trendData({keywords: 'OJ Simpson'}) // .then(function(trendData){ // console.log('here are the results', util.inspect(trendData, {showHidden: false, depth: null})); @@ -17,7 +17,7 @@ var util = require('util'); // return err; // }); -// Trend data example with multiple keywords +// // Trend data example with multiple keywords // googleTrends.trendData({keywords: ['OJ Simpson', 'Michael Phelps']}) // .then(function(trendData){ // console.log('here are the results', util.inspect(trendData, {showHidden: false, depth: null})); @@ -27,6 +27,15 @@ var util = require('util'); // return err; // }); +// // Trend data example with a time period provided (timePeriod is an optional parameter) +// googleTrends.trendData({keywords: 'OJ Simpson', timePeriod: {type: 'month', value: 1}}) +// .then(function(trendData){ +// console.log('here are the results', util.inspect(trendData, {showHidden: false, depth: null})); +// }) +// .catch(function(err){ +// console.log("there was an error", err); +// return err; +// }); /* ~=~=~=~=~=~=~=~=~=~= EXAMPLE 2 =~=~=~=~=~=~=~=~=~=~ */ diff --git a/src/resources/timePeriodConverter.js b/src/resources/timePeriodConverter.js new file mode 100644 index 0000000..8b9547b --- /dev/null +++ b/src/resources/timePeriodConverter.js @@ -0,0 +1,18 @@ +'use strict'; + +module.exports = function(timePeriodObj){ + if(!timePeriodObj) return ''; + if(typeof timePeriodObj !== 'object') return new Error('timePeriod must be an object of type {type: enum, value: number}'); + + const enumTypes = { + hour: ['now', 'H'], + day: ['now', 'd'], + month: ['today', 'm'], + year: ['today', 'm'] + }; + + if(typeof timePeriodObj.type !== 'string' || !enumTypes[timePeriodObj.type.toLowerCase()]) return new Error('type must be one of the specified enumerated types'); + if(!timePeriodObj.value || typeof timePeriodObj.value !== 'number' ) return new Error('timePeriod value must be a number'); + + return `date=${enumTypes[timePeriodObj.type.toLowerCase()][0]} ${timePeriodObj.type.toLowerCase() === 'year' ? Math.round(timePeriodObj.value) * 12 : Math.round(timePeriodObj.value)}-${enumTypes[timePeriodObj.type.toLowerCase()][1]}`; +} \ No newline at end of file diff --git a/src/utils/trendData.js b/src/utils/trendData.js index 2e80fc9..c04bc5d 100644 --- a/src/utils/trendData.js +++ b/src/utils/trendData.js @@ -6,14 +6,15 @@ var checkErrors = require(__dirname + '/../resources/errorHandling.js'); var parseJSON = require(__dirname + '/../resources/htmlParser.js').parseJSON; var groupKeywords = require(__dirname + '/../resources/trendDataHelper.js').groupKeywords; var reduceArrayDimensions = require(__dirname + '/../resources/trendDataHelper.js').reduceArrayDimensions; +var timePeriodConverter = require(__dirname + '/../resources/timePeriodConverter.js'); -module.exports = function request(keywords, cbFunc){ +module.exports = function request(keywords, timePeriod, cbFunc){ var obj = createObj(arguments, request); var error = checkErrors(obj); if(error instanceof Error) return Promise.reject(obj.cbFunc(error)); - return Promise.all(promiseArr(obj.keywords)) + return Promise.all(promiseArr(obj.keywords, timePeriodConverter(obj.timePeriod))) .then(function(results){ return obj.cbFunc(null, reduceArrayDimensions(results)); }) @@ -22,9 +23,9 @@ module.exports = function request(keywords, cbFunc){ }); }; -function promiseArr(keywords){ +function promiseArr(keywords, timePeriod){ return groupKeywords(keywords).map(function(keyword, index, arr){ - return rp(`http://www.google.com/trends/fetchComponent?q=${keyword}&cid=TIMESERIES_GRAPH_0&export=3`) + return rp(`http://www.google.com/trends/fetchComponent?q=${keyword}&cid=TIMESERIES_GRAPH_0&export=3&${timePeriod}`) .then(function(htmlString){ return parseJSON(htmlString, arr[index].split(',')); }); From 4b0d315f666fda5d1ba3c34719fb3353cb003eeb Mon Sep 17 00:00:00 2001 From: pat310 Date: Sat, 22 Oct 2016 15:10:18 -0400 Subject: [PATCH 2/9] adding test for timePeriodConverter --- test/resources/index.js | 3 +- test/resources/timePeriodConverter.test.js | 45 +++++++++++++++++++ ...dDataHelper.js => trendDataHelper.test.js} | 4 +- 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 test/resources/timePeriodConverter.test.js rename test/resources/{trendDataHelper.js => trendDataHelper.test.js} (74%) diff --git a/test/resources/index.js b/test/resources/index.js index 9d1a445..6808aed 100644 --- a/test/resources/index.js +++ b/test/resources/index.js @@ -6,5 +6,6 @@ module.exports = { dateValidate: require(__dirname + '/dateValidate.test.js'), errorHandling: require(__dirname + '/errorHandling.test.js'), htmlParser: require(__dirname + '/htmlParser.test.js'), - trendDataHelper: require(__dirname + '/trendDataHelper.js') + trendDataHelper: require(__dirname + '/trendDataHelper.test.js'), + timePeriodConverter: require(__dirname + '/timePeriodConverter.test.js') }; \ No newline at end of file diff --git a/test/resources/timePeriodConverter.test.js b/test/resources/timePeriodConverter.test.js new file mode 100644 index 0000000..c0faedb --- /dev/null +++ b/test/resources/timePeriodConverter.test.js @@ -0,0 +1,45 @@ +'use strict'; +var fs = require('fs'); + +var chai = require('chai'); +var chaiAsPromised = require('chai-as-promised'); +chai.use(chaiAsPromised); +var expect = chai.expect; +var assert = chai.assert; + +var timePeriodConverter = require(__dirname + '/../../lib/resources/timePeriodConverter.js'); + +module.exports = +describe('timePeriodConverter.test.js', function(){ + + describe('timePeriodConverter', function(){ + it('exists', function(){ + assert.isFunction(timePeriodConverter); + }); + it('returns empty string if receives undefined value', function(){ + expect(timePeriodConverter(undefined)).to.deep.equal(''); + }); + it('returns an error if it receives anything but an object', function(){ + expect(timePeriodConverter('5-years')).to.be.an('error').and.have.property('message', 'timePeriod must be an object of type {type: enum, value: number}'); + expect(timePeriodConverter(5)).to.be.an('error').and.have.property('message', 'timePeriod must be an object of type {type: enum, value: number}'); + }); + it('returns an error if type is not one of the enumerated values', function(){ + expect(timePeriodConverter({type: 5, value: 5})).to.be.an('error').and.have.property('message', 'type must be one of the specified enumerated types'); + expect(timePeriodConverter({type: 'hours', value: 5})).to.be.an('error').and.have.property('message', 'type must be one of the specified enumerated types'); + expect(timePeriodConverter({value: 5})).to.be.an('error').and.have.property('message', 'type must be one of the specified enumerated types'); + }); + it('returns an error if value is not a number', function(){ + expect(timePeriodConverter({type: 'hour', value: 'string'})).to.be.an('error').and.have.property('message', 'timePeriod value must be a number'); + expect(timePeriodConverter({type: 'hour', value: NaN})).to.be.an('error').and.have.property('message', 'timePeriod value must be a number'); + expect(timePeriodConverter({type: 'hour'})).to.be.an('error').and.have.property('message', 'timePeriod value must be a number'); + }); + it('returns properly formatted string', function(){ + expect(timePeriodConverter({type: 'HoUr', value: 5})).to.deep.equal('date=now 5-H'); + expect(timePeriodConverter({type: 'hour', value: 5})).to.deep.equal('date=now 5-H'); + expect(timePeriodConverter({type: 'day', value: 5})).to.deep.equal('date=now 5-d'); + expect(timePeriodConverter({type: 'month', value: 5})).to.deep.equal('date=today 5-m'); + expect(timePeriodConverter({type: 'year', value: 5})).to.deep.equal('date=today 60-m'); + }); + }); + +}); \ No newline at end of file diff --git a/test/resources/trendDataHelper.js b/test/resources/trendDataHelper.test.js similarity index 74% rename from test/resources/trendDataHelper.js rename to test/resources/trendDataHelper.test.js index 91e5394..cb25e00 100644 --- a/test/resources/trendDataHelper.js +++ b/test/resources/trendDataHelper.test.js @@ -20,8 +20,8 @@ describe('trendDataHelper.test.js', function(){ expect(trendDataHelper.groupKeywords(['dog', 'cat'])).to.deep.equal(['dog,cat']); }); it('correctly groups an array greater limit of 5', function(){ - expect(trendDataHelper.groupKeywords(['dog', 'cat', 'giraffe', 'bear', 'sloth', 'pig'])).to.deep.equal(['dog,cat,giraffe,bear,sloth', 'pig']); - expect(trendDataHelper.groupKeywords(['dog', 'cat', 'giraffe', 'bear', 'sloth', 'pig', 'donkey', 'horse', 'crane', 'wolf', 'lion'])).to.deep.equal(['dog,cat,giraffe,bear,sloth', 'pig,donkey,horse,crane,wolf', 'lion']); + expect(trendDataHelper.groupKeywords(['dog', 'cat', 'giraffe', 'bear', 'sloth', 'pig'])).to.deep.equal(['dog,cat,giraffe,bear,sloth', 'pig']); + expect(trendDataHelper.groupKeywords(['dog', 'cat', 'giraffe', 'bear', 'sloth', 'pig', 'donkey', 'horse', 'crane', 'wolf', 'lion'])).to.deep.equal(['dog,cat,giraffe,bear,sloth', 'pig,donkey,horse,crane,wolf', 'lion']); }); }); From 6b370c451a857e4570e766f633cb0ca389ef3ffa Mon Sep 17 00:00:00 2001 From: pat310 Date: Sat, 22 Oct 2016 15:27:34 -0400 Subject: [PATCH 3/9] adding test for trendData checking timePeriod object --- src/resources/callbacks.js | 2 +- test/utils/trendData.test.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/resources/callbacks.js b/src/resources/callbacks.js index b10f007..10c2c06 100644 --- a/src/resources/callbacks.js +++ b/src/resources/callbacks.js @@ -20,7 +20,7 @@ function parseArguments(args, func){ var parameters = getParamNames(func); var returnObj = parameters.reduce(function(acc, curr, index){ - if((typeof args[index] !== 'object' || Array.isArray(args[index])) && curr !== 'cbFunc') acc[curr] = typeof args[index] !== 'function' ? args[index] : undefined; + if((curr === 'timePeriod' || typeof args[index] !== 'object' || Array.isArray(args[index])) && curr !== 'cbFunc') acc[curr] = typeof args[index] !== 'function' ? args[index] : undefined; if(typeof args[index] === 'function') acc.cbFunc = args[index]; return acc; }, {}); diff --git a/test/utils/trendData.test.js b/test/utils/trendData.test.js index a4c139b..fe9a3ef 100644 --- a/test/utils/trendData.test.js +++ b/test/utils/trendData.test.js @@ -12,7 +12,13 @@ describe('trendData.js', function(){ it('should reject if no keyword is provided', function(){ return trendData().should.be.rejectedWith('Keywords must be provided'); }); + it('should reject if timePeriod is not provided correctly', function(){ + return trendData('swimming', {type: 'something', value: 5}).should.be.rejectedWith('type must be one of the specified enumerated types'); + }); it('should run analysis for keywords', function(){ return trendData('swimming').should.be.resolved; }); + it('should run analysis for keywords with timePeriod object', function(){ + return trendData('swimming', {type: 'hour', value: 5}).should.be.resolved; + }); }); \ No newline at end of file From cc599182616b9aa37f3aafe21d89d2849083f32b Mon Sep 17 00:00:00 2001 From: pat310 Date: Sat, 22 Oct 2016 17:00:20 -0400 Subject: [PATCH 4/9] selecting value f from date parser --- CHANGES.md | 8 ++ README.md | 194 +++++++++++++++++++++--------------- examples.js | 4 +- src/resources/htmlParser.js | 2 +- 4 files changed, 122 insertions(+), 86 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index da363cd..27b461b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,11 @@ +## [v2.1.0] +> Oct 22, 2016 + +- `trendData` now accepts an optional `timePeriod` object that will return trend data based on a provided time period ([#33]) + +[v2.1.0]: https://github.com/pat310/google-trends-api/compare/v2.0.0...v2.1.0 +[#33]: https://github.com/pat310/google-trends-api/pull/33 + ## [v2.0.0] > Oct 22, 2016 diff --git a/README.md b/README.md index 4e00649..d354915 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,11 @@ var options = { geo: 'country name', date: 'yyyymm', keywords: ['some', 'list', 'of', 'keywords'], - category: 'some category' + category: 'some category', + timePeriod: { + type: enumerated string 'hour', 'day', 'month', or 'year' + value: number + } } googleTrends.apiMethod(options) @@ -122,7 +126,7 @@ The examples shown for each API method can be run by changing into the home `goo ### API Methods The following API methods are available: -* [trendData](#trenddata): returns the historical trend data to a provided keyword or an array of keywords. +* [trendData](#trenddata): returns the historical trend data to a provided keyword or an array of keywords - optionally accepts a `timePeriod` object * [topRelated](#toprelated): returns the top related keywords to a provided keyword or an array of keywords along with it's percentage of correlation. * [hotTrends](#hottrends): returns the current top 20 trending searches for a given location. * [hotTrendsDetail](#hottrendsdetail): same as the [hotTrends](#hottrends) results except with more detail such as links, publication date, approximate traffic, etc. @@ -145,12 +149,13 @@ For each of the API methods, rather than providing the parameters to the functio *Returns the historical trend data to a provided keyword or an array of keywords.* #####Syntax -`googleTrends.trendData(['keywords'])` +`googleTrends.trendData(['keywords'], {type: 'string', value: number})` * `['keywords']` - either an array of keywords as strings or a string with one keyword. If keywords is an array, the results will be returned in an array of the same order as the input. Entering a keyword is **required**. +* `{type: 'string', value: number}` - the `timePeriod` object that must be formatted with keys `type` (which is an enumerated string of either 'hour', 'day', 'month', or 'year') and `value` (which is a number). Entering a `timePeriod` is optional. If no `timePeriod` object is provided, by default `trendData` will return all past trend data available. #####Example -The following example provides the historical trend data for 'OJ Simpson'. Optionally, the input could have been provided as `googleTrends.trendData({keywords: 'OJ Simpson'})`. Any other keys provided in the object will be ignore. +The following example provides the historical trend data for 'OJ Simpson'. Optionally, the input could have been provided as `googleTrends.trendData({keywords: 'OJ Simpson'})`. ######Input ```js @@ -165,43 +170,27 @@ googleTrends.trendData('OJ Simpson') ######Output ```js -[ - { - "query": "oj simpson", - "values": [{ - "date": "Thu, 01 Jan 2004 06:00:00 GMT", - "value": 4 - }, { - "date": "Sun, 01 Feb 2004 06:00:00 GMT", - "value": 3 - }, { - "date": "Mon, 01 Mar 2004 06:00:00 GMT", - "value": 3 - }, { - "date": "Thu, 01 Apr 2004 06:00:00 GMT", - "value": 3 - }, { - "date": "Sat, 01 May 2004 05:00:00 GMT", - "value": 4 - }, { - "date": "Tue, 01 Jun 2004 05:00:00 GMT", - "value": 7 - }, { - "date": "Thu, 01 Jul 2004 05:00:00 GMT", - "value": 2 - }, { - "date": "Sun, 01 Aug 2004 05:00:00 GMT", - "value": 2 - }, - ... - }, { - "date": "Mon, 01 Aug 2016 05:00:00 GMT", - "value": 9 - } - } -] +[ { query: 'oj simpson', + values: + [ { date: '2003-12-01T05:00:00.000Z', value: 4 }, + { date: '2004-01-01T05:00:00.000Z', value: 4 }, + { date: '2004-02-01T05:00:00.000Z', value: 3 }, + { date: '2004-03-01T05:00:00.000Z', value: 4 }, + { date: '2004-04-01T05:00:00.000Z', value: 5 }, + { date: '2004-05-01T04:00:00.000Z', value: 7 }, + { date: '2004-06-01T04:00:00.000Z', value: 2 }, + { date: '2004-07-01T04:00:00.000Z', value: 2 }, + { date: '2004-08-01T04:00:00.000Z', value: 2 }, + { date: '2004-09-01T04:00:00.000Z', value: 4 }, + { date: '2004-10-01T04:00:00.000Z', value: 4 }, + { date: '2004-11-01T05:00:00.000Z', value: 3 }, + { date: '2004-12-01T05:00:00.000Z', value: 3 }, + ... more items ] } ] ``` +#####Example +The following example provides the historical trend data for 'swimming' and the 'olympics'. Optionally, the input could have been provided as `googleTrends.trendData({keywords: ['swimming', 'olympics']})`. + ######Input ```js googleTrends.trendData(['swimming', 'olympics']) @@ -215,50 +204,89 @@ googleTrends.trendData(['swimming', 'olympics']) ######Output ```js -[ - { - "query": "swimming", - "values": [{ - "date": "Thu, 01 Jan 2004 06:00:00 GMT", - "value": 5 - }, { - "date": "Sun, 01 Feb 2004 06:00:00 GMT", - "value": 5 - }, { - "date": "Mon, 01 Mar 2004 06:00:00 GMT", - "value": 5 - }, { - "date": "Thu, 01 Apr 2004 06:00:00 GMT", - "value": 5 - }, { - ... - }, { - "date": "Mon, 01 Aug 2016 05:00:00 GMT", - "value": 10 - }] - }, - { - "query": "olympics", - "values": [{ - "date": "Thu, 01 Jan 2004 06:00:00 GMT", - "value": 2 - }, { - "date": "Sun, 01 Feb 2004 06:00:00 GMT", - "value": 3 - }, { - "date": "Mon, 01 Mar 2004 06:00:00 GMT", - "value": 3 - }, { - "date": "Thu, 01 Apr 2004 06:00:00 GMT", - "value": 3 - }, { - ... - }, { - "date": "Mon, 01 Aug 2016 05:00:00 GMT", - "value": 100 - }] - } -] +[ { query: 'swimming', + values: + [ { date: '2003-12-01T05:00:00.000Z', value: 7 }, + { date: '2004-01-01T05:00:00.000Z', value: 7 }, + { date: '2004-02-01T05:00:00.000Z', value: 7 }, + { date: '2004-03-01T05:00:00.000Z', value: 7 }, + { date: '2004-04-01T05:00:00.000Z', value: 8 }, + { date: '2004-05-01T04:00:00.000Z', value: 9 }, + { date: '2004-06-01T04:00:00.000Z', value: 10 }, + { date: '2004-07-01T04:00:00.000Z', value: 11 }, + { date: '2004-08-01T04:00:00.000Z', value: 7 }, + { date: '2004-09-01T04:00:00.000Z', value: 6 }, + { date: '2004-10-01T04:00:00.000Z', value: 5 }, + { date: '2004-11-01T05:00:00.000Z', value: 4 }, + { date: '2004-12-01T05:00:00.000Z', value: 6 }, + { date: '2005-01-01T05:00:00.000Z', value: 6 }, + { date: '2005-02-01T05:00:00.000Z', value: 6 }, + ... more items ] }, + { query: 'olympics', + values: + [ { date: '2003-12-01T05:00:00.000Z', value: 3 }, + { date: '2004-01-01T05:00:00.000Z', value: 4 }, + { date: '2004-02-01T05:00:00.000Z', value: 4 }, + { date: '2004-03-01T05:00:00.000Z', value: 4 }, + { date: '2004-04-01T05:00:00.000Z', value: 5 }, + { date: '2004-05-01T04:00:00.000Z', value: 5 }, + { date: '2004-06-01T04:00:00.000Z', value: 8 }, + { date: '2004-07-01T04:00:00.000Z', value: 66 }, + { date: '2004-08-01T04:00:00.000Z', value: 8 }, + { date: '2004-09-01T04:00:00.000Z', value: 3 }, + { date: '2004-10-01T04:00:00.000Z', value: 3 }, + ... more items ] } ] +``` + +#####Example +The following example provides the historical trend data for 'OJ Simpson' for the past 5 days. Optionally, the input could have been provided as `googleTrends.trendData('OJ Simpson', {type: 'day', value: 5})`. + +######Input +```js +googleTrends.trendData({keywords: 'Oj Simpson', timePeriod: {type: 'day', value: 5}}) +.then(function(results){ + console.log(results); +}) +.catch(function(err){ + console.error(err); +}); +``` + +######Output +**Note: Query was conducted on 10/22 so 5 days back leads to results starting at 10/17** +```js +[ { query: 'oj simpson', + values: + [ { date: '2016-10-17T21:00:00.000Z', value: 20 }, + { date: '2016-10-17T22:00:00.000Z', value: 18 }, + { date: '2016-10-17T23:00:00.000Z', value: 17 }, + { date: '2016-10-18T00:00:00.000Z', value: 23 }, + { date: '2016-10-18T01:00:00.000Z', value: 20 }, + { date: '2016-10-18T02:00:00.000Z', value: 22 }, + { date: '2016-10-18T03:00:00.000Z', value: 19 }, + { date: '2016-10-18T04:00:00.000Z', value: 15 }, + { date: '2016-10-18T05:00:00.000Z', value: 11 }, + { date: '2016-10-18T06:00:00.000Z', value: 8 }, + { date: '2016-10-18T07:00:00.000Z', value: 7 }, + { date: '2016-10-18T08:00:00.000Z', value: 7 }, + { date: '2016-10-18T09:00:00.000Z', value: 6 }, + { date: '2016-10-18T10:00:00.000Z', value: 7 }, + { date: '2016-10-18T11:00:00.000Z', value: 7 }, + { date: '2016-10-18T12:00:00.000Z', value: 10 }, + { date: '2016-10-18T13:00:00.000Z', value: 10 }, + { date: '2016-10-18T14:00:00.000Z', value: 10 }, + { date: '2016-10-18T15:00:00.000Z', value: 11 }, + { date: '2016-10-18T16:00:00.000Z', value: 13 }, + { date: '2016-10-18T17:00:00.000Z', value: 13 }, + { date: '2016-10-18T18:00:00.000Z', value: 18 }, + { date: '2016-10-18T19:00:00.000Z', value: 16 }, + { date: '2016-10-18T20:00:00.000Z', value: 16 }, + { date: '2016-10-18T21:00:00.000Z', value: 19 }, + { date: '2016-10-18T22:00:00.000Z', value: 33 }, + { date: '2016-10-18T23:00:00.000Z', value: 81 }, + { date: '2016-10-19T00:00:00.000Z', value: 100 }, + { date: '2016-10-19T01:00:00.000Z', value: 30 }, + ... more items ] } ] ``` [back to top](#introduction) diff --git a/examples.js b/examples.js index 6730a03..125431a 100644 --- a/examples.js +++ b/examples.js @@ -18,7 +18,7 @@ var util = require('util'); // }); // // Trend data example with multiple keywords -// googleTrends.trendData({keywords: ['OJ Simpson', 'Michael Phelps']}) +// googleTrends.trendData(['swimming', 'olympics']) // .then(function(trendData){ // console.log('here are the results', util.inspect(trendData, {showHidden: false, depth: null})); // }) @@ -28,7 +28,7 @@ var util = require('util'); // }); // // Trend data example with a time period provided (timePeriod is an optional parameter) -// googleTrends.trendData({keywords: 'OJ Simpson', timePeriod: {type: 'month', value: 1}}) +// googleTrends.trendData({keywords: 'OJ Simpson', timePeriod: {type: 'day', value: 5}}) // .then(function(trendData){ // console.log('here are the results', util.inspect(trendData, {showHidden: false, depth: null})); // }) diff --git a/src/resources/htmlParser.js b/src/resources/htmlParser.js index 9051a3c..623a364 100644 --- a/src/resources/htmlParser.js +++ b/src/resources/htmlParser.js @@ -52,7 +52,7 @@ function parseJSON(htmlString) { } for (let j = 0; j < parsedTrends.table.rows.length; j++) { var data = parsedTrends.table.rows[j].c, - date = data[0].v; + date = new Date(data[0].f); for (let k = 1; k < data.length; k++) { if (data[k]) { trendsData[k - 1].values.push({ From 432a17138c258ea4174e7500e807a0986b63a3fd Mon Sep 17 00:00:00 2001 From: pat310 Date: Sat, 22 Oct 2016 17:09:56 -0400 Subject: [PATCH 5/9] add error handling for timePeriod --- src/utils/trendData.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/trendData.js b/src/utils/trendData.js index c04bc5d..f8f51bc 100644 --- a/src/utils/trendData.js +++ b/src/utils/trendData.js @@ -13,6 +13,7 @@ module.exports = function request(keywords, timePeriod, cbFunc){ var error = checkErrors(obj); if(error instanceof Error) return Promise.reject(obj.cbFunc(error)); + if(timePeriodConverter(obj.timePeriod) instanceof Error) return Promise.reject(obj.cbFunc(timePeriodConverter(obj.timePeriod))); return Promise.all(promiseArr(obj.keywords, timePeriodConverter(obj.timePeriod))) .then(function(results){ From f2d54141d3961c9aaf176c47c2f2b5bde8287817 Mon Sep 17 00:00:00 2001 From: pat310 Date: Sat, 22 Oct 2016 17:14:57 -0400 Subject: [PATCH 6/9] moving error handling from trendData to errorHandling file --- src/resources/errorHandling.js | 3 ++- src/utils/trendData.js | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resources/errorHandling.js b/src/resources/errorHandling.js index 90ec5e8..c0a2886 100644 --- a/src/resources/errorHandling.js +++ b/src/resources/errorHandling.js @@ -2,7 +2,7 @@ const COUNTRY = require(__dirname + '/countryCodes.js'); const DATE = require(__dirname + '/dateValidate.js'); - +const timePeriodConverter = require(__dirname + '/../resources/timePeriodConverter.js'); function checkErrors(obj){ var keys = Object.keys(obj); @@ -20,6 +20,7 @@ function checkErrors(obj){ obj.countryDomain = COUNTRY.getDomain(obj.geo); obj.countryCode = COUNTRY.getCode(obj.geo); + if(obj.timePeriod && timePeriodConverter(obj.timePeriod) instanceof Error) return timePeriodConverter(obj.timePeriod); } function findKey(searchKey, keys){ diff --git a/src/utils/trendData.js b/src/utils/trendData.js index f8f51bc..c04bc5d 100644 --- a/src/utils/trendData.js +++ b/src/utils/trendData.js @@ -13,7 +13,6 @@ module.exports = function request(keywords, timePeriod, cbFunc){ var error = checkErrors(obj); if(error instanceof Error) return Promise.reject(obj.cbFunc(error)); - if(timePeriodConverter(obj.timePeriod) instanceof Error) return Promise.reject(obj.cbFunc(timePeriodConverter(obj.timePeriod))); return Promise.all(promiseArr(obj.keywords, timePeriodConverter(obj.timePeriod))) .then(function(results){ From a199e5f6b7b81de86678ab19ab3a4044092a32cd Mon Sep 17 00:00:00 2001 From: pat310 Date: Sat, 22 Oct 2016 17:23:58 -0400 Subject: [PATCH 7/9] adding timePeriod key to object creator --- src/resources/callbacks.js | 3 +++ src/resources/errorHandling.js | 2 +- src/utils/trendData.js | 3 +-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/resources/callbacks.js b/src/resources/callbacks.js index 10c2c06..0757668 100644 --- a/src/resources/callbacks.js +++ b/src/resources/callbacks.js @@ -1,4 +1,5 @@ 'use strict'; +var timePeriodConverter = require(__dirname + '/../resources/timePeriodConverter.js'); function generic(err, results){ if(err) return err; @@ -30,6 +31,8 @@ function parseArguments(args, func){ returnObj.cbFunc = typeof returnObj.cbFunc === "function" ? returnObj.cbFunc : generic; if(returnObj.keywords) returnObj.keywords = Array.isArray(returnObj.keywords) ? returnObj.keywords : [returnObj.keywords]; + + returnObj.timePeriod = timePeriodConverter(returnObj.timePeriod); return returnObj; } diff --git a/src/resources/errorHandling.js b/src/resources/errorHandling.js index c0a2886..04fd8e9 100644 --- a/src/resources/errorHandling.js +++ b/src/resources/errorHandling.js @@ -20,7 +20,7 @@ function checkErrors(obj){ obj.countryDomain = COUNTRY.getDomain(obj.geo); obj.countryCode = COUNTRY.getCode(obj.geo); - if(obj.timePeriod && timePeriodConverter(obj.timePeriod) instanceof Error) return timePeriodConverter(obj.timePeriod); + if(obj.timePeriod && obj.timePeriod instanceof Error) return obj.timePeriod; } function findKey(searchKey, keys){ diff --git a/src/utils/trendData.js b/src/utils/trendData.js index c04bc5d..cf663c1 100644 --- a/src/utils/trendData.js +++ b/src/utils/trendData.js @@ -6,7 +6,6 @@ var checkErrors = require(__dirname + '/../resources/errorHandling.js'); var parseJSON = require(__dirname + '/../resources/htmlParser.js').parseJSON; var groupKeywords = require(__dirname + '/../resources/trendDataHelper.js').groupKeywords; var reduceArrayDimensions = require(__dirname + '/../resources/trendDataHelper.js').reduceArrayDimensions; -var timePeriodConverter = require(__dirname + '/../resources/timePeriodConverter.js'); module.exports = function request(keywords, timePeriod, cbFunc){ var obj = createObj(arguments, request); @@ -14,7 +13,7 @@ module.exports = function request(keywords, timePeriod, cbFunc){ var error = checkErrors(obj); if(error instanceof Error) return Promise.reject(obj.cbFunc(error)); - return Promise.all(promiseArr(obj.keywords, timePeriodConverter(obj.timePeriod))) + return Promise.all(promiseArr(obj.keywords, obj.timePeriod)) .then(function(results){ return obj.cbFunc(null, reduceArrayDimensions(results)); }) From d829a10e603d1c6a844189885fa8ab2d6d44a008 Mon Sep 17 00:00:00 2001 From: pat310 Date: Sat, 22 Oct 2016 17:52:52 -0400 Subject: [PATCH 8/9] adding tests to increase code coverage --- README.md | 10 +++++----- package.json | 2 +- src/resources/errorHandling.js | 1 - test/utils/allTopCharts.test.js | 12 ++++++++++++ test/utils/categoryTopCharts.test.js | 15 +++++++++++++++ test/utils/hotTrends.test.js | 9 +++++++++ test/utils/hotTrendsDetail.test.js | 9 +++++++++ test/utils/topRelated.test.js | 9 +++++++++ 8 files changed, 60 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d354915..3e75269 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,10 @@ var options = { date: 'yyyymm', keywords: ['some', 'list', 'of', 'keywords'], category: 'some category', - timePeriod: { - type: enumerated string 'hour', 'day', 'month', or 'year' - value: number - } + timePeriod: { + type: enumerated string 'hour', 'day', 'month', or 'year' + value: number + } } googleTrends.apiMethod(options) @@ -654,7 +654,7 @@ The following example provides the top charts for actors in January 2016 in the ######Input ```js -googleTrends.categoryTopCharts({'actors', '201601', 'US'}) +googleTrends.categoryTopCharts('actors', '201601', 'US') .then(function(results){ console.log(results); }) diff --git a/package.json b/package.json index 1e5c0e4..4e257de 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "an API layer on top of google trends", "main": "index.js", "scripts": { - "test": "mocha", + "test": "mocha --timeout 15000", "compile": "./node_modules/.bin/babel --presets es2015 -d lib/ src/", "test-cov": "./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- -R spec ./test/*", "prepublish": "npm run compile", diff --git a/src/resources/errorHandling.js b/src/resources/errorHandling.js index 04fd8e9..dbc6429 100644 --- a/src/resources/errorHandling.js +++ b/src/resources/errorHandling.js @@ -2,7 +2,6 @@ const COUNTRY = require(__dirname + '/countryCodes.js'); const DATE = require(__dirname + '/dateValidate.js'); -const timePeriodConverter = require(__dirname + '/../resources/timePeriodConverter.js'); function checkErrors(obj){ var keys = Object.keys(obj); diff --git a/test/utils/allTopCharts.test.js b/test/utils/allTopCharts.test.js index ca41648..bb75cf9 100644 --- a/test/utils/allTopCharts.test.js +++ b/test/utils/allTopCharts.test.js @@ -15,4 +15,16 @@ describe('allTopCharts.js', function(){ it('should reject if country is invalid', function(){ return allTopCharts('201401', 'ZZ').should.be.rejectedWith('Could not locate country'); }); + it('should resolve without a date or country', function(){ + return allTopCharts().should.be.fulfilled; + }); + it('should resolve without a country', function(){ + return allTopCharts('201401').should.be.fulfilled; + }); + it('should resolve with a country code', function(){ + return allTopCharts('201401', 'US').should.be.fulfilled; + }); + it('should resolve with a country name', function(){ + return allTopCharts('201401', 'united states').should.be.fulfilled; + }); }); \ No newline at end of file diff --git a/test/utils/categoryTopCharts.test.js b/test/utils/categoryTopCharts.test.js index 1a8215c..e0ebd7c 100644 --- a/test/utils/categoryTopCharts.test.js +++ b/test/utils/categoryTopCharts.test.js @@ -18,4 +18,19 @@ describe('categoryTopCharts.js', function(){ it('should reject if country is invalid', function(){ return categoryTopCharts('dogs','201401', 'ZZ').should.be.rejectedWith('Could not locate country'); }); + it('should resolve without a date or country', function(){ + return categoryTopCharts('dogs').should.be.fulfilled; + }); + it('should resolve without a date', function(){ + return categoryTopCharts({category: 'dogs', geo: 'US'}).should.be.fulfilled; + }); + it('should resolve without a country', function(){ + return categoryTopCharts('dogs','201401').should.be.fulfilled; + }); + it('should resolve with a valid country code and date', function(){ + return categoryTopCharts('dogs','201401', 'US').should.be.fulfilled; + }); + it('should resolve with a valid country name', function(){ + return categoryTopCharts('dogs','201401', 'united states').should.be.fulfilled; + }); }); \ No newline at end of file diff --git a/test/utils/hotTrends.test.js b/test/utils/hotTrends.test.js index 7b4e663..9f9f17a 100644 --- a/test/utils/hotTrends.test.js +++ b/test/utils/hotTrends.test.js @@ -12,4 +12,13 @@ describe('hotTrends.js', function(){ it('should reject if country is invalid', function(){ return hotTrends('ZZ').should.be.rejectedWith('Could not locate country'); }); + it('should resolve without a country', function(){ + return hotTrends().should.be.fulfilled; + }); + it('should resolve with a valid country code', function(){ + return hotTrends('US').should.be.fulfilled; + }); + it('should resolve with a valid country name', function(){ + return hotTrends('united states').should.be.fulfilled; + }); }); \ No newline at end of file diff --git a/test/utils/hotTrendsDetail.test.js b/test/utils/hotTrendsDetail.test.js index 8707674..676cb3a 100644 --- a/test/utils/hotTrendsDetail.test.js +++ b/test/utils/hotTrendsDetail.test.js @@ -12,4 +12,13 @@ describe('hotTrendsDetail.js', function(){ it('should reject if country is invalid', function(){ return hotTrendsDetail('ZZ').should.be.rejectedWith('Could not locate country'); }); + it('should resolve without a country', function(){ + return hotTrendsDetail().should.be.fulfilled; + }); + it('should resolve with a country code', function(){ + return hotTrendsDetail('US').should.be.fulfilled; + }); + it('should resolve with a country name', function(){ + return hotTrendsDetail('united states').should.be.fulfilled; + }); }); \ No newline at end of file diff --git a/test/utils/topRelated.test.js b/test/utils/topRelated.test.js index d077760..7b202b8 100644 --- a/test/utils/topRelated.test.js +++ b/test/utils/topRelated.test.js @@ -15,4 +15,13 @@ describe('topRelated.js', function(){ it('should reject if no keyword is provided', function(){ return topRelated().should.be.rejectedWith('Keywords must be provided'); }); + it('should resolve without a country', function(){ + return topRelated('dogs').should.be.fulfilled; + }); + it('should resolve with a country code', function(){ + return topRelated('dogs', 'US').should.be.fulfilled; + }); + it('should resolve with a country name', function(){ + return topRelated('dogs', 'united states').should.be.fulfilled; + }); }); \ No newline at end of file From 0f68d5a0a90d27728e87a2c9e4bc24284820a54e Mon Sep 17 00:00:00 2001 From: pat310 Date: Sat, 22 Oct 2016 18:04:36 -0400 Subject: [PATCH 9/9] using a real category for categoryTopCharts --- test/utils/categoryTopCharts.test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/utils/categoryTopCharts.test.js b/test/utils/categoryTopCharts.test.js index e0ebd7c..5243328 100644 --- a/test/utils/categoryTopCharts.test.js +++ b/test/utils/categoryTopCharts.test.js @@ -19,18 +19,18 @@ describe('categoryTopCharts.js', function(){ return categoryTopCharts('dogs','201401', 'ZZ').should.be.rejectedWith('Could not locate country'); }); it('should resolve without a date or country', function(){ - return categoryTopCharts('dogs').should.be.fulfilled; + return categoryTopCharts('actors').should.be.fulfilled; }); it('should resolve without a date', function(){ - return categoryTopCharts({category: 'dogs', geo: 'US'}).should.be.fulfilled; + return categoryTopCharts({category: 'actors', geo: 'US'}).should.be.fulfilled; }); it('should resolve without a country', function(){ - return categoryTopCharts('dogs','201401').should.be.fulfilled; + return categoryTopCharts('actors','201401').should.be.fulfilled; }); it('should resolve with a valid country code and date', function(){ - return categoryTopCharts('dogs','201401', 'US').should.be.fulfilled; + return categoryTopCharts('actors','201401', 'US').should.be.fulfilled; }); it('should resolve with a valid country name', function(){ - return categoryTopCharts('dogs','201401', 'united states').should.be.fulfilled; + return categoryTopCharts('actors','201401', 'united states').should.be.fulfilled; }); }); \ No newline at end of file