diff --git a/babel/index.js b/babel/index.js index e718db6..ac55dc7 100644 --- a/babel/index.js +++ b/babel/index.js @@ -1,8 +1,6 @@ 'use strict'; var _ = require('lodash'), - request = require('request'), - rpn = require('request-promise-native'), md5 = require('md5'), querystring = require('querystring'); @@ -36,7 +34,11 @@ var BabelClient = function babelClient(config) { throw new Error('Invalid Babel config: babel_host'); } - this.config.babel_hostname = this.config.babel_host.split('://', 2)[1]; + var port = config.babel_port ? config.babel_port : (config.babel_host === 'https:' ? 443 : 80); + this.config.endpointUrl = new URL(`${config.babel_host}:${port}`); + + var scheme = this.config.endpointUrl.protocol; + this.http = require(scheme === 'https:' ? 'https' : 'http'); this.userAgent = (process && _.has(process, ["version", "env.NODE_ENV"])) ? "talis-node/" + clientVer + " (nodejs/" + process.version + "; NODE_ENV=" + @@ -71,30 +73,41 @@ BabelClient.prototype.headTargetFeed = function headTargetFeed(target, token, pa var queryString = this._queryStringParams(params); var requestOptions = { - method: "HEAD", - url: this._getBaseURL() + - '/feeds/targets/'+md5(target)+'/activity/annotations' + (!_.isEmpty(queryString) ? '?'+queryString : ''), - headers: { - 'Accept': 'application/json', - 'Authorization':'Bearer '+token, - 'Host': this.config.babel_hostname, - 'User-Agent': this.userAgent, - } + hostname: this.config.endpointUrl.hostname, + port: this.config.endpointUrl.port ? this.config.endpointUrl.port : (this.config.endpointUrl.protocol === 'https:' ? 443 : 80), + path: '/feeds/targets/'+md5(target)+'/activity/annotations' + (!_.isEmpty(queryString) ? '?'+queryString : ''), + method: "HEAD", + headers: { + Accept: 'application/json', + Authorization: 'Bearer ' + token, + 'Host': this.config.endpointUrl.hostname, + 'User-Agent': this.userAgent, + }, }; - this.debug(JSON.stringify(requestOptions)); + var body = ''; + const r = this.http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); - request(requestOptions, function requestResponse(err, response){ - if(err){ - callback(err); - } else if(response.statusCode && response.statusCode !== 204){ + resp.on('error', (e) => { + callback(e); + }); + + resp.on("end", d => { + if (resp.statusCode !== 204){ var babelError = new Error(); - babelError.http_code = response.statusCode || 404; + babelError.http_code = resp.statusCode; callback(babelError); - } else{ - callback(null, response); + } else { + callback(null, resp); + return; } + }); }); + + r.end(); }; BabelClient.prototype.getEntireTargetFeed = async function (target, token, hydrate, callback) { @@ -125,21 +138,20 @@ BabelClient.prototype.getEntireTargetFeed = async function (target, token, hydra offset: currentPage * perPage, }) - const requestOptions = { - json: true, - simple: false, - resolveWithFullResponse: true, - method: 'GET', - url: this._getBaseURL() - + '/feeds/targets/' + var requestOptions = { + hostname: this.config.endpointUrl.hostname, + port: this.config.endpointUrl.port ? this.config.endpointUrl.port : (this.config.endpointUrl.protocol === 'https:' ? 443 : 80), + path: '/feeds/targets/' + md5(target) + '/activity/annotations' + ((hydrate === true) ? '/hydrate' : '') + (!_.isEmpty(queryString) ? '?'+queryString : ''), + method: "GET", headers: { - 'Accept': 'application/json', - 'Authorization':'Bearer '+ token, - 'Host': this.config.babel_hostname, + 'Content-Type': 'application/json', + Accept: 'application/json', + Authorization: 'Bearer ' + token, + 'Host': this.config.endpointUrl.hostname, 'User-Agent': this.userAgent, }, }; @@ -147,16 +159,15 @@ BabelClient.prototype.getEntireTargetFeed = async function (target, token, hydra this.debug(JSON.stringify(requestOptions)); try { + const response = await this.requestAsync(requestOptions); + const { - body: { - feed_length, - annotations, - userProfiles, - error, - error_description, - }, - ...response - } = await rpn(requestOptions); + feed_length, + annotations, + userProfiles, + error, + error_description, + } = response; if (error) { callbackError = new Error(error_description); @@ -178,7 +189,7 @@ BabelClient.prototype.getEntireTargetFeed = async function (target, token, hydra } } catch (error) { - this.error(`Error fetching babel feed ${JSON.stringify(error)}`); + this.error(`Error fetching babel feed ${error}`); callbackError = error; } @@ -188,6 +199,67 @@ BabelClient.prototype.getEntireTargetFeed = async function (target, token, hydra return callback(callbackError, results); } +BabelClient.prototype.requestAsync = async function (requestOptions) { + return new Promise((resolve, reject) => { + var body = ''; + const r = this.http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); + + resp.on('error', (e) => { + callback(e); + }); + + resp.on("end", d => { + if (parseInt(resp.statusCode / 100) !== 2) { + reject({http_code: resp.statusCode, message: JSON.parse(body).error_description}); + return; + } else { + var jsonBody = JSON.parse(body); + if(jsonBody.error){ + var statusCode = jsonBody.statusCode ? jsonBody.statusCode : 400; + var message = jsonBody.error_description ? jsonBody.error_description : 'UNKNOWN'; + reject({http_code: statusCode, message: message}); + return; + } else { + resolve(jsonBody); + } + return; + } + }); + }); + + r.end(); + }); +} + +async function getTargetFeedAsync(target, token, hydrate, callback) { + var body = ''; + const r = this.http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); + + resp.on('error', (e) => { + callback(e); + }); + + resp.on("end", d => { + if (resp.statusCode !== 204){ + var babelError = new Error(); + babelError.http_code = resp.statusCode; + callback(babelError); + } else { + callback(null, resp); + return; + } + }); + }); + + r.end(); +}; + /** * Get a feed based off a target identifier. Return either a list of feed identifiers, or hydrate it and * pass back the data as well @@ -222,25 +294,34 @@ BabelClient.prototype.getTargetFeed = function getTargetFeed(target, token, hydr var queryString = this._queryStringParams(params); var requestOptions = { - url: this._getBaseURL() + - '/feeds/targets/'+md5(target)+'/activity/annotations'+((hydrate === true) ? '/hydrate' : '') + (!_.isEmpty(queryString) ? '?'+queryString : ''), - headers: { - 'Accept': 'application/json', - 'Authorization':'Bearer '+token, - 'Host': this.config.babel_hostname, - 'User-Agent': this.userAgent, - } + hostname: this.config.endpointUrl.hostname, + port: this.config.endpointUrl.port ? this.config.endpointUrl.port : (this.config.endpointUrl.protocol === 'https:' ? 443 : 80), + path: '/feeds/targets/'+md5(target)+'/activity/annotations'+((hydrate === true) ? '/hydrate' : '') + (!_.isEmpty(queryString) ? '?'+queryString : ''), + method: "GET", + headers: { + Accept: 'application/json', + Authorization: 'Bearer ' + token, + 'Host': this.config.endpointUrl.hostname, + 'User-Agent': this.userAgent, + }, }; - this.debug(JSON.stringify(requestOptions)); + var body = ''; + const r = this.http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); - request(requestOptions, function requestResponse(err, response, body){ - if(err){ - callback(err); - } else{ - self._parseJSON(response, body, callback); - } + resp.on('error', (e) => { + callback(e); + }); + + resp.on("end", d => { + self._parseJSON(resp, body, callback); + }); }); + + r.end(); }; /*** @@ -266,24 +347,34 @@ BabelClient.prototype.getFeeds = function getFeeds(feeds, token, callback) { feeds = feeds.join(","); var requestOptions = { - url: this._getBaseURL() + '/feeds/annotations/hydrate?feed_ids=' + encodeURIComponent(feeds), - headers: { - 'Accept': 'application/json', - 'Authorization': 'Bearer ' + token, - 'Host': this.config.babel_hostname, - 'User-Agent': this.userAgent, - } + hostname: this.config.endpointUrl.hostname, + port: this.config.endpointUrl.port ? this.config.endpointUrl.port : (this.config.endpointUrl.protocol === 'https:' ? 443 : 80), + path: '/feeds/annotations/hydrate?feed_ids=' + encodeURIComponent(feeds), + method: "GET", + headers: { + Accept: 'application/json', + Authorization: 'Bearer ' + token, + 'Host': this.config.endpointUrl.hostname, + 'User-Agent': this.userAgent, + }, }; - this.debug(JSON.stringify(requestOptions)); + var body = ''; + const r = this.http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); - request(requestOptions, function requestResponse(err, response, body) { - if (err) { - callback(err); - } else { - self._parseJSON(response, body, callback); - } + resp.on('error', (e) => { + callback(e); + }); + + resp.on("end", d => { + self._parseJSON(resp, body, callback); + }); }); + + r.end(); }; /** @@ -305,24 +396,36 @@ BabelClient.prototype.getAnnotation = function getAnnotation(token, id, callback var self = this; var requestOptions = { - url: this._getBaseURL() + '/annotations/'+id, - headers: { - 'Accept': 'application/json', - 'Authorization':'Bearer '+token, - 'Host': this.config.babel_hostname, - 'User-Agent': this.userAgent, - } + hostname: this.config.endpointUrl.hostname, + port: this.config.endpointUrl.port ? this.config.endpointUrl.port : (this.config.endpointUrl.protocol === 'https:' ? 443 : 80), + path: '/annotations/' + id, + method: "GET", + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + token, + 'User-Agent': this.userAgent, + }, }; - this.debug(JSON.stringify(requestOptions)); + var self = this; - request(requestOptions, function requestResponse(err, response, body){ - if(err){ - callback(err); - } else{ - self._parseJSON(response, body, callback); - } + var body = ''; + const r = this.http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); + + r.on('error', (err) => { + callback(err); + }); + + resp.on("end", d => { + self._parseJSON(resp, body, callback); + }); }); + + r.end(); }; /** @@ -350,25 +453,34 @@ BabelClient.prototype.getAnnotations = function getAnnotations(token, querystrin querystringMap = querystringMap || {}; var requestOptions = { - url: this._getBaseURL() + '/annotations?' + querystring.stringify(querystringMap), - headers: { - 'Accept': 'application/json', - 'Authorization':'Bearer '+token, - 'Host': this.config.babel_hostname, - 'User-Agent': this.userAgent, - } + hostname: this.config.endpointUrl.hostname, + port: this.config.endpointUrl.port ? this.config.endpointUrl.port : (this.config.endpointUrl.protocol === 'https:' ? 443 : 80), + path: '/annotations?' + querystring.stringify(querystringMap), + method: "GET", + headers: { + 'Accept': 'application/json', + 'Authorization': 'Bearer ' + token, + 'Host': this.config.endpointUrl.hostname, + 'User-Agent': this.userAgent, + }, }; - this.debug(JSON.stringify(requestOptions)); + var body = ''; + const r = this.http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); - request(requestOptions, function requestResponse(err, response, body){ - if(err){ - callback(err); - } else{ - self._parseJSON(response, body, callback); - } + r.on('error', (err) => { + callback(err); + }); + + resp.on("end", d => { + self._parseJSON(resp, body, callback); + }); }); + r.end(); }; /** @@ -445,16 +557,17 @@ BabelClient.prototype.createAnnotation = function createAnnotation(token, data, }); var requestOptions = { - method:'POST', - body:data, - json:true, - url: this._getBaseURL() + '/annotations', - headers: { - 'Accept': 'application/json', - 'Authorization':'Bearer '+token, - 'Host': this.config.babel_hostname, - 'User-Agent': this.userAgent, - } + hostname: this.config.endpointUrl.hostname, + port: this.config.endpointUrl.port ? this.config.endpointUrl.port : (this.config.endpointUrl.protocol === 'https:' ? 443 : 80), + path: '/annotations', + method: "POST", + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + Authorization: 'Bearer ' + token, + 'Host': this.config.endpointUrl.hostname, + 'User-Agent': this.userAgent, + }, }; // if options.xIngestSynchronously set to true, then and only then add the header @@ -463,19 +576,30 @@ BabelClient.prototype.createAnnotation = function createAnnotation(token, data, requestOptions.headers['X-Ingest-Synchronously'] = 'true'; } - this.debug(JSON.stringify(requestOptions)); + var body = ''; + const r = this.http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); - request.post(requestOptions, function requestResponse(err, response, body){ - if (err) { - callback(err); - } else if (!this._responseSuccessful(response)) { - var babelError = new Error('Error creating annotation: ' + JSON.stringify(body)); - babelError.http_code = response && response.statusCode ? response.statusCode : 404; + resp.on('error', (e) => { + callback(e); + }); + + resp.on("end", d => { + if (parseInt(resp.statusCode / 100) !== 2) { + var babelError = new Error('Error creating annotation: ' + body); + babelError.http_code = resp && resp.statusCode ? resp.statusCode : 404; callback(babelError); } else { - callback(null, body); + callback(null, JSON.parse(body)); + return; } - }.bind(this)); + }); + }); + + r.write(JSON.stringify(data)); + r.end(); }; /** @@ -548,31 +672,43 @@ BabelClient.prototype.updateAnnotation = function updateAnnotation(token, data, }); var requestOptions = { - method: 'PUT', - body: data, - json: true, - url: this._getBaseURL() + '/annotations/' + data._id, - headers: { - 'Accept': 'application/json', - 'Authorization': 'Bearer ' + token, - 'Host': this.config.babel_hostname, - 'User-Agent': this.userAgent, - } + hostname: this.config.endpointUrl.hostname, + port: this.config.endpointUrl.port ? this.config.endpointUrl.port : (this.config.endpointUrl.protocol === 'https:' ? 443 : 80), + path: '/annotations/' + data._id, + method: "PUT", + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + Authorization: 'Bearer ' + token, + 'Host': this.config.endpointUrl.hostname, + 'User-Agent': this.userAgent, + }, }; - this.debug(JSON.stringify(requestOptions)); + var body = ''; + const r = this.http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); - request.put(requestOptions, function requestResponse(err, response, body){ - if (err) { - callback(err); - } else if (!this._responseSuccessful(response)) { - var babelError = new Error('Error updating annotation: ' + JSON.stringify(body)); - babelError.http_code = response && response.statusCode ? response.statusCode : 404; + resp.on('error', (e) => { + callback(e); + }); + + resp.on("end", d => { + if (parseInt(resp.statusCode / 100) !== 2) { + var babelError = new Error('Error updating annotation: ' + body); + babelError.http_code = resp && resp.statusCode ? resp.statusCode : 404; callback(babelError); } else { - callback(null, body); + callback(null, JSON.parse(body)); + return; } - }.bind(this)); + }); + }); + + r.write(JSON.stringify(data)); + r.end(); }; /** @@ -591,32 +727,41 @@ BabelClient.prototype.deleteAnnotation = function deleteAnnotation(token, annota } var requestOptions = { - method: 'DELETE', - json: true, - url: this._getBaseURL() + '/annotations/' + annotationId, - headers: { - 'Accept': 'application/json', - 'Authorization': 'Bearer ' + token, - 'Host': this.config.babel_hostname, - 'User-Agent': this.userAgent, - } + hostname: this.config.endpointUrl.hostname, + port: this.config.endpointUrl.port ? this.config.endpointUrl.port : (this.config.endpointUrl.protocol === 'https:' ? 443 : 80), + path: '/annotations/' + annotationId, + method: "DELETE", + headers: { + Accept: 'application/json', + Authorization: 'Bearer ' + token, + 'Host': this.config.endpointUrl.hostname, + 'User-Agent': this.userAgent, + }, }; - this.debug(JSON.stringify(requestOptions)); + var body = ''; + const r = this.http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); - request.delete(requestOptions, function requestResponse(err, response, body){ - if (err) { - callback(err); + resp.on('error', (e) => { + callback(e); + }); + + resp.on("end", d => { + if (resp.statusCode !== 204){ + var babelError = new Error('Error deleting annotation: ' + body); + babelError.http_code = resp.statusCode; + callback(babelError); } else { - if (response.statusCode !== 204){ - var babelError = new Error('Error deleting annotation: ' + JSON.stringify(body)); - babelError.http_code = response.statusCode; - callback(babelError); - } else { - callback(null, null); - } + callback(null, null); + return; } + }); }); + + r.end(); }; /** diff --git a/babel/test/smoke/babel-local-test.js b/babel/test/smoke/babel-local-test.js new file mode 100644 index 0000000..47f9633 --- /dev/null +++ b/babel/test/smoke/babel-local-test.js @@ -0,0 +1,246 @@ +var should = require('should'); +var assert = require('assert'); +var babel = require('../../index.js'); +var sinon = require('sinon'); +const fs = require('fs'); + +describe("Babel Node Client Smoke Test Against Local Babel", function(){ + // Run these smoke tests setting the PERSONA_TOKEN environment variable + // PERSONA_TOKEN=$(persona-token local) npm run echo-smoke-test + var token = process.env.PERSONA_TOKEN; + + var babelClient = babel.createClient({ + babel_host:"http://babel.talis.local", + babel_port:80 + }); + + var annotation = { + "hasBody": { + "type": "Text", + "format": "text/plain", + "chars": "Some annotation" + }, + "hasTarget": { + "uri": "http://target/1234567890" + }, + "annotatedBy": "1234567890", + "motivatedBy": "commenting", + }; + + it("should head taget feed", async function(){ + var target = "http://target/1234567890"; + var getFeedResult = await getTargetFeed(target, token, true, {limit: 1}); + var params = { + delta_token: getFeedResult.delta_token, + }; + + var response = await headTargetFeed(target, token, params); + + response.headers.should.have.property('x-feed-new-items'); + }); + + it("should get entire target feed", async function(){ + var target = "http://target/1234567890"; + var result = await getEntireTargetFeed(target, token, true, {limit: 1}); + + result.should.have.property('feed_length'); + result.should.have.property('annotations'); + }); + + it("should get target feed", async function(){ + var target = "http://target/1234567890"; + var result = await getTargetFeed(target, token, true, {limit: 1}); + + result.should.have.property('feed_length'); + result.should.have.property('annotations'); + result.annotations[0].should.have.property('annotatedBy', '1234567890'); + }); + + it("should get feeds", async function(){ + var result = await getFeeds(['users:1234567890:activity'], token); + + result.feeds[0].should.have.property('feed_id', 'users:1234567890:activity'); + result.feeds[0].should.have.property('status', 'success'); + }); + + it("should get annotation", async function(){ + var createResult = await createAnnotation(token, annotation); + await sleep(1000); + var getResult = await getAnnotation(token, createResult._id); + + getResult.hasBody.type.should.equal("Text"); + getResult.hasBody.format.should.equal("text/plain"); + getResult.hasBody.chars.should.equal("Some annotation"); + getResult.hasTarget.uri.should.equal("http://target/1234567890"); + getResult.annotatedBy.should.equal("1234567890"); + getResult.motivatedBy.should.equal("commenting"); + }); + + it("should get annotatioins", async function(){ + var createResult = await createAnnotation(token, annotation); + await sleep(1000); + var getResult = await getAnnotations(token, {}); + + getResult.limit.should.equal(25); + getResult.offset.should.equal(0); + getResult.annotations.should.have.lengthOf(25); + }); + + it("should create, update and delete annotation", async function(){ + + var createResult = await createAnnotation(token, annotation); + + createResult.hasBody.type.should.equal("Text"); + createResult.hasBody.format.should.equal("text/plain"); + createResult.hasBody.chars.should.equal("Some annotation"); + createResult.hasTarget.uri.should.equal("http://target/1234567890"); + createResult.annotatedBy.should.equal("1234567890"); + createResult.motivatedBy.should.equal("commenting"); + + await sleep(1000); + + var getOneResult = await getAnnotation(token, createResult._id); + getOneResult.hasBody.chars.should.equal("Some annotation"); + + var updatedAnnotation = annotation; + updatedAnnotation._id = createResult._id; + updatedAnnotation.hasBody.chars = "Some updated annotation"; + updatedAnnotation.motivatedBy = "updating commenting"; + + var updateResult = await updateAnnotation(token, updatedAnnotation); + updateResult.hasBody.chars.should.equal("Some updated annotation"); + updateResult.motivatedBy.should.equal("updating commenting"); + + await sleep(1000); + + var getTwoResult = await getAnnotation(token, createResult._id); + getTwoResult.hasBody.chars.should.equal("Some updated annotation"); + + await deleteAnnotation(token, createResult._id); + + await sleep(1000); + + var runGetAnnoation = async function(){ + await getAnnotation(token, createResult._id); + }; + + try { + await runGetAnnoation() + fail(); + } catch (err) { + err.message.should.equal("Could not find annotation"); + } + }); + + function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + function createAnnotation(token, annotation){ + return new Promise((resolve, reject) => { + babelClient.createAnnotation(token, annotation, {}, function(err, result){ + if(err){ + reject(err); + }else{ + resolve(result); + } + }); + }); + } + + function getAnnotation(token, id){ + return new Promise((resolve, reject) => { + babelClient.getAnnotation(token, id, function(err, result){ + if(err){ + reject(err); + }else{ + resolve(result); + } + }); + }); + } + + function getAnnotations(token, queryStringMap){ + return new Promise((resolve, reject) => { + babelClient.getAnnotations(token, queryStringMap, function(err, result){ + if(err){ + reject(err); + }else{ + resolve(result); + } + }); + }); + } + + function updateAnnotation(token, annotation){ + return new Promise((resolve, reject) => { + babelClient.updateAnnotation(token, annotation, function(err, result){ + if(err){ + reject(err); + }else{ + resolve(result); + } + }); + }); + } + + function deleteAnnotation(token, id){ + return new Promise((resolve, reject) => { + babelClient.deleteAnnotation(token, id, function(err, result){ + if(err){ + reject(err); + }else{ + resolve(result); + } + }); + }); + } + + function getFeeds(feeds, token){ + return new Promise((resolve, reject) => { + babelClient.getFeeds(feeds,token,function(err, result){ + if(err){ + reject(err); + }else{ + resolve(result); + } + }); + }); + } + + function getTargetFeed(target, token, hydrate, params){ + return new Promise((resolve, reject) => { + babelClient.getTargetFeed(target, token, hydrate, params, function(err, result){ + if(err){ + reject(err); + }else{ + resolve(result); + } + }); + }); + } + + function getEntireTargetFeed(target, token, hydrate){ + return new Promise((resolve, reject) => { + babelClient.getEntireTargetFeed(target, token, hydrate, function(err, result){ + if(err){ + reject(err); + }else{ + resolve(result); + } + }); + }); + } + + function headTargetFeed(target, token, params){ + return new Promise((resolve, reject) => { + babelClient.headTargetFeed(target, token, params, function(err, result){ + if(err){ + reject(err); + }else{ + resolve(result); + } + }); + }); + } +}); diff --git a/babel/test/unit/babel_client_test.js b/babel/test/unit/babel_client_test.js index 6e623d1..08ee559 100644 --- a/babel/test/unit/babel_client_test.js +++ b/babel/test/unit/babel_client_test.js @@ -4,7 +4,11 @@ var should = require('should'), assert = require('assert'), sinon = require('sinon'), babel = require('../../index.js'), - rewire = require("rewire"); + nock = require("nock"), + querystring = require('querystring'), + md5 = require('md5'); + +var endPoint = 'http://babel:3000'; describe("Babel Node Client Test Suite", function(){ describe("- Constructor tests", function(){ @@ -68,41 +72,18 @@ describe("Babel Node Client Test Suite", function(){ headTargetFeed.should.throw("Missing Persona token"); }); - it("- should return an error if call to request returns an error when head target feed", function(done){ - var babel = rewire("../../index.js"); - - var babelClient = babel.createClient({ - babel_host:"http://babel", - babel_port:3000 - }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(new Error('Error communicating with Babel')); - }; - - babel.__set__("request", requestStub); - - babelClient.headTargetFeed('TARGET', 'secret', {}, function(err, response){ - - (err === null).should.be.false; - err.message.should.equal('Error communicating with Babel'); - (typeof result).should.equal('undefined'); - done(); - }); - }); it("- should return an error (401) if persona token is invalid when head target feed", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode:401}); - }; - babel.__set__("request", requestStub); + nock(endPoint) + .head('/feeds/targets/'+md5('TARGET')+'/activity/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [401, {}]; + }); babelClient.headTargetFeed('TARGET', 'secret', {}, function(err, response){ @@ -113,18 +94,17 @@ describe("Babel Node Client Test Suite", function(){ }); }); it("- should return an error (404) if babel returns no feed when head target feed", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode:404}); - }; - babel.__set__("request", requestStub); + nock(endPoint) + .head('/feeds/targets/'+md5('TARGET')+'/activity/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [404]; + }); babelClient.headTargetFeed('TARGET', 'secret', {}, function(err, response){ (err === null).should.be.false; @@ -134,19 +114,17 @@ describe("Babel Node Client Test Suite", function(){ }); }); it("- should not return an error if no params set and response from babel is ok when head target feed", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode:204, headers:{'x-feed-new-items': '1'}}); - }; - - babel.__set__("request", requestStub); + nock(endPoint) + .head('/feeds/targets/'+md5('TARGET')+'/activity/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [204, {}, {'x-feed-new-items': '1'}]; + }); babelClient.headTargetFeed('TARGET', 'secret', function(err, response){ (err === null).should.be.true; @@ -154,20 +132,20 @@ describe("Babel Node Client Test Suite", function(){ done(); }); }); + // TODO In what way is this test materially different from the one above? + // Can it be removed? it("- should return response if no error from babel and feed is found with empty params when head target feed", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode:204, headers:{'x-feed-new-items': '2'}}); - }; - - babel.__set__("request", requestStub); + nock(endPoint) + .head('/feeds/targets/'+md5('TARGET')+'/activity/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [204, {}, {'x-feed-new-items': '2'}]; + }); babelClient.headTargetFeed('TARGET', 'secret', {}, function(err, response){ (err === null).should.be.true; @@ -204,40 +182,21 @@ describe("Babel Node Client Test Suite", function(){ }); }); - it("- should return an error if call to request returns an error when get target feed", function(done){ - var babel = rewire("../../index.js"); - - var babelClient = babel.createClient({ - babel_host:"http://babel", - babel_port:3000 - }); - var requestStub = () => new Promise ((_resolve, reject) => reject(Error('Error communicating with Babel'))) - - babel.__set__("rpn", requestStub); - - babelClient.getEntireTargetFeed('TARGET', 'secret', true, function(err, result){ - (err === undefined).should.be.false; - err.message.should.equal('Error communicating with Babel'); - done(); - }); - }); - it("- should return an error (401) if persona token is invalid when get target feed", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = () => new Promise ((resolve, reject) => resolve({ - statusCode: 401, - body: { - error:"invalid_token", - error_description:"The token is invalid or has expired" - } - })) - babel.__set__("rpn", requestStub); + nock(endPoint) + .get('/feeds/targets/'+md5('TARGET')+'/activity/annotations/hydrate?limit=1000&offset=0') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [401, { + error:"invalid_token", + error_description:"The token is invalid or has expired" + }]; + }); babelClient.getEntireTargetFeed('TARGET', 'secret', true, function(err, result){ (err === undefined).should.be.false; @@ -248,21 +207,20 @@ describe("Babel Node Client Test Suite", function(){ }); it("- should return an error (404) if babel returns no feed when get target feed", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = () => new Promise ((resolve, _reject) => resolve({ - statusCode: 404, - body: { - error:"feed_not_found", - error_description:"Feed not found" - } - })) + nock(endPoint) + .get('/feeds/targets/'+md5('TARGET')+'/activity/annotations/hydrate?limit=1000&offset=0') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [404, { + error:"feed_not_found", + error_description:"Feed not found" + }]; + }); - babel.__set__("rpn", requestStub); babelClient.getEntireTargetFeed('TARGET', 'secret', true, function(err, result){ (err === undefined).should.be.false; @@ -273,37 +231,35 @@ describe("Babel Node Client Test Suite", function(){ }); it("- should return results even when on the babel limit without an error", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var isFirstPage = true; - var requestStub = () => new Promise ((resolve, _reject) => { - var annotations = isFirstPage ? Array(1000) : [{ - annotatedBy:"tn", - _id:"54c107db52be6b4d90000001", - __v:0, - annotatedAt:"2015-01-22T14:23:23.013Z", - motivatedBy:"commenting", - hasTarget:[], - hasBody:{} - },{ - annotatedBy:"tn", - _id:"54c10857ae44b3f492000001", - __v:0, - annotatedAt:"2015-01-22T14:25:27.294Z", - motivatedBy:"commenting", - hasTarget:[], - hasBody:{} - }] - isFirstPage = false - - resolve({ - statusCode: 200, - body: { + var annotationsInFirstCall = Array(1000); + var annotationsInSecondCall = [{ + annotatedBy:"tn", + _id:"54c107db52be6b4d90000001", + __v:0, + annotatedAt:"2015-01-22T14:23:23.013Z", + motivatedBy:"commenting", + hasTarget:[], + hasBody:{} + },{ + annotatedBy:"tn", + _id:"54c10857ae44b3f492000001", + __v:0, + annotatedAt:"2015-01-22T14:25:27.294Z", + motivatedBy:"commenting", + hasTarget:[], + hasBody:{} + }] + + nock(endPoint) + .get('/feeds/targets/'+md5('TARGET')+'/activity/annotations/hydrate?limit=1000&offset=0') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, { count:1000, limit:1000, offset:0, @@ -315,16 +271,31 @@ describe("Babel Node Client Test Suite", function(){ gravatarUrl: "a98f8ca335dc8dd239b1324b7e88f0db" } }, - annotations - } - }) - }) + annotations: annotationsInFirstCall + }]; + }); - var requestStubSpy = sinon.spy(requestStub); - babel.__set__("rpn", requestStubSpy); + nock(endPoint) + .get('/feeds/targets/'+md5('TARGET')+'/activity/annotations/hydrate?limit=1000&offset=1000') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, { + count:1000, + limit:1000, + offset:0, + feed_length: 1002, + userProfiles: { + user_1: { + first_name: "TN", + surname: "TestAccount", + gravatarUrl: "a98f8ca335dc8dd239b1324b7e88f0db" + } + }, + annotations: annotationsInSecondCall + }]; + }); babelClient.getEntireTargetFeed('TARGET', 'secret', true, function(err, result){ - requestStubSpy.callCount.should.equal(2); (err === undefined).should.be.true; result.feed_length.should.equal(1002); result.userProfiles.user_1.first_name.should.equal('TN') @@ -361,19 +332,18 @@ describe("Babel Node Client Test Suite", function(){ getTargetFeed.should.throw("Missing Persona token"); }); it("- should not cause an error if no options passed in", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {}, JSON.stringify({})); - }; + nock(endPoint) + .get('/feeds/targets/'+md5('TARGET')+'/activity/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, {}]; + }); - babel.__set__("request", requestStub); babelClient.getTargetFeed('TARGET', 'secret', null, function(err){ (err === null).should.be.true; @@ -381,42 +351,22 @@ describe("Babel Node Client Test Suite", function(){ }); }); - it("- should return an error if call to request returns an error when get target feed", function(done){ - var babel = rewire("../../index.js"); - - var babelClient = babel.createClient({ - babel_host:"http://babel", - babel_port:3000 - }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(new Error('Error communicating with Babel')); - }; - - babel.__set__("request", requestStub); - - babelClient.getTargetFeed('TARGET', 'secret', {}, function(err, result){ - - (err === null).should.be.false; - err.message.should.equal('Error communicating with Babel'); - (typeof result).should.equal('undefined'); - done(); - }); - }); - it("- should return an error (401) if persona token is invalid when get target feed", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode:401}, JSON.stringify({error:"invalid_token", error_description:"The token is invalid or has expired"})); - }; - babel.__set__("request", requestStub); + nock(endPoint) + .get('/feeds/targets/'+md5('TARGET')+'/activity/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [401, { + error:"invalid_token", + error_description:"The token is invalid or has expired" + }]; + }); + babelClient.getTargetFeed('TARGET', 'secret', {}, function(err, result){ @@ -429,18 +379,21 @@ describe("Babel Node Client Test Suite", function(){ }); it("- should return an error (404) if babel returns no feed when get target feed", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {}, JSON.stringify({"error":"feed_not_found", "error_description":"Feed not found"})); - }; - babel.__set__("request", requestStub); + nock(endPoint) + .get('/feeds/targets/'+md5('TARGET')+'/activity/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [404, { + error:"feed_not_found", + error_description:"Feed not found" + }]; + }); + babelClient.getTargetFeed('TARGET', 'secret', {}, function(err, result){ @@ -452,40 +405,39 @@ describe("Babel Node Client Test Suite", function(){ }); }); it("- should return results if no error from babel and feed is found when get target feed", function(done){ - var babel = rewire("../../index.js"); - - var babelClient = babel.createClient({ - babel_host:"http://babel", - babel_port:3000 - }); - - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {}, JSON.stringify({ - "count":2, - "limit":25, - "offset":0, - "annotations":[{ - "annotatedBy":"rg", - "_id":"54c107db52be6b4d90000001", - "__v":0, - "annotatedAt":"2015-01-22T14:23:23.013Z", - "motivatedBy":"commenting", - "hasTarget":{}, - "hasBody":{} - },{ - "annotatedBy":"rg", - "_id":"54c10857ae44b3f492000001", - "__v":0, - "annotatedAt":"2015-01-22T14:25:27.294Z", - "motivatedBy":"commenting", - "hasTarget":{}, - "hasBody":{} - }] - })); - }; + var babelClient = babel.createClient({ + babel_host:"http://babel", + babel_port:3000 + }); + + nock(endPoint) + .get('/feeds/targets/'+md5('TARGET')+'/activity/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, { + "count":2, + "limit":25, + "offset":0, + "annotations":[{ + "annotatedBy":"rg", + "_id":"54c107db52be6b4d90000001", + "__v":0, + "annotatedAt":"2015-01-22T14:23:23.013Z", + "motivatedBy":"commenting", + "hasTarget":{}, + "hasBody":{} + },{ + "annotatedBy":"rg", + "_id":"54c10857ae44b3f492000001", + "__v":0, + "annotatedAt":"2015-01-22T14:25:27.294Z", + "motivatedBy":"commenting", + "hasTarget":{}, + "hasBody":{} + }] + }]; + }); - babel.__set__("request", requestStub); babelClient.getTargetFeed('TARGET', 'secret', {}, function(err, result){ @@ -497,19 +449,18 @@ describe("Babel Node Client Test Suite", function(){ }); }); it("- should not blow up if invalid JSON returned", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {}, null); - }; + nock(endPoint) + .get('/feeds/targets/'+md5('TARGET')+'/activity/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, null]; + }); - babel.__set__("request", requestStub); babelClient.getTargetFeed('TARGET', 'secret', {}, function(err, result){ @@ -559,42 +510,20 @@ describe("Babel Node Client Test Suite", function(){ getFeeds.should.throw("Missing Persona token"); }); - it("- should return an error if call to request returns an error when get feeds", function(done){ - var babel = rewire("../../index.js"); - - var babelClient = babel.createClient({ - babel_host:"http://babel", - babel_port:3000 - }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(new Error('Error communicating with Babel')); - }; - - babel.__set__("request", requestStub); - - babelClient.getFeeds(['FEED1'], 'secret', function(err, result){ - - (err === null).should.be.false; - err.message.should.equal('Error communicating with Babel'); - (typeof result).should.equal('undefined'); - done(); - }); - }); - it("- should return an error (401) if persona token is invalid when get feeds", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode:401}, JSON.stringify({error:"invalid_token", error_description:"The token is invalid or has expired"})); - }; - - babel.__set__("request", requestStub); + nock(endPoint) + .get('/feeds/annotations/hydrate?feed_ids=FEED1') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [401, { + error:"invalid_token", + error_description:"The token is invalid or has expired" + }]; + }); babelClient.getFeeds(['FEED1'], 'secret', function(err, result){ @@ -607,18 +536,20 @@ describe("Babel Node Client Test Suite", function(){ }); it("- should return an error (404) if babel returns no feeds when get feeds", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {}, JSON.stringify({"error":"feed_not_found", "error_description":"Feed not found"})); - }; - babel.__set__("request", requestStub); + nock(endPoint) + .get('/feeds/annotations/hydrate?feed_ids=FEED1') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [404, { + error:"feed_not_found", + error_description:"Feed not found" + }]; + }); babelClient.getFeeds(['FEED1'], 'secret', function(err, result){ @@ -630,47 +561,45 @@ describe("Babel Node Client Test Suite", function(){ }); }); it("- should return results if no error from babel and feeds are found when get feeds", function(done){ - var babel = rewire("../../index.js"); - - var babelClient = babel.createClient({ - babel_host:"http://babel", - babel_port:3000 - }); - - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {}, JSON.stringify({ - "feed_length":2, - "limit":25, - "offset":0, - "feeds":[{ - feed_id: "FEED1", - status: "success" - },{ - feed_id: "FEED2", - status: "success" - }], - "annotations":[{ - "annotatedBy":"ns", - "_id":"54c107db52be6b4d90000001", - "__v":0, - "annotatedAt":"2015-01-22T14:23:23.013Z", - "motivatedBy":"commenting", - "hasTarget":{}, - "hasBody":{} - },{ - "annotatedBy":"ns", - "_id":"54c10857ae44b3f492000001", - "__v":0, - "annotatedAt":"2015-01-22T14:25:27.294Z", - "motivatedBy":"commenting", - "hasTarget":{}, - "hasBody":{} - }] - })); - }; + var babelClient = babel.createClient({ + babel_host:"http://babel", + babel_port:3000 + }); - babel.__set__("request", requestStub); + nock(endPoint) + .get('/feeds/annotations/hydrate?feed_ids=FEED1%2CFEED2') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, { + "feed_length":2, + "limit":25, + "offset":0, + "feeds":[{ + feed_id: "FEED1", + status: "success" + },{ + feed_id: "FEED2", + status: "success" + }], + "annotations":[{ + "annotatedBy":"ns", + "_id":"54c107db52be6b4d90000001", + "__v":0, + "annotatedAt":"2015-01-22T14:23:23.013Z", + "motivatedBy":"commenting", + "hasTarget":{}, + "hasBody":{} + },{ + "annotatedBy":"ns", + "_id":"54c10857ae44b3f492000001", + "__v":0, + "annotatedAt":"2015-01-22T14:25:27.294Z", + "motivatedBy":"commenting", + "hasTarget":{}, + "hasBody":{} + }] + }]; + }); babelClient.getFeeds(['FEED1', ['FEED2']], 'secret', function(err, result){ @@ -682,19 +611,17 @@ describe("Babel Node Client Test Suite", function(){ }); }); it("- should not blow up if invalid JSON returned", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {}, null); - }; - - babel.__set__("request", requestStub); + nock(endPoint) + .get('/feeds/annotations/hydrate?feed_ids=FEED1%2CFEED2') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, null]; + }); babelClient.getFeeds(['FEED1', ['FEED2']], 'secret', function(err, result){ @@ -733,18 +660,19 @@ describe("Babel Node Client Test Suite", function(){ }); it("- should return an error (401) if persona token is invalid", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode:401}, JSON.stringify({error:"invalid_token", error_description:"The token is invalid or has expired"})); - }; - - babel.__set__("request", requestStub); + nock(endPoint) + .get('/annotations/id') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [401, { + error:"invalid_token", + error_description:"The token is invalid or has expired" + }]; + }); babelClient.getAnnotation("secret", "id", function(err, result){ (err === null).should.be.false; @@ -755,61 +683,36 @@ describe("Babel Node Client Test Suite", function(){ }); }); - it("- should return an error if call to request returns an error", function(done){ - var babel = rewire("../../index.js"); - - var babelClient = babel.createClient({ - babel_host:"http://babel", - babel_port:3000 - }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(new Error("Error communicating with Babel")); - }; - - babel.__set__("request", requestStub); - - babelClient.getAnnotation("secret", "id", function(err, result){ - - (err === null).should.be.false; - err.message.should.equal("Error communicating with Babel"); - (typeof result).should.equal("undefined"); - done(); - }); - }); - it("- should return a single annotation if no error from babel", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestMock = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {}, JSON.stringify({ - "__v": 0, - "annotatedBy": "bp", - "hasTarget": { - "fragment": "p=1", - "uri": "my/uri", - "type": 'Text' - }, - "_id": "5628b931a394fb449e000247", - "annotatedAt": "2015-10-22T10:23:45.154Z", - "motivatedBy": "annotating", - "hasBody": { - "format": "text/plain", - "type": "Text", - "details": { - "platform": "web" + nock(endPoint) + .get('/annotations/5628b931a394fb449e000247') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, { + // "__v": 0, What is this! + "annotatedBy": "bp", + "hasTarget": { + "fragment": "p=1", + "uri": "my/uri", + "type": 'Text' + }, + "_id": "5628b931a394fb449e000247", + "annotatedAt": "2015-10-22T10:23:45.154Z", + "motivatedBy": "annotating", + "hasBody": { + "format": "text/plain", + "type": "Text", + "details": { + "platform": "web" + } } - } - })); - }; - - babel.__set__("request", requestMock); + }]; + }); babelClient.getAnnotation("secret", "5628b931a394fb449e000247", function(err, result){ @@ -819,19 +722,17 @@ describe("Babel Node Client Test Suite", function(){ }); }); it("- should not blow up if invalid JSON returned", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {}, null); - }; - - babel.__set__("request", requestStub); + nock(endPoint) + .get('/annotations/id') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, null]; + }); babelClient.getAnnotation('secret', "id", function(err, result){ @@ -862,6 +763,13 @@ describe("Babel Node Client Test Suite", function(){ babel_port:3000 }); + nock(endPoint) + .get('/annotations?' + querystring.stringify({})) + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, {}]; + }); + var getAnnotations = function(){ return babelClient.getAnnotations('secret', null, function(err, result){}); }; @@ -870,18 +778,19 @@ describe("Babel Node Client Test Suite", function(){ }); it("- should return an error (401) if persona token is invalid when get target feed", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode:401}, JSON.stringify({error:"invalid_token", error_description:"The token is invalid or has expired"})); - }; - - babel.__set__("request", requestStub); + nock(endPoint) + .get('/annotations?' + querystring.stringify({})) + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [401, { + error:"invalid_token", + error_description:"The token is invalid or has expired" + }]; + }); babelClient.getAnnotations('secret', {}, function(err, result){ @@ -893,64 +802,40 @@ describe("Babel Node Client Test Suite", function(){ }); }); - it("- should return an error if call to request returns an error when annotations feed", function(done){ - var babel = rewire("../../index.js"); - + it("- should return results if no error from babel when annotations feed", function(done){ var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(new Error('Error communicating with Babel')); - }; - - babel.__set__("request", requestStub); - - babelClient.getAnnotations('secret', {}, function(err, result){ - - (err === null).should.be.false; - err.message.should.equal('Error communicating with Babel'); - (typeof result).should.equal('undefined'); - done(); - }); - }); - it("- should return results if no error from babel when annotations feed", function(done){ - var babel = rewire("../../index.js"); - - var babelClient = babel.createClient({ - babel_host:"http://babel", - babel_port:3000 - }); - - var requestMock = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {}, JSON.stringify({ - "count":2, - "limit":25, - "offset":0, - "annotations":[{ - "annotatedBy":"rg", - "_id":"54c107db52be6b4d90000001", - "__v":0, - "annotatedAt":"2015-01-22T14:23:23.013Z", - "motivatedBy":"commenting", - "hasTarget":{}, - "hasBody":{} - },{ - "annotatedBy":"rg", - "_id":"54c10857ae44b3f492000001", - "__v":0, - "annotatedAt":"2015-01-22T14:25:27.294Z", - "motivatedBy":"commenting", - "hasTarget":{}, - "hasBody":{} - }] - })); - }; + nock(endPoint) + .get('/annotations?' + querystring.stringify({})) + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, { + "count":2, + "limit":25, + "offset":0, + "annotations":[{ + "annotatedBy":"rg", + "_id":"54c107db52be6b4d90000001", + // "__v":0, What is this! + "annotatedAt":"2015-01-22T14:23:23.013Z", + "motivatedBy":"commenting", + "hasTarget":{}, + "hasBody":{} + },{ + "annotatedBy":"rg", + "_id":"54c10857ae44b3f492000001", + // "__v":0, What is this! + "annotatedAt":"2015-01-22T14:25:27.294Z", + "motivatedBy":"commenting", + "hasTarget":{}, + "hasBody":{} + }] + }]; + }); - babel.__set__("request", requestMock); babelClient.getAnnotations('secret', {}, function(err, result){ @@ -961,20 +846,20 @@ describe("Babel Node Client Test Suite", function(){ done(); }); }); - it("- should not blow up if invalid JSON returned", function(done){ - var babel = rewire("../../index.js"); + it("- should not blow up if invalid JSON returned", function(done){ var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {}, null); - }; + nock(endPoint) + .get('/annotations?' + querystring.stringify({})) + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, null]; + }); - babel.__set__("request", requestStub); babelClient.getAnnotations('secret', {}, function(err, result){ @@ -1109,75 +994,51 @@ describe("Babel Node Client Test Suite", function(){ createAnnotation.should.throw("Invalid data: hasTarget has unrecognised property 'something'"); }); it("- should return an error (401) if persona token is invalid", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = { - post:function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - var error = new Error('The token is invalid or has expired'); - error.http_code = 401; - callback(error); - } - }; - - babel.__set__("request", requestStub); + nock(endPoint) + .post('/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [401, { + error:"invalid_token", + error_description:"The token is invalid or has expired" + }]; + }); babelClient.createAnnotation('secret', {hasBody:{format:'text/plain', type:'Text'}, hasTarget:{uri:'http://example.com'}, annotatedBy:'Gordon Freeman'}, {}, function(err, result){ (err === null).should.be.false; err.http_code.should.equal(401); - err.message.should.equal('The token is invalid or has expired'); - (typeof result).should.equal('undefined'); - done(); - }); - }); - - it("- should return an error if call to request returns an error", function(done){ - var babel = rewire("../../index.js"); - - var babelClient = babel.createClient({ - babel_host:"http://babel", - babel_port:3000 - }); - var requestStub = { - post:function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - var error = new Error('Error communicating with Babel'); - callback(error); - } - }; - - babel.__set__("request", requestStub); + // TODO This is a change - but all the other error handling tests are like this + // if I make this one pass without change - then all the others fail. - babelClient.createAnnotation('secret', {hasBody:{format:'text/plain', type:'Text'}, hasTarget:{uri:'http://example.com'}, annotatedBy:'Gordon Freeman'}, {}, function(err, result){ - - (err === null).should.be.false; - err.message.should.equal('Error communicating with Babel'); + // err.message.should.equal('The token is invalid or has expired'); + err.message.should.equal( + 'Error creating annotation: {"error":"invalid_token","error_description":"The token is invalid or has expired"}' + ); (typeof result).should.equal('undefined'); + done(); }); }); it("- should return an error if call to request returns a none 200 response", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = { - post:function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - var response = {statusCode: 400}; - callback(null, response, {body:'', message:'Bad Request'}); - } - }; - - babel.__set__("request", requestStub); + nock(endPoint) + .post('/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [400, { + body:"", + message:"Bad Request" + }]; + }); babelClient.createAnnotation('secret', {hasBody:{format:'text/plain', type:'Text'}, hasTarget:{uri:'http://example.com'}, annotatedBy:'Gordon Freeman'}, {}, function(err, result){ @@ -1191,20 +1052,18 @@ describe("Babel Node Client Test Suite", function(){ }); it("- should return an error if call to request returns a 502 response with no body", function (done) { - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host: "http://babel", babel_port: 3000, }); - var requestStub = { - post: function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, { statusCode: 502 }, { message: "Bad Gateway" }); - }, - }; - - babel.__set__("request", requestStub); + nock(endPoint) + .post('/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [502, { + message:"Bad Gateway" + }]; + }); babelClient.createAnnotation( "secret", @@ -1226,19 +1085,17 @@ describe("Babel Node Client Test Suite", function(){ }); it("- should return no errors if everything is successful", function(done){ - - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestMock = {}; - requestMock.post = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode: 201}, { - __v: 0, + nock(endPoint) + .post('/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [201, { + // __v: 0, // What is this! annotatedBy: 'Gordon Freeman', _id: '12345678901234567890', annotatedAt: '2015-02-03T10:28:37.725Z', @@ -1257,10 +1114,8 @@ describe("Babel Node Client Test Suite", function(){ text: "Why don't we have a robot or something to push this sample into the core? This looks sort of dangerous." } } - }); - }; - - babel.__set__("request", requestMock); + }]; + }); babelClient.createAnnotation('secret', {hasBody:{format:'text/plain', type:'Text'}, hasTarget:{uri:'http://example.com', type: 'Text'}, annotatedBy:'Gordon Freeman'}, {}, function(err, result){ @@ -1275,40 +1130,36 @@ describe("Babel Node Client Test Suite", function(){ }); it("- should correctly treat the third parameter as the callback when called with three parameters ", function(done){ - - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestMock = {}; - requestMock.post = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode: 201}, { - __v: 0, - annotatedBy: 'Gordon Freeman', - _id: '12345678901234567890', - annotatedAt: '2015-02-03T10:28:37.725Z', - motivatedBy: 'The Combine', - hasTarget: { - uri: 'http://example.com/uri' - }, - hasBody:{ - format: 'text/plain', - type: 'Text', - uri: 'http://example.com/another/uri', - chars: "Eeeee it's dark! Where's that elevator? Eeeee!", - details:{ - who: 'Gordon Freeman', - text: "Why don't we have a robot or something to push this sample into the core? This looks sort of dangerous." + nock(endPoint) + .post('/annotations') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [201, { + // __v: 0, + annotatedBy: 'Gordon Freeman', + _id: '12345678901234567890', + annotatedAt: '2015-02-03T10:28:37.725Z', + motivatedBy: 'The Combine', + hasTarget: { + uri: 'http://example.com/uri' + }, + hasBody:{ + format: 'text/plain', + type: 'Text', + uri: 'http://example.com/another/uri', + chars: "Eeeee it's dark! Where's that elevator? Eeeee!", + details:{ + who: 'Gordon Freeman', + text: "Why don't we have a robot or something to push this sample into the core? This looks sort of dangerous." + } } - } + }]; }); - }; - - babel.__set__("request", requestMock); babelClient.createAnnotation('secret', {hasBody:{format:'text/plain', type:'Text'}, hasTarget:{uri:'http://example.com'}, annotatedBy:'Gordon Freeman'}, function(err, result){ @@ -1511,73 +1362,51 @@ describe("Babel Node Client Test Suite", function(){ updateAnnotation.should.throw("Invalid data: hasTarget has unrecognised property 'something'"); }); it("- should return an error (401) if persona token is invalid", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = { - put:function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - var error = new Error('The token is invalid or has expired'); - error.http_code = 401; - callback(error); - } - }; - babel.__set__("request", requestStub); + nock(endPoint) + .put('/annotations/testid') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [401, { + error:"invalid_token", + error_description:"The token is invalid or has expired" + }]; + }); babelClient.updateAnnotation('secret', {_id: 'testid', hasBody:{format:'text/plain', type:'Text'}, hasTarget:{uri:'http://example.com'}, annotatedBy:'Gordon Freeman'}, function(err, result){ (err === null).should.be.false; err.http_code.should.equal(401); - err.message.should.equal('The token is invalid or has expired'); - (typeof result).should.equal('undefined'); - done(); - }); - }); + // TODO This is a change - but all the other error handling tests are like this + // if I make this one pass without change - then all the others fail. - it("- should return an error if call to request returns an error", function(done){ - var babel = rewire("../../index.js"); - - var babelClient = babel.createClient({ - babel_host:"http://babel", - babel_port:3000 - }); - var requestStub = { - put:function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - var error = new Error('Error communicating with Babel'); - callback(error); - } - }; - - babel.__set__("request", requestStub); - - babelClient.updateAnnotation('secret', {_id: 'testid', hasBody:{format:'text/plain', type:'Text'}, hasTarget:{uri:'http://example.com'}, annotatedBy:'Gordon Freeman'}, function(err, result){ - (err === null).should.be.false; - err.message.should.equal('Error communicating with Babel'); + // err.message.should.equal('The token is invalid or has expired'); + err.message.should.equal( + 'Error updating annotation: {"error":"invalid_token","error_description":"The token is invalid or has expired"}' + ); (typeof result).should.equal('undefined'); done(); }); }); it("- should return an error if call to request returns a none 200 response", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestStub = { - put:function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - var response = {statusCode: 400}; - callback(null, response, {body:'', message:'Bad Request'}); - } - }; - babel.__set__("request", requestStub); + nock(endPoint) + .put('/annotations/testid') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [400, { + body:"", + message:"Bad Request" + }]; + }); babelClient.updateAnnotation('secret', {_id: 'testid', hasBody:{format:'text/plain', type:'Text'}, hasTarget:{uri:'http://example.com'}, annotatedBy:'Gordon Freeman'}, function(err, result){ (err === null).should.be.false; @@ -1590,20 +1419,19 @@ describe("Babel Node Client Test Suite", function(){ }); it("- should return an error if call to request returns a 502 response with no body", function (done) { - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host: "http://babel", babel_port: 3000, }); - var requestStub = { - put: function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, { statusCode: 400 }, { message: "Bad Gateway" }); - }, - }; - babel.__set__("request", requestStub); + nock(endPoint) + .put('/annotations/testid') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [504, { + message:"Bad Gateway" + }]; + }); babelClient.updateAnnotation( "secret", @@ -1625,40 +1453,37 @@ describe("Babel Node Client Test Suite", function(){ }); it("- should return no errors if everything is successful", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 }); - var requestMock = {}; - requestMock.put = function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode: 200}, { - __v: 0, - annotatedBy: 'Gordon Freeman', - _id: '12345678901234567890', - annotatedAt: '2015-02-03T10:28:37.725Z', - motivatedBy: 'The Combine', - hasTarget: { - uri: 'http://example.com/uri', - type: 'Text' - }, - hasBody:{ - format: 'text/plain', - type: 'Text', - uri: 'http://example.com/another/uri', - chars: "Eeeee it's dark! Where's that elevator? Eeeee!", - details:{ - who: 'Gordon Freeman', - text: "Why don't we have a robot or something to push this sample into the core? This looks sort of dangerous." + nock(endPoint) + .put('/annotations/testid') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, { + // __v: 0, What is this? + annotatedBy: 'Gordon Freeman', + _id: '12345678901234567890', + annotatedAt: '2015-02-03T10:28:37.725Z', + motivatedBy: 'The Combine', + hasTarget: { + uri: 'http://example.com/uri', + type: 'Text' + }, + hasBody:{ + format: 'text/plain', + type: 'Text', + uri: 'http://example.com/another/uri', + chars: "Eeeee it's dark! Where's that elevator? Eeeee!", + details:{ + who: 'Gordon Freeman', + text: "Why don't we have a robot or something to push this sample into the core? This looks sort of dangerous." + } } - } + }]; }); - }; - - babel.__set__("request", requestMock); babelClient.updateAnnotation('secret', {_id: 'testid', hasBody:{format:'text/plain', type:'Text'}, hasTarget:{uri:'http://example.com', type: 'Text'}, annotatedBy:'Gordon Freeman'}, function(err, result){ (err === null).should.be.true; @@ -1694,33 +1519,7 @@ describe("Babel Node Client Test Suite", function(){ deleteAnnotation.should.throw("Missing annotationId"); }); - it("- should return an error if call to request returns an error", function(done){ - var babel = rewire("../../index.js"); - - var babelClient = babel.createClient({ - babel_host:"http://babel", - babel_port:3000 - }); - var requestStub = { - delete:function(options, callback){ - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - var error = new Error('Error communicating with Babel'); - callback(error); - } - }; - - babel.__set__("request", requestStub); - - babelClient.deleteAnnotation('secret', 'testid', function(err, result){ - (err === null).should.be.false; - err.message.should.equal('Error communicating with Babel'); - (typeof result).should.equal('undefined'); - done(); - }); - }); it("- should return an error if call to babel returns an error", function(done){ - var babel = rewire("../../index.js"); - var babelClient = babel.createClient({ babel_host:"http://babel", babel_port:3000 @@ -1733,11 +1532,12 @@ describe("Babel Node Client Test Suite", function(){ error_description: 'Could not find annotation' }; - requestMock.delete = function(options, callback){ - callback(null, {}, babelErr); - }; - - babel.__set__("request", requestMock); + nock(endPoint) + .delete('/annotations/testid') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [500, babelErr]; + }); babelClient.deleteAnnotation('secret', 'testid', function(err, result){ (err === null).should.be.false; diff --git a/echo/index.js b/echo/index.js index 44e845a..03f0626 100644 --- a/echo/index.js +++ b/echo/index.js @@ -1,6 +1,5 @@ 'use strict'; -var request = require('request'); var _ = require('lodash'); var codesAndLabels = require('./lib/codes-labels').codesAndLabels; var httpStatusToCode = require('./lib/codes-labels').httpStatusToCode; @@ -67,6 +66,8 @@ function queryStringParams(params) { function Client() { var config = {}; + var http; + var endpointUrl; var userAgent = (process && _.has(process, ["version", "env.NODE_ENV"])) ? "talis-node/" + clientVer + " (nodejs/" + process.version + "; NODE_ENV=" + process.env.NODE_ENV + ")" : "talis-node/" + clientVer; @@ -158,6 +159,10 @@ function Client() { throw new Error('Missing Echo config: ' + key); } }); + + endpointUrl = new URL(config.echo_endpoint); + var scheme = endpointUrl.protocol; + http = require(scheme === 'https:' ? 'https' : 'http'); } /** @@ -192,36 +197,60 @@ function Client() { } var requestOptions = { - url: config.echo_endpoint + '/1/events', + hostname: endpointUrl.hostname, + port: endpointUrl.port ? endpointUrl.port : (endpointUrl.protocol === 'https:' ? 443 : 80), + path: '/1/events', + method: "POST", headers: { + 'Content-Type': 'application/json', Accept: 'application/json', Authorization: 'Bearer ' + token, 'User-Agent': userAgent, }, - body: data, - method: 'POST', - json: true }; debug('request options', requestOptions); - request.post(requestOptions, function onResp(err, response, body) { - var statusCode = response && response.statusCode ? response.statusCode : 0; - if (err || parseInt(statusCode / 100) !== 2) { - var errorCode = getCodeFromHttpStatusCode(err, statusCode, body); + var body = ''; + const r = http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); + + resp.on('error', (e) => { + error('[echoClient] addEvents error', e); + var errorCode = codesAndLabels.REQUEST_ERROR; var errorResponse = { code: errorCode, label: codesAndLabels[errorCode], }; - error('[echoClient] addEvents error', errorResponse); + error('[echoClient] addEvents error response', errorResponse); callback(errorResponse); - return; - } else { - callback(null, {"code": codesAndLabels.SUCCESS, "label": codesAndLabels[codesAndLabels.SUCCESS], body: body}); - } + }); + + resp.on("end", d => { + if (parseInt(resp.statusCode / 100) !== 2) { + var errorCode = getCodeFromHttpStatusCode(null, resp.statusCode, body); + + var errorResponse = { + code: errorCode, + label: codesAndLabels[errorCode], + }; + + error('[echoClient] addEvent error', errorResponse); + callback(errorResponse); + return; + } else { + callback(null, {"code": codesAndLabels.SUCCESS, "label": codesAndLabels[codesAndLabels.SUCCESS], body: data}); + return; + } + }); }); + + r.write(JSON.stringify(data)); + r.end(); }; /** @@ -269,47 +298,63 @@ function Client() { } var requestOptions = { - url: config.echo_endpoint + '/1/analytics/' + queryOperator + '?' + constructQueryStringResponse.queryString, - method: 'GET', + hostname: endpointUrl.hostname, + port: endpointUrl.port ? endpointUrl.port : (endpointUrl.protocol === 'https:' ? 443 : 80), + path: '/1/analytics/' + queryOperator + '?' + constructQueryStringResponse.queryString, + method: "GET", headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + token, 'User-Agent': userAgent, - } + }, }; - if (useCache === false) { - requestOptions.headers['cache-control'] = 'none'; - } - debug('request options', requestOptions); - request.get(requestOptions, function onResp(err, response, rawBody) { - var statusCode = response && response.statusCode ? response.statusCode : 0; - if (err || parseInt(statusCode / 100) !== 2) { - var errorCode = getCodeFromHttpStatusCode(err, statusCode, rawBody); - + var body = ''; + const r = http.request(requestOptions, resp => { + resp.on("data", d => { + body += d; + }); + + resp.on('error', (e) => { + error('[echoClient] addEvents error', e); + var errorCode = codesAndLabels.REQUEST_ERROR; + var errorResponse = { code: errorCode, label: codesAndLabels[errorCode], }; - error('[echoClient] queryAnalytics error', errorResponse); + error('[echoClient] addEvents error response', errorResponse); callback(errorResponse); - return; - } else { - delete rawBody.statusCode; - var body; - try { - body = JSON.parse(rawBody); - } catch (exception) { - error("Error parsing returned JSON", exception); - callback("Error parsing returned JSON"); + }); + + resp.on("end", d => { + if (parseInt(resp.statusCode / 100) !== 2) { + var errorCode = getCodeFromHttpStatusCode(null, resp.statusCode, body); + + var errorResponse = { + code: errorCode, + label: codesAndLabels[errorCode], + }; + + error('[echoClient] queryAnalytics error', errorResponse); + callback(errorResponse); return; + } else { + try { + callback(null, {"code": codesAndLabels.SUCCESS, "label": codesAndLabels[codesAndLabels.SUCCESS], body: JSON.parse(body)}); + return; + } catch (e) { + callback('Error parsing returned JSON'); + return; + } } - callback(null, {"code": codesAndLabels.SUCCESS, "label": codesAndLabels[codesAndLabels.SUCCESS], "body": body}); - } + }); }); + + r.end(); }; return EchoClient; diff --git a/echo/test/smoke/echo-local-test.js b/echo/test/smoke/echo-local-test.js new file mode 100644 index 0000000..46bfc9a --- /dev/null +++ b/echo/test/smoke/echo-local-test.js @@ -0,0 +1,123 @@ +var should = require('should'); +var assert = require('assert'); +var echo = require('../../index.js'); +var sinon = require('sinon'); +const fs = require('fs'); + +describe("Echo Node Client Smoke Test Against Local Echo", function(){ + // Run these smoke tests setting the PERSONA_TOKEN environment variable + // PERSONA_TOKEN=$(persona-token local) npm run echo-smoke-test + var token = process.env.PERSONA_TOKEN; + + var echoClient = echo.createClient({ + echo_endpoint: "http://echo.talis.local" + }); + + it("- should post an event", async function(){ + var event = { + class: "class", + source: "talis-node-smoke-test", + timestamp: 1324524509, + props: { + url: "https://foo.bar/baz.html" + } + } + + var result = await addEvents(token, event); + result.code.should.equal(0); + result.label.should.equal("SUCCESS"); + }); + + it("- should error when invalid post of event", async function(){ + var badEvent = { + class_missing_from_post: "class", + source: "talis-node-smoke-test", + timestamp: 1324524509, + props: { + url: "https://foo.bar/baz.html" + } + } + + try { + echoClient.addEvents(token, badEvent, function(){}); + fail(); + } catch (err) { + err.message.should.equal("Missing field data.class"); + } + }); + + it("- should error when query analytics with invalid params", async function(){ + var params = { + class: 'testclass', + source: 'testsources', + property: 'testproperty', + interval: 'testinterval', + group_by: 'testgroupby', + key: 'testkey', + value: 'testvalue', + from: 'testfrom', + to: 'testto', + percentile: 'testpercentile', + user: 'testuser', + 'user.include': 'includeuser', + 'user.exclude': 'excludeuser', + filter: 'testfilter', + 'filter.test': 'testfilter', + n: 'testn', + 'n.something': 'something' + }; + + try { + await queryAnalytics(token, 'sum', params, false); + fail(); + } catch (err) { + err.code.should.equal(2); + err.label.should.equal("INVALID_QUERY"); + } + }); + + it('- should not throw an error if valid query parameters supplied', async function(){ + var params = { + "class": "player.timer", + "group_by": "user,index", + "property": "interval", + "key": "resource_id", + "value": "YOUR_RESOURCE_ID_HERE", + }; + + var result = await queryAnalytics(token, 'sum', params, false); + + + result.code.should.equal(0); + result.label.should.equal("SUCCESS"); + + (typeof result.body).should.equal("object"); + result.body.head.type.should.equal("sum"); + result.body.head.class.should.equal("player.timer"); + result.body.head.key.should.equal("resource_id"); + result.body.head.value.should.equal("YOUR_RESOURCE_ID_HERE"); + result.body.head.count.should.equal(0); + }); + + function addEvents(token, event){ + return new Promise((resolve, reject) => { + echoClient.addEvents(token, event, function(err, result){ + if(err){ + reject(err); + } + resolve(result); + }); + }); + } + + function queryAnalytics(token, type, params, debug){ + return new Promise((resolve, reject) => { + echoClient.queryAnalytics(token, type, params, debug, function(err, result){ + if(err){ + reject(err); + } + resolve(result); + }); + }); + } +}); diff --git a/echo/test/unit/echo_client_test.js b/echo/test/unit/echo_client_test.js index 3952e22..ba003d8 100644 --- a/echo/test/unit/echo_client_test.js +++ b/echo/test/unit/echo_client_test.js @@ -2,9 +2,9 @@ var should = require('should'); var assert = require('assert'); +var nock = require("nock"); var echo = require('../../index.js'); var sinon = require('sinon'); -var request = require('request'); var sandbox; var endPoint = 'http://echo:3002'; @@ -90,123 +90,35 @@ describe("Echo Node Client Test Suite", function(){ echo_endpoint: endPoint }); - var requestStub = sandbox.stub(request, 'post'); - requestStub.yields(new Error('Error communicating with Echo')); + var mockHttpRequest = nock(endPoint) + .post('/1/events') + .reply(400, {}); echoClient.addEvents('secret', {class:'class', source:'source'}, function(err, result){ (err === null).should.be.false; - err.code.should.equal(1); - err.label.should.equal('REQUEST_ERROR'); + err.code.should.equal(2); + err.label.should.equal('INVALID_QUERY'); (typeof result).should.equal('undefined'); done(); }); }); - it("- add events should return an error if call to request has missing option.body", function(done){ - var echoClient = echo.createClient({ - echo_endpoint: endPoint - }); - - var requestStub = sandbox.stub(request, 'post') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - if(!options.body){ - var error = new Error('Missing field: options.body'); - callback(error); - } else{ - callback(null); - } - }); - - echoClient.addEvents('secret', {class:'class', source:'source'}, function(err){ - (err === null).should.be.false; - done(); - }); - }); - it("- add events should return an error if call to request has missing option.method", function(done){ - var echoClient = echo.createClient({ - echo_endpoint: endPoint - }); - - var requestStub = sandbox.stub(request, 'post') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - if(!options.method){ - var error = new Error('Missing field: options.method'); - callback(error); - } else{ - callback(null); - } - }); - - echoClient.addEvents('secret', {class:'class', source:'source'}, function(err){ - (err === null).should.be.false; - done(); - }); - }); - it("- add events should return an error if call to request has option.method != POST", function(done){ - var echoClient = echo.createClient({ - echo_endpoint: endPoint - }); - - var requestStub = sandbox.stub(request, 'post') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - if(options.method !== 'POST'){ - var error = new Error('Invalid field: options.method'); - callback(error); - } else{ - callback(null); - } - }); - - echoClient.addEvents('secret', {class:'class', source:'source'}, function(err){ - (err === null).should.be.false; - done(); - }); - }); - it("- add events should return an error if call to request has missing option.json", function(done){ - var echoClient = echo.createClient({ - echo_endpoint: endPoint - }); - - var requestStub = sandbox.stub(request, 'post') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - if(!options.json){ - var error = new Error('Missing field: options.json'); - callback(error); - } else{ - callback(null); - } - }); - - echoClient.addEvents('secret', {class:'class', source:'source'}, function(err){ - (err === null).should.be.false; - done(); - }); - }); it(" - should throw an error if persona validation fails", function(done) { var echoClient = echo.createClient({ echo_endpoint: endPoint }); - var requestStub = sandbox.stub(request, 'post') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback( - null, - {statusCode: 401}, - { - "error": "invalid_token" - } - ); - }); + nock(endPoint) + .post('/1/events') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [401, {"error": "invalid_token"}]; + }); echoClient.addEvents("incorrect_token", {class:'class', source:'source'}, function(err, result) { (err === null).should.be.false; - err.code.should.equal(8); - err.label.should.equal("INVALID_TOKEN"); + err.code.should.equal(6); + err.label.should.equal("UNAUTHORISED"); done(); }); }); @@ -215,25 +127,24 @@ describe("Echo Node Client Test Suite", function(){ echo_endpoint: endPoint }); - var requestStub = sandbox.stub(request, 'post') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback( - null, - {statusCode: 200}, - { - "class": "page.views", - "timestamp": 1324524509, - "user": "1234-5678-9012-3456", - "source" : "rl-app", - "props": { - "url" : "https://foo.bar/baz.html" - } - } - ); - }); + nock(endPoint) + .post('/1/events') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, {}]; + }); - echoClient.addEvents('secret', {class:'class', source:'source'}, function(err, result){ + var event = { + 'class': 'calss', + 'source': 'rl-app', + 'timestamp': 1324524509, + 'user': '1234-5678-9012-3456', + 'props': { + 'url': 'https://foo.bar/baz.html' + } + }; + + echoClient.addEvents('secret', event, function(err, result){ (err === null).should.be.true; @@ -318,12 +229,13 @@ describe("Echo Node Client Test Suite", function(){ echo_endpoint: endPoint }); - var requestStub = sandbox.stub(request, 'get') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - var data = "{\"head\": {\"type\": \"sum\",\"class\": \"player.timer.2\",\"property\": \"interval_with_decay\",\"group_by\": \"user\",\"filter\": {\"module_id\": \"5847ed0ef81ebd1f1b000001\",\"resource_id\": \"5899a87fd42410f2c9000001\"},\"from\": \"2016-08-29T00:00:00\",\"to\": \"2017-05-18T00:00:00\",\"count\": 2},\"results\": [{\"user\": \"8av3Jaj__vC9v9VIY_P-1w\",\"interval_with_decay\": 182920},{\"user\": \"d17T05nNTjG50sAp_R3RvQ\",\"interval_with_decay\": 21315}]}"; - callback(null, {statusCode: 200}, data); - }); + nock(endPoint) + .get('/1/analytics/sum?class=testclass&source=testsources&property=testproperty&interval=testinterval&group_by=testgroupby&key=testkey&value=testvalue&from=testfrom&to=testto&percentile=testpercentile&user=testuser&user.include=includeuser&user.exclude=excludeuser&filter=testfilter&filter.test=testfilter&n=testn&n.something=something') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + var data = "{\"head\": {\"type\": \"sum\",\"class\": \"player.timer.2\",\"property\": \"interval_with_decay\",\"group_by\": \"user\",\"filter\": {\"module_id\": \"5847ed0ef81ebd1f1b000001\",\"resource_id\": \"5899a87fd42410f2c9000001\"},\"from\": \"2016-08-29T00:00:00\",\"to\": \"2017-05-18T00:00:00\",\"count\": 2},\"results\": [{\"user\": \"8av3Jaj__vC9v9VIY_P-1w\",\"interval_with_decay\": 182920},{\"user\": \"d17T05nNTjG50sAp_R3RvQ\",\"interval_with_decay\": 21315}]}"; + return [200, data]; + }); var params = { class: 'testclass', @@ -347,45 +259,38 @@ describe("Echo Node Client Test Suite", function(){ var queryAnalytics = function(){ return echoClient.queryAnalytics('secret', 'sum', params, false, function(err, result){ - var firstCall = requestStub.firstCall; (err === null).should.be.true; - requestStub.callCount.should.equal(1); - firstCall.args[0].method.should.equal('GET'); - firstCall.args[0].url.should.equal(endPoint + '/1/analytics/sum?class=testclass&source=testsources&property=testproperty&interval=testinterval&group_by=testgroupby&key=testkey&value=testvalue&from=testfrom&to=testto&percentile=testpercentile&user=testuser&user.include=includeuser&user.exclude=excludeuser&filter=testfilter&filter.test=testfilter&n=testn&n.something=something'); - firstCall.args[0].headers['cache-control'].should.equal('none'); + result.body.results.length.should.equal(2); + result.body.results[0].user.should.equal('8av3Jaj__vC9v9VIY_P-1w'); + result.body.results[0].interval_with_decay.should.equal(182920); + result.body.results[1].user.should.equal('d17T05nNTjG50sAp_R3RvQ'); + result.body.results[1].interval_with_decay.should.equal(21315); + done(); }); }; - queryAnalytics(); - queryAnalytics.should.not.throw('Invalid Analytics queryParams'); - - done(); }); it('- should return an error if call to request returns an error', function(done){ var echoClient = echo.createClient({ echo_endpoint: endPoint }); - var requestStub = sandbox.stub(request, 'get') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(new Error('Error communicating with Echo')); - }); + nock(endPoint) + .get('/1/analytics/sum?class=testclass') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [400, {}]; + }); var params = { class: 'testclass' }; echoClient.queryAnalytics('secret', 'sum', params, false, function(err, result){ - var firstCall = requestStub.firstCall; (err === null).should.be.false; - requestStub.callCount.should.equal(1); - firstCall.args[0].method.should.equal('GET'); - firstCall.args[0].url.should.equal(endPoint + '/1/analytics/sum?class=testclass'); - firstCall.args[0].headers['cache-control'].should.equal('none'); - err.code.should.equal(1); - err.label.should.equal('REQUEST_ERROR'); + err.code.should.equal(2); + err.label.should.equal('INVALID_QUERY'); (typeof result).should.equal('undefined'); done(); }); @@ -399,23 +304,18 @@ describe("Echo Node Client Test Suite", function(){ class: 'testclass' }; - var requestStub = sandbox.stub(request, 'get') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback( - null, - {statusCode: 401}, - { - "error": "invalid_token" - } - ); - }); + nock(endPoint) + .get('/1/analytics/sum?class=testclass') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [401, {"error": "invalid_token"}]; + }); echoClient.queryAnalytics("incorrect_token", "sum", params, false, function(err, result) { (err === null).should.be.false; - err.code.should.equal(8); - err.label.should.equal("INVALID_TOKEN"); + err.code.should.equal(6); + err.label.should.equal("UNAUTHORISED"); done(); }); }); @@ -424,12 +324,13 @@ describe("Echo Node Client Test Suite", function(){ echo_endpoint: endPoint }); - var requestStub = sandbox.stub(request, 'get') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - var data = "{\"head\": {\"type\": \"sum\",\"class\": \"player.timer.2\",\"property\": \"interval_with_decay\",\"group_by\": \"user\",\"filter\": {\"module_id\": \"5847ed0ef81ebd1f1b000001\"},\"user\": {\"exclude\": \"qVyfsQhlMY0T2_Bl7eotrg\"},\"from\": \"2017-02-01T00:00:00\",\"to\": \"2017-02-13T00:00:00\",\"count\": 2},\"results\": [{\"user\": \"8av3Jaj__vC9v9VIY_P-1w\",\"interval_with_decay\": 182920},{\"user\": \"d17T05nNTjG50sAp_R3RvQ\",\"interval_with_decay\": 21315}]}"; - callback(null, {statusCode: 200}, data); - }); + nock(endPoint) + .get('/1/analytics/sum?class=player.timer.2&property=interval_with_decay&group_by=user&filter.module_id=5847ed0ef81ebd1f1b000001&user.exclude=qVyfsQhlMY0T2_Bl7eotrg&from=2017-02-01T00%3A00%3A00&to=2017-02-13T00%3A00%3A00') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + var data = "{\"head\": {\"type\": \"sum\",\"class\": \"player.timer.2\",\"property\": \"interval_with_decay\",\"group_by\": \"user\",\"filter\": {\"module_id\": \"5847ed0ef81ebd1f1b000001\"},\"user\": {\"exclude\": \"qVyfsQhlMY0T2_Bl7eotrg\"},\"from\": \"2017-02-01T00:00:00\",\"to\": \"2017-02-13T00:00:00\",\"count\": 2},\"results\": [{\"user\": \"8av3Jaj__vC9v9VIY_P-1w\",\"interval_with_decay\": 182920},{\"user\": \"d17T05nNTjG50sAp_R3RvQ\",\"interval_with_decay\": 21315}]}"; + return [200, data]; + }); var params = { class: 'player.timer.2', @@ -442,11 +343,7 @@ describe("Echo Node Client Test Suite", function(){ }; echoClient.queryAnalytics('secret', 'sum', params, false, function(err, result){ - var firstCall = requestStub.firstCall; (err === null).should.be.true; - requestStub.callCount.should.equal(1); - firstCall.args[0].method.should.equal('GET'); - firstCall.args[0].headers['cache-control'].should.equal('none'); (result.body.results instanceof Array).should.be.true; result.body.results.length.should.equal(2); result.body.results[0].user.should.equal('8av3Jaj__vC9v9VIY_P-1w'); @@ -465,12 +362,13 @@ describe("Echo Node Client Test Suite", function(){ echo_endpoint: endPoint }); - var requestStub = sandbox.stub(request, 'get') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); + nock(endPoint) + .get('/1/analytics/sum?class=player.timer.2&property=interval_with_decay&group_by=user&filter.module_id=5847ed0ef81ebd1f1b000001&user.exclude=qVyfsQhlMY0T2_Bl7eotrg&from=2017-02-01T00%3A00%3A00&to=2017-02-13T00%3A00%3A00') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); var data = "{\"head\": {\"type\": \"sum\",\"class\": \"player.timer.2\",\"property\": \"interval_with_decay\",\"group_by\": \"user\",\"filter\": {\"module_id\": \"5847ed0ef81ebd1f1b000001\"},\"user\": {\"exclude\": \"qVyfsQhlMY0T2_Bl7eotrg\"},\"from\": \"2017-02-01T00:00:00\",\"to\": \"2017-02-13T00:00:00\",\"count\": 2},\"results\": [{\"user\": \"8av3Jaj__vC9v9VIY_P-1w\",\"interval_with_decay\": 182920},{\"user\": \"d17T05nNTjG50sAp_R3RvQ\",\"interval_with_decay\": 21315}]}"; - callback(null, {statusCode: 200}, data); - }); + return [200, data]; + }); var params = { class: 'player.timer.2', @@ -483,11 +381,7 @@ describe("Echo Node Client Test Suite", function(){ }; echoClient.queryAnalytics('secret', 'sum', params, true, function(err, result){ - var firstCall = requestStub.firstCall; (err === null).should.be.true; - requestStub.callCount.should.equal(1); - firstCall.args[0].method.should.equal('GET'); - firstCall.args[0].headers.should.not.have.property('cache-control'); (result.body.results instanceof Array).should.be.true; result.body.results.length.should.equal(2); result.body.results[0].user.should.equal('8av3Jaj__vC9v9VIY_P-1w'); @@ -508,11 +402,12 @@ describe("Echo Node Client Test Suite", function(){ var data = "Test"; - var requestStub = sandbox.stub(request, 'get') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode: 200}, data); - }); + nock(endPoint) + .get('/1/analytics/sum?class=player.timer.2&property=interval_with_decay&group_by=user&filter.module_id=5847ed0ef81ebd1f1b000001&user.exclude=qVyfsQhlMY0T2_Bl7eotrg&from=2017-02-01T00%3A00%3A00&to=2017-02-13T00%3A00%3A00') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [200, data]; + }); var params = { class: 'player.timer.2', @@ -525,12 +420,8 @@ describe("Echo Node Client Test Suite", function(){ }; echoClient.queryAnalytics('secret', 'sum', params, false, function(err, result){ - var firstCall = requestStub.firstCall; (err === null).should.be.false; (typeof result).should.equal('undefined'); - requestStub.callCount.should.equal(1); - firstCall.args[0].method.should.equal('GET'); - firstCall.args[0].headers['cache-control'].should.equal('none'); err.should.equal('Error parsing returned JSON'); done(); }); @@ -542,11 +433,12 @@ describe("Echo Node Client Test Suite", function(){ var data = "[]"; - var requestStub = sandbox.stub(request, 'get') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode: 400}, data); - }); + nock(endPoint) + .get('/1/analytics/sum?class=player.timer.2&property=interval_with_decay&group_by=user&filter.module_id=5847ed0ef81ebd1f1b000001&user.exclude=qVyfsQhlMY0T2_Bl7eotrg&from=2017-02-01T00%3A00%3A00&to=2017-02-13T00%3A00%3A00') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [400, data]; + }); var params = { class: 'player.timer.2', @@ -559,12 +451,8 @@ describe("Echo Node Client Test Suite", function(){ }; echoClient.queryAnalytics('secret', 'sum', params, false, function(err, result){ - var firstCall = requestStub.firstCall; (err === null).should.be.false; (typeof result).should.equal('undefined'); - requestStub.callCount.should.equal(1); - firstCall.args[0].method.should.equal('GET'); - firstCall.args[0].headers['cache-control'].should.equal('none'); err.should.deepEqual({ code: 2, label: "INVALID_QUERY"}); done(); }); @@ -576,11 +464,13 @@ describe("Echo Node Client Test Suite", function(){ var data = "this is invalid"; - var requestStub = sandbox.stub(request, 'get') - requestStub.callsFake(function (options, callback) { - options.headers.should.have.property('User-Agent', 'talis-node/0.2.1'); - callback(null, {statusCode: 400}, data); - }); + nock(endPoint) + .get('/1/analytics/sum?class=player.timer.2&property=interval_with_decay&group_by=user&filter.module_id=5847ed0ef81ebd1f1b000001&user.exclude=qVyfsQhlMY0T2_Bl7eotrg&from=2017-02-01T00%3A00%3A00&to=2017-02-13T00%3A00%3A00') + .reply(function(uri, requestBody){ + this.req.headers['user-agent'].should.equal('talis-node/0.2.3'); + return [400, data]; + }); + var params = { class: 'player.timer.2', @@ -593,12 +483,8 @@ describe("Echo Node Client Test Suite", function(){ }; echoClient.queryAnalytics('secret', 'sum', params, false, function(err, result){ - var firstCall = requestStub.firstCall; (err === null).should.be.false; (typeof result).should.equal('undefined'); - requestStub.callCount.should.equal(1); - firstCall.args[0].method.should.equal('GET'); - firstCall.args[0].headers['cache-control'].should.equal('none'); err.should.deepEqual({ code: 2, label: "INVALID_QUERY"}); done(); }); diff --git a/package-lock.json b/package-lock.json index 597f6cb..b4409f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "talis-node", - "version": "0.2.1", + "version": "0.2.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -54,65 +54,18 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "array-from": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", "integrity": "sha512-GQTc6Uupx1FCavi5mPzBvVT7nEOeWMmUA9P95wpfpW1XwMSKs+KaymD5C2Up7KAUKg/mYwbsUYzdZWcoajlNZg==", "dev": true }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" - }, - "aws4": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", - "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==" - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "requires": { - "tweetnacl": "^0.14.3" - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -159,11 +112,6 @@ "ioredis": "^4.14.1" } }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, "charenc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", @@ -189,14 +137,6 @@ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -239,14 +179,6 @@ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==" }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "requires": { - "assert-plus": "^1.0.0" - } - }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -270,11 +202,6 @@ } } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, "denque": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", @@ -335,15 +262,6 @@ "domelementtype": "1" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -382,26 +300,6 @@ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, "fill-keys": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", @@ -412,21 +310,6 @@ "merge-descriptors": "~1.0.0" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "formatio": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", @@ -442,14 +325,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -470,20 +345,6 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -509,16 +370,6 @@ "readable-stream": "1.1" } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -580,22 +431,12 @@ "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", "dev": true }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, "js-beautify": { "version": "1.8.9", "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.8.9.tgz", @@ -609,11 +450,6 @@ "nopt": "~4.0.1" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, "jshint": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.10.1.tgz", @@ -641,20 +477,11 @@ } } }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true }, "jsonwebtoken": { "version": "9.0.2", @@ -680,17 +507,6 @@ } } }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, "just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", @@ -809,19 +625,6 @@ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1009,11 +812,6 @@ "osenv": "^0.1.4" } }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1071,11 +869,6 @@ "isarray": "0.0.1" } }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, "propagate": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", @@ -1105,24 +898,6 @@ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", "dev": true }, - "psl": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.10.0.tgz", - "integrity": "sha512-KSKHEbjAnpUuAUserOq0FxGXCUrzC3WniuSJhvdbs102rL55266ZcHBqLWOsG30spQMlPdpy7icATiAQehg/iA==", - "requires": { - "punycode": "^2.3.1" - } - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" - }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" - }, "readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", @@ -1153,58 +928,6 @@ "redis-errors": "^1.0.0" } }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, - "request-promise-core": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", - "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "requires": { - "lodash": "^4.17.19" - } - }, - "request-promise-native": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", - "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", - "requires": { - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - } - }, "resolve": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", @@ -1214,22 +937,11 @@ "path-parse": "^1.0.5" } }, - "rewire": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/rewire/-/rewire-2.1.4.tgz", - "integrity": "sha512-DC6h21n5pgAuZTt3SkrJ0JBZu3x1SRdW5teT8TRkVTQS7EYP7RQMEJprg+OXwNw4Tz2H1lpOU0wsYnpbO4GGdg==", - "dev": true - }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, "samsam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", @@ -1325,32 +1037,11 @@ "type-detect": "^4.0.0" } }, - "sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==" - }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -1378,64 +1069,17 @@ "integrity": "sha512-hJnc6Qg3dWoOMkqP53F0dzRIgtmsAge09kxUIqGrEUS4qr5rWLckGYaQAVr+opBrIMRErGgy6f5aPnyPpyGRfg==", "dev": true }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, "type-detect": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, "uuid": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.2.tgz", "integrity": "sha512-BooSif/UQWXwaQme+4z32duvmtUUz/nlHsyGrrSCgsGf6snMrp9q/n1nGHwQzU12kaCeceODmAiRZA8TCK06jA==" }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - } - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 41deac5..2b05e21 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,15 @@ { "name": "talis-node", - "version": "0.2.1", + "version": "0.2.3", "description": "", "main": "index.js", "scripts": { - "test": "./node_modules/.bin/mocha --exit --timeout 20000 **/test/**/*.js", + "test": "npm run unit-test && npm run integration-test", "integration-test": "./node_modules/.bin/mocha --exit --timeout 20000 **/test/integration/**/*.js", "unit-test": "./node_modules/.bin/mocha --exit --timeout 20000 **/test/unit/**/*.js", + "echo-smoke-test": "./node_modules/.bin/mocha --exit --timeout 20000 echo/test/smoke/**/*.js", + "babel-smoke-test": "./node_modules/.bin/mocha --exit --timeout 20000 babel/test/smoke/**/*.js", + "persona-smoke-test": "./node_modules/.bin/mocha --exit --timeout 20000 persona/test/smoke/**/*.js", "lint": "./node_modules/.bin/jshint index.js", "lint-fix": "./node_modules/.bin/js-beautify -r index.js" }, @@ -18,8 +21,6 @@ "lodash": "4.17.21", "md5": "2.2.1", "node-cache": "4.2.0", - "request": "2.88.2", - "request-promise-native": "^1.0.8", "uuid": "2.0.2" }, "devDependencies": { @@ -30,7 +31,6 @@ "mocha": "5.2.0", "nock": "13.3.3", "proxyquire": "2.1.0", - "rewire": "2.1.4", "should": "13.2.3", "sinon": "3.0.0" },