test/utilities.spec.js
'use strict';
import chai from 'chai';
import {
constructInterestObj,
constructTrendingObj,
convertDateToString,
formatResolution,
formatTime,
formatComparisonItems,
getInterestResults,
getTrendingResults,
isLessThan7Days,
parseResults,
} from '../src/utilities';
import request from '../src/request';
const expect = chai.expect;
describe('utilities', () => {
describe('isLessThan7Days', () => {
it('should return true if difference is less than 7 days', () => {
const d1 = new Date('2017-02-04');
const d2 = new Date('2017-02-10');
const d3 = new Date('2017-02-01');
expect(isLessThan7Days(d1, d2)).to.be.true;
expect(isLessThan7Days(d2, d3)).to.be.false;
});
});
describe('convertDateToString', () => {
it('should be able to return a date formatted as YYYY-MM-DD', () => {
const d = new Date('2017-02-04');
expect(convertDateToString(d)).to.equal('2017-02-4');
});
it('should be able to return a date formatted as YYYY-MM-DDTHH\\:MM\\:SS',
() => {
const d = new Date('2017', '01', '04', '12', '43');
const utcHour = d.getUTCHours();
expect(convertDateToString(d, true)).to.equal(
`2017-02-4T${utcHour}\\:43\\:00`);
});
it('should be able to return a date formatted as YYYYMMDDTHH\\:MM\\:SS',
() => {
const d = new Date('2017', '01', '04', '12', '43');
const utcHour = d.getUTCHours();
expect(convertDateToString(d, true, true)).to.equal(
`20170204T${utcHour}\\:43\\:00`);
});
});
describe('formatTime', () => {
it('should make endTime the current date if not provided', () => {
const d = new Date();
const endTime = convertDateToString(d);
const time = formatTime({}).time.split(' ');
expect(formatTime({}).time).to.exist;
expect(time[1]).to.equal(endTime);
});
it('should make the startTime 2004-01-01 if not provided', () => {
const time = formatTime({}).time.split(' ');
expect(formatTime({}).time).to.exist;
expect(time[0]).to.equal('2004-01-1');
});
it('should include time if dates are less than a week and ' +
'granularTimeResolution set to true', () => {
const endTime = new Date();
const startTime = new Date(Date.now() - (5 * 24 * 60 * 60 * 1000));
const startTime2 = new Date(Date.now() - (8 * 24 * 60 * 60 * 1000));
expect(/T/.test(formatTime({
endTime,
startTime,
granularTimeResolution: true,
}).time)).to.be.true;
expect(/T/.test(formatTime({
endTime,
startTime,
granularTimeResolution: false,
}).time)).to.be.false;
expect(/T/.test(formatTime({
endTime,
startTime: startTime2,
granularTimeResolution: true,
}).time)).to.be.false;
});
it('should switch startTime and endTime if startTime is after endTime',
() => {
const endTime = new Date();
const startTime = new Date(Date.now() + (5 * 24 * 60 * 60 * 1000));
const result = formatTime({startTime, endTime});
expect(result.startTime).to.equal(endTime);
expect(result.endTime).to.equal(startTime);
});
});
describe('formatComparisonItems', () => {
it('should return single comparisonItem', () => {
let keywords = formatComparisonItems({ keyword: 'test' });
expect(keywords).to.deep.equal([{ keyword: 'test' }]);
});
it('should return an array of comparisonItems', () => {
let keywords = formatComparisonItems({
keyword: ['test', 'test2'],
startDate: '2017-01-01',
});
expect(keywords).to.deep.equal([
{keyword: 'test', startDate: '2017-01-01'},
{keyword: 'test2', startDate: '2017-01-01'},
]);
});
it('should return comparisonItems with same region', () => {
let keywords = formatComparisonItems({
keyword: ['test', 'test2'],
startDate: '2017-01-01',
geo: 'GB',
});
expect(keywords).to.deep.equal([
{keyword: 'test', startDate: '2017-01-01', geo: 'GB'},
{keyword: 'test2', startDate: '2017-01-01', geo: 'GB'},
]);
});
it('should return comparisonItems with different regions', () => {
let keywords = formatComparisonItems({
keyword: ['test', 'test2'],
startDate: '2017-01-01',
geo: ['GB', 'ES'],
});
expect(keywords).to.deep.equal([
{keyword: 'test', startDate: '2017-01-01', geo: 'GB'},
{keyword: 'test2', startDate: '2017-01-01', geo: 'ES'},
]);
});
it('should duplicate single keyword searches for multiple regions', () => {
let keywords = formatComparisonItems({
keyword: 'test',
startDate: '2018-01-01',
geo: ['US-MA', 'US-VA'],
});
expect(keywords).to.deep.equal([
{keyword: 'test', startDate: '2018-01-01', geo: 'US-MA'},
{keyword: 'test', startDate: '2018-01-01', geo: 'US-VA'},
]);
});
});
describe('constructInterestObj', () => {
it('should return an error if first argument is not an object', () => {
expect(constructInterestObj('not an obj').obj).to.be.an('error');
});
it('should return an error if keyword is not provided', () => {
expect(constructInterestObj({endTime: new Date()}).obj)
.to.be.an('error');
expect(constructInterestObj({keywords: 'Brooklyn'}).obj)
.to.be.an('error');
});
it('should return an error if keyword and geo length are not equal', () => {
expect(constructInterestObj({
keyword: ['foo', 'bar'],
geo: ['Brooklyn', 'DC', 'Boston'],
}).obj).to.be.an('error');
});
it('should return an error if startTime is not a date', () => {
expect(constructInterestObj({
keyword: 'test',
startTime: '2018-01-01',
}).obj).to.be.an('error');
});
it('should return an error if endTime is not a date', () => {
expect(constructInterestObj({
keyword: 'test',
endTime: '2018-01-01',
}).obj).to.be.an('error');
});
it('should return an error if keyword and geo length are not equal', () => {
expect(constructInterestObj({
keyword: ['foo', 'bar'],
geo: ['Brooklyn', 'DC', 'Boston'],
}).obj).to.be.an('error');
});
it('should return an error if startTime is not a date', () => {
expect(constructInterestObj({
keyword: 'test',
startTime: '2018-01-01',
}).obj).to.be.an('error');
});
it('should return an error if endTime is not a date', () => {
expect(constructInterestObj({
keyword: 'test',
endTime: '2018-01-01',
}).obj).to.be.an('error');
});
it('should return an error if cbFunc is not a function', () => {
expect(constructInterestObj({keyword: 'Brooklyn'}, 'str').obj)
.to.be.an('error');
});
it('should not require a callback function', () => {
expect(constructInterestObj({keyword: 'Brooklyn'}).obj)
.to.not.be.an('error');
});
it('should create a callback if one is not provided', () => {
expect(constructInterestObj({keyword: 'Brooklyn'}).cbFunc)
.to.be.a('function');
});
it('should add default hl to english if not provided', () => {
expect(constructInterestObj({keyword: 'Brooklyn'}).obj.hl)
.to.equal('en-US');
});
it('should add default category to 0 if not provided', () => {
expect(constructInterestObj({keyword: 'Brooklyn'}).obj.category)
.to.equal(0);
});
it('@test should have a property if provided', () => {
expect(constructInterestObj({
keyword: 'Brooklyn',
property: 'youtube',
}).obj.property).to.equal('youtube');
});
it('@test has only allowed properties', () => {
expect(constructInterestObj({
keyword: 'Brooklyn',
property: [],
}).obj.property).to.equal('');
expect(constructInterestObj({
keyword: 'Brooklyn',
property: 'netflix',
}).obj.property).to.equal('');
expect(constructInterestObj({
keyword: 'Brooklyn',
property: undefined,
}).obj.property).to.equal('');
});
});
describe('formatResolution', () => {
const resolutions = ['COUNTRY', 'REGION', 'CITY', 'DMA'];
it('should accept all words on the enumerated list', () => {
const isItTrue = resolutions.every(formatResolution);
expect(isItTrue).to.be.true;
});
it('should return an empty string if word is not on list', () => {
expect(formatResolution('random string')).to.equal('');
});
it('should capitalize a word on the list', () => {
expect(formatResolution('country')).to.equal('COUNTRY');
});
});
describe('getInterestResults', () => {
it('should return a function', () => {
const resultsFunc = getInterestResults();
expect(resultsFunc).to.be.a('function');
});
it('should eventually return', (done) => {
const resultsFunc = getInterestResults(request);
const { obj } = constructInterestObj({keyword: 'Brooklyn'});
resultsFunc('Interest over time', obj)
.then((res) => {
expect(res).to.exist;
expect(JSON.parse(res)).to.not.be.an('error');
done();
})
.catch((e) => {
expect(e).to.not.exist();
done();
});
});
it('should error if widgets do not contain selected api type', (done) => {
function promiseFunc() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const fakeReqObj = {
widgets: [{
request: {
requestOptions: {},
},
token: 'dogman',
title: 'Related topics',
}],
};
resolve(`1234${JSON.stringify(fakeReqObj)}`);
}, 500);
});
}
const resultsFunc = getInterestResults(promiseFunc);
const { obj } = constructInterestObj({ keyword: 'Brooklyn' });
resultsFunc('Interest over time', obj)
.catch((e) => {
const message = 'Available widgets does not contain selected api type';
expect(e.message).to.equal(message);
done();
});
});
it('should error if JSON is not valid', (done) => {
let count = 0;
const expectedFailureMsg = 'not valid json';
function promiseFunc() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (count === 0) {
count += 1;
const fakeReqObj = {
widgets: [{
request: {
requestOptions: {},
},
token: 'dogman',
title: 'Interest over time',
}],
};
resolve(`1234${JSON.stringify(fakeReqObj)}`);
} else {
resolve(expectedFailureMsg);
}
}, 500);
});
}
const resultsFunc = getInterestResults(promiseFunc);
const { obj } = constructInterestObj({keyword: 'Brooklyn'});
resultsFunc('Interest over time', obj)
.then((res) => {
expect(res).to.exist;
expect(res).to.equal(expectedFailureMsg);
done();
})
.catch((e) => {
done();
});
});
});
describe('parseResults', () => {
it('should return a javascript object', () => {
// The 'abcd' is the 4 characters that are returned by the request
let validJSON = parseResults('abcd{' +
'"some": "valid json",' +
'"widgets": ["a", "b", "c"]' +
'}');
expect(validJSON).to.deep.equal(['a', 'b', 'c']);
});
it('should throw an error on invalid JSON', () => {
expect(() => parseResults('<!DOCTYPE html><html</html>')).to.throw(Error);
});
});
describe('constructTrendingObj', () => {
it('should return an error if first argument is not an object', () => {
expect(constructTrendingObj('not an obj').obj).to.be.an('error');
});
it('should return an error if cbFunc is not a function', () => {
expect(constructTrendingObj({geo: 'US'}, 'str').obj).to.be.an('error');
});
it('should not require a callback function', () => {
expect(constructTrendingObj({geo: 'US'}).obj).to.not.be.an('error');
});
it('should create a functioning callback if one is not provided', () => {
expect(constructTrendingObj({geo: 'US'}).cbFunc).to.be.a('function');
expect(constructTrendingObj({geo: 'US'})
.cbFunc(new Error())).to.be.an('error');
expect(constructTrendingObj({geo: 'US'}).cbFunc(0, '')).to.equal('');
});
it('should add default hl to english if not provided', () => {
expect(constructTrendingObj({geo: 'US'}).obj.hl).to.equal('en-US');
});
it('should add default category to \'all\' if not provided', () => {
expect(constructTrendingObj({geo: 'US'}).obj.category).to.equal('all');
});
it('should return an error if the geo is not provided', () => {
expect(constructTrendingObj({trendDate: '2018-12-25'}).obj)
.to.be.an('error');
});
it('should default trendDate to today if not provided', () => {
expect(
convertDateToString(constructTrendingObj(
{geo: 'US', trendDate: '2018-12-25'}).obj.trendDate)).to.equal(
convertDateToString(new Date()));
});
it('should default trendDate to today provided in wrong format', () => {
expect(
convertDateToString(
constructTrendingObj({geo: 'US', trendDate: '2018-12-25'})
.obj.trendDate)).to.equal(convertDateToString(new Date()));
});
it('should default TimeZone to the current TZ if not provided', () => {
expect(constructTrendingObj({geo: 'US'}).obj.timezone).to.equal(
new Date().getTimezoneOffset());
});
it('should default ns to 15 if not not provided', () => {
expect(constructTrendingObj({geo: 'US'}).obj.ns).to.equal(15);
});
});
describe('getTrendingResults', () => {
it('should return a function', () => {
const resultsFunc = getTrendingResults();
expect(resultsFunc).to.be.a('function');
});
it('should eventually return', (done) => {
const resultsFunc = getTrendingResults(request);
const { obj } = constructTrendingObj({geo: 'US'});
resultsFunc('Daily trends', obj)
.then((res) => {
expect(res).to.exist;
expect(JSON.parse(res)).to.not.be.an('error');
done();
})
.catch((e) => {
expect(e).to.not.exist();
done();
});
});
it('should error if JSON is not valid', (done) => {
const expectedFailureMsg = 'not valid json';
function promiseFunc() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(expectedFailureMsg);
}, 500);
});
}
const resultsFunc = getTrendingResults(promiseFunc);
const { obj } = constructTrendingObj({geo: 'US'});
resultsFunc('Daily trends', obj)
.then((res) => {
expect(res).to.exist;
expect(res).to.equal(expectedFailureMsg);
done();
})
.catch((e) => {
done();
});
});
});
});