From 6894b02dbc43845407b679da783c8cc3e90b52bf Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Wed, 5 Dec 2018 18:54:11 -0800 Subject: [PATCH 01/24] Removes unused simple-oauth2 dependency --- package-lock.json | 2 +- package.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index de6326e3..7a9c4c3e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "gambit-content", - "version": "6.0.0", + "version": "6.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ab7b9bcf..40945757 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "redis": "^2.8.0", "s3-upload-stream": "^1.0.7", "serve-favicon": "^2.5.0", - "simple-oauth2": "^1.5.2", "superagent": "^3.8.3", "throng": "^4.0.0", "underscore": "^1.9.0", From 7408c8b0316144f7c89b899dee2a05bee2427c87 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Wed, 5 Dec 2018 19:13:40 -0800 Subject: [PATCH 02/24] Updates packages --- package-lock.json | 155 +++++++++++----------------------------------- package.json | 18 +++--- 2 files changed, 44 insertions(+), 129 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7a9c4c3e..9b3c153a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -670,7 +670,7 @@ "babel-core": "6.26.3", "babel-generator": "6.26.1", "babel-plugin-syntax-object-rest-spread": "6.13.0", - "bluebird": "3.5.1", + "bluebird": "3.5.3", "caching-transform": "1.0.1", "chalk": "2.4.1", "chokidar": "1.7.0", @@ -1860,9 +1860,9 @@ } }, "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" }, "body-parser": { "version": "1.18.3", @@ -2134,9 +2134,9 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chai": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", - "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", "dev": true, "requires": { "assertion-error": "1.1.0", @@ -2159,9 +2159,9 @@ } }, "chance": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/chance/-/chance-1.0.16.tgz", - "integrity": "sha512-2bgDHH5bVfAXH05SPtjqrsASzZ7h90yCuYT2z4mkYpxxYvJXiIydBFzVieVHZx7wLH1Ag2Azaaej2/zA1XUrNQ==", + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.0.18.tgz", + "integrity": "sha512-g9YLQVHVZS/3F+zIicfB58vjcxopvYQRp7xHzvyDFDhXH1aRZI/JhwSAO0X5qYiQluoGnaNAU6wByD2KTxJN1A==", "dev": true }, "chardet": { @@ -2333,13 +2333,14 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "codecov": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.0.4.tgz", - "integrity": "sha512-KJyzHdg9B8U9LxXa7hS6jnEW5b1cNckLYc2YpnJ1nEFiOW+/iSzDHp+5MYEIQd9fN3/tC6WmGZmYiwxzkuGp/A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.1.0.tgz", + "integrity": "sha512-aWQc/rtHbcWEQLka6WmBAOpV58J2TwyXqlpAQGhQaSiEUoigTTUk6lLd2vB3kXkhnDyzyH74RXfmV4dq2txmdA==", "dev": true, "requires": { "argv": "0.0.2", "ignore-walk": "3.0.1", + "js-yaml": "3.12.0", "request": "2.87.0", "urlgrey": "0.4.4" } @@ -3263,13 +3264,13 @@ } }, "express": { - "version": "4.16.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", - "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", "requires": { "accepts": "1.3.5", "array-flatten": "1.1.1", - "body-parser": "1.18.2", + "body-parser": "1.18.3", "content-disposition": "0.5.2", "content-type": "1.0.4", "cookie": "0.3.1", @@ -3287,9 +3288,9 @@ "parseurl": "1.3.2", "path-to-regexp": "0.1.7", "proxy-addr": "2.0.4", - "qs": "6.5.1", + "qs": "6.5.2", "range-parser": "1.2.0", - "safe-buffer": "5.1.1", + "safe-buffer": "5.1.2", "send": "0.16.2", "serve-static": "1.13.2", "setprototypeof": "1.1.0", @@ -3299,23 +3300,6 @@ "vary": "1.1.2" }, "dependencies": { - "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "requires": { - "bytes": "3.0.0", - "content-type": "1.0.4", - "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.3", - "iconv-lite": "0.4.19", - "on-finished": "2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "1.6.16" - } - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -3324,55 +3308,6 @@ "ms": "2.0.0" } }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.4.0" - } - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" - } - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", @@ -5570,12 +5505,12 @@ } }, "nock": { - "version": "9.4.4", - "resolved": "https://registry.npmjs.org/nock/-/nock-9.4.4.tgz", - "integrity": "sha512-HrF96ecwONEv7tW8bk79kwc9mshxWAw8WfEPv5LStc0X25bsoWgescTtmevFSetu3gdjOypnUtniubYSz+5DNA==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/nock/-/nock-9.6.1.tgz", + "integrity": "sha512-EDgl/WgNQ0C1BZZlASOQkQdE6tAWXJi8QQlugqzN64JJkvZ7ILijZuG24r4vCC7yOfnm6HKpne5AGExLGCeBWg==", "dev": true, "requires": { - "chai": "4.1.2", + "chai": "4.2.0", "debug": "3.1.0", "deep-equal": "1.0.1", "json-stringify-safe": "5.0.1", @@ -5587,9 +5522,9 @@ } }, "node-mocks-http": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.7.0.tgz", - "integrity": "sha512-AX1jGG87itK38N9UZif1CFYjJDibCOj07d0YGpUsxzglVWJjyJ3R7fxtuK7l6RVCKZteLiQyaTo9UR8rIEESgw==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.7.3.tgz", + "integrity": "sha512-wayzLNhEroH3lJj113pFKQ1cd1GKG1mXoZR1HcKp/o9a9lTGGgVY/hYeLajiIFr/z4tXFKOdfJickqqihBtn9g==", "dev": true, "requires": { "accepts": "1.3.5", @@ -9341,7 +9276,7 @@ "resolved": "https://registry.npmjs.org/simple-oauth2/-/simple-oauth2-1.6.0.tgz", "integrity": "sha512-nSfa5lIJbf89k+VpWrZTzChH4B0/a/DRD3+NlEqyto8qgQ/FWX8eWzZs4KnkvnTMAB2Lph/V46ikoqk7UrjjEg==", "requires": { - "bluebird": "3.5.1", + "bluebird": "3.5.3", "date-fns": "1.29.0", "debug": "3.1.0", "joi": "12.0.0", @@ -9364,9 +9299,9 @@ } }, "sinon-chai": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.2.0.tgz", - "integrity": "sha512-Z72B4a0l0IQe5uWi9yzcqX/Ml6K9e1Hp03NmkjJnRG3gDsKTX7KvLFZsVUmCaz0eqeXLLK089mwTsP1P1W+DUQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.3.0.tgz", + "integrity": "sha512-r2JhDY7gbbmh5z3Q62pNbrjxZdOAjpsqW/8yxAZRSqLZqowmfGZPGUZPFf3UX36NLis0cv8VEM5IJh9HgkSOAA==", "dev": true }, "slash": { @@ -9624,33 +9559,13 @@ } }, "supertest": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.1.0.tgz", - "integrity": "sha512-O44AMnmJqx294uJQjfUmEyYOg7d9mylNFsMw/Wkz4evKd1njyPrtCN+U6ZIC7sKtfEVQhfTqFFijlXx8KP/Czw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.3.0.tgz", + "integrity": "sha512-dMQSzYdaZRSANH5LL8kX3UpgK9G1LRh/jnggs/TI0W2Sz7rkMx9Y48uia3K9NgcaWEV28tYkBnXE4tiFC77ygQ==", "dev": true, "requires": { "methods": "1.1.2", - "superagent": "3.8.2" - }, - "dependencies": { - "superagent": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", - "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "cookiejar": "2.1.2", - "debug": "3.1.0", - "extend": "3.0.2", - "form-data": "2.3.2", - "formidable": "1.2.1", - "methods": "1.1.2", - "mime": "1.6.0", - "qs": "6.5.2", - "readable-stream": "2.3.6" - } - } + "superagent": "3.8.3" } }, "supports-color": { diff --git a/package.json b/package.json index 40945757..8be29532 100644 --- a/package.json +++ b/package.json @@ -45,14 +45,14 @@ "@risingstack/v8-profiler": "^5.7.11", "async": "^2.6.0", "aws-sdk": "2.36.0", - "bluebird": "^3.5.1", + "bluebird": "^3.5.3", "body-parser": "^1.9.2", "cacheman": "^2.2.1", "cacheman-redis": "^1.1.2", "connect-timeout": "^1.8.0", "contentful": "^3.8.0", "date-fns": "^1.29.0", - "express": "^4.16.3", + "express": "^4.16.4", "express-sslify": "^1.2.0", "file-exists": "^4.0.0", "html-entities": "^1.1.1", @@ -69,18 +69,18 @@ "devDependencies": { "@dosomething/eslint-config": "^4.0.0", "ava": "^0.25.0", - "chai": "^4.1.2", - "chance": "^1.0.16", - "codecov": "^3.0.1", + "chai": "^4.2.0", + "chance": "^1.0.18", + "codecov": "^3.1.0", "dotenv": "^5.0.1", "eslint": "^4.19.1", "eslint-plugin-ava": "^4.5.1", - "nock": "^9.2.5", - "node-mocks-http": "^1.6.1", + "nock": "^9.6.1", + "node-mocks-http": "^1.7.3", "nyc": "^11.8.0", "rewire": "^4.0.1", "sinon": "^4.5.0", - "sinon-chai": "^3.0.0", - "supertest": "^3.0.0" + "sinon-chai": "^3.3.0", + "supertest": "^3.3.0" } } From 52ee4f58c476dff82ef00f67d51a3285984acb92 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Fri, 7 Dec 2018 15:34:37 -0800 Subject: [PATCH 03/24] Fetches campaigns from Rogue --- lib/gateway.js | 25 +++++++ lib/helpers/campaign.js | 53 +++------------ lib/rogue.js | 21 ------ server.js | 4 +- test/lib/{rogue.test.js => gateway.test.js} | 10 +-- test/lib/lib-helpers/campaign.test.js | 73 +++++---------------- test/utils/factories/campaign.js | 9 ++- test/utils/factories/rogue/campaign.js | 20 ++++++ test/utils/factories/topic.js | 3 - 9 files changed, 86 insertions(+), 132 deletions(-) create mode 100644 lib/gateway.js delete mode 100644 lib/rogue.js rename test/lib/{rogue.test.js => gateway.test.js} (64%) create mode 100644 test/utils/factories/rogue/campaign.js diff --git a/lib/gateway.js b/lib/gateway.js new file mode 100644 index 00000000..bcde1274 --- /dev/null +++ b/lib/gateway.js @@ -0,0 +1,25 @@ +'use strict'; + +const { GatewayClient } = require('@dosomething/gateway/server'); + +let gatewayClient; + +function getClient() { + if (!gatewayClient) { + gatewayClient = GatewayClient.getNewInstance(); + } + return gatewayClient; +} + +/** + * @param {Number} campaignId + * @return {Promise} + */ +function fetchCampaignById(campaignId) { + return module.exports.getClient().Rogue.Campaigns.get(campaignId); +} + +module.exports = { + fetchCampaignById, + getClient, +}; diff --git a/lib/helpers/campaign.js b/lib/helpers/campaign.js index df0d46bc..2d756458 100644 --- a/lib/helpers/campaign.js +++ b/lib/helpers/campaign.js @@ -5,7 +5,7 @@ const logger = require('winston'); const Promise = require('bluebird'); const helpers = require('../helpers'); const contentful = require('../contentful'); -const phoenix = require('../phoenix'); +const gateway = require('../gateway'); const config = require('../../config/lib/helpers/campaign'); /** @@ -13,7 +13,7 @@ const config = require('../../config/lib/helpers/campaign'); * @return {Promise} */ function fetchById(campaignId) { - return phoenix.fetchCampaignById(campaignId) + return gateway.fetchCampaignById(campaignId) .then(res => module.exports.parseCampaign(res.data)) .then(campaign => helpers.cache.campaigns.set(campaignId, campaign)); } @@ -111,38 +111,13 @@ module.exports = { return Promise.all(promises); }, getCampaignConfigByCampaignId, - /** - * @param {Object} campaign - * @return {Boolean} - */ - hasEnded: function hasEnded(campaign) { - const endDate = dateFns.parse(campaign.endDate); - return dateFns.isPast(endDate); - }, - /** - * @param {Object} campaign - * @return {Boolean} - */ - isClosed: function isClosed(campaign) { - if (campaign.status) { - return this.isClosedStatus(campaign); - } - - if (!campaign.endDate) { - return false; - } - - return this.hasEnded(campaign); - }, - isClosedStatus: function isClosedStatus(campaign) { - return campaign.status === config.statuses.closed; - }, /** * @param {Object} campaign * @return {String} */ - parseStatus: function parseStatus(campaign) { - if (this.isClosed(campaign)) { + parseCampaignStatus: function parseCampaignStatus(campaign) { + const endDate = campaign.end_date; + if (endDate && endDate.date && dateFns.isPast(dateFns.parse(endDate.date))) { return config.statuses.closed; } return config.statuses.active; @@ -152,20 +127,12 @@ module.exports = { * @return {Object} */ parseCampaign: function parseCampaign(campaign) { - const campaignId = Number(campaign.legacyCampaignId); - logger.debug('parseCampaign', { campaignId }); - - const result = { - id: campaignId, - title: campaign.title, - tagline: campaign.tagline, - status: this.parseStatus(campaign), - currentCampaignRun: { id: Number(campaign.legacyCampaignRunId) }, - endDate: campaign.endDate, + return { + id: campaign.id, + title: campaign.internal_title, + status: this.parseCampaignStatus(campaign), + endDate: campaign.end_date ? campaign.end_date.date : null, }; - logger.debug('parseCampaign', { result }); - - return result; }, parseCampaignConfig, }; diff --git a/lib/rogue.js b/lib/rogue.js deleted file mode 100644 index bafe10b3..00000000 --- a/lib/rogue.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -const { RogueClient } = require('@dosomething/gateway/server'); - -let rogueClient; - -function getClient() { - if (!rogueClient) { - rogueClient = RogueClient.getNewInstance(); - } - return rogueClient; -} - -/** - * TODO: Add getCampaign function once Rogue campaigns go live. - * @see https://github.com/DoSomething/infrastructure/issues/61 - */ - -module.exports = { - getClient, -}; diff --git a/server.js b/server.js index 185f80e4..62735bd6 100644 --- a/server.js +++ b/server.js @@ -19,11 +19,13 @@ function start(processId) { // app modules const app = require('./app'); + // Setup Gateway client. + require('./lib/gateway').getClient(); + /** * Profiler setup * TODO: Move out to external file */ - const Profiler = require('./lib/tools/profiler'); const Uploader = require('./lib/tools/uploader'); diff --git a/test/lib/rogue.test.js b/test/lib/gateway.test.js similarity index 64% rename from test/lib/rogue.test.js rename to test/lib/gateway.test.js index 6c93d3cc..1372e5f3 100644 --- a/test/lib/rogue.test.js +++ b/test/lib/gateway.test.js @@ -13,18 +13,18 @@ chai.use(sinonChai); const sandbox = sinon.sandbox.create(); // Module to test -const rogue = rewire('../../lib/rogue'); +const gateway = rewire('../../lib/gateway'); test.beforeEach(() => { }); test.afterEach(() => { sandbox.restore(); - rogue.__set__('rogueClient', undefined); + gateway.__set__('gatewayClient', undefined); }); -test('rogue.getClient() should return the same instance', () => { - const client = rogue.getClient(); - const newClient = rogue.getClient(); +test('gateway.getClient() should return the same instance', () => { + const client = gateway.getClient(); + const newClient = gateway.getClient(); client.should.be.equal(newClient); }); diff --git a/test/lib/lib-helpers/campaign.test.js b/test/lib/lib-helpers/campaign.test.js index 7bf084c2..a00d582f 100644 --- a/test/lib/lib-helpers/campaign.test.js +++ b/test/lib/lib-helpers/campaign.test.js @@ -9,23 +9,21 @@ const chai = require('chai'); const logger = require('winston'); const sinonChai = require('sinon-chai'); const sinon = require('sinon'); -const underscore = require('underscore'); -const dateFns = require('date-fns'); const helpers = require('../../../lib/helpers'); -const phoenix = require('../../../lib/phoenix'); +const gateway = require('../../../lib/gateway'); const contentful = require('../../../lib/contentful'); const stubs = require('../../utils/stubs'); const campaignEntryFactory = require('../../utils/factories/contentful/campaign'); +const rogueCampaignFactory = require('../../utils/factories/rogue/campaign'); +const campaignFactory = require('../../utils/factories/campaign'); -const campaign = stubs.phoenix.getCampaign().data; +const rogueCampaign = rogueCampaignFactory.getValidCampaign(); +const campaign = campaignFactory.getValidCampaign(); const campaignId = campaign.id; const campaignConfigEntry = campaignEntryFactory.getValidCampaign(); const parsedCampaignConfig = { id: stubs.getContentfulId() }; -// Config -const config = require('../../../config/lib/helpers/campaign'); - // Module to test const campaignHelper = require('../../../lib/helpers/campaign'); @@ -36,8 +34,6 @@ const sandbox = sinon.sandbox.create(); test.beforeEach(() => { stubs.stubLogger(sandbox, logger); - sandbox.stub(dateFns, 'parse') - .returns(underscore.noop); }); test.afterEach(() => { @@ -46,16 +42,16 @@ test.afterEach(() => { // fetchById test('fetchById calls phoenix.fetchCampaignById, parseCampaign, and sets cache', async () => { - sandbox.stub(phoenix, 'fetchCampaignById') - .returns(Promise.resolve(stubs.phoenix.getCampaign())); + sandbox.stub(gateway, 'fetchCampaignById') + .returns(Promise.resolve({ data: rogueCampaign })); sandbox.stub(campaignHelper, 'parseCampaign') .returns(campaign); sandbox.stub(helpers.cache.campaigns, 'set') .returns(Promise.resolve(campaign)); const result = await campaignHelper.fetchById(campaignId); - phoenix.fetchCampaignById.should.have.been.calledWith(campaignId); - campaignHelper.parseCampaign.should.have.been.calledWith(campaign); + gateway.fetchCampaignById.should.have.been.calledWith(campaignId); + campaignHelper.parseCampaign.should.have.been.calledWith(rogueCampaign); helpers.cache.campaigns.set.should.have.been.calledWith(campaignId, campaign); result.should.deep.equal(campaign); }); @@ -126,55 +122,18 @@ test('getCampaignConfigByCampaignId returns fetchCampaignConfigByCampaignId if c result.should.deep.equal(parsedCampaignConfig); }); -// isClosed -test('isClosed validations', () => { - // If status property exists, check against config.statuses - campaignHelper.isClosed({ status: config.statuses.closed }).should.equal(true); - campaignHelper.isClosed({ status: config.statuses.active }).should.equal(false); - // If status and endDate undefined, isClosed - campaignHelper.isClosed({}).should.equal(false); -}); - -// hasEnded -test('hasEnded returns false if campaign.endDate not isPast', () => { - sandbox.stub(dateFns, 'isPast') - .returns(false); - campaignHelper.hasEnded(campaign).should.equal(false); -}); - -test('hasEnded returns true if campaign.endDate isPast', () => { - sandbox.stub(dateFns, 'isPast') - .returns(true); - campaignHelper.hasEnded(campaign).should.equal(true); -}); - -// parseStatus -test('parseStatus returns active status value if campaign not isClosed', () => { - sandbox.stub(campaignHelper, 'isClosed') - .returns(false); - campaignHelper.parseStatus(campaign).should.equal(config.statuses.active); -}); - -test('parseStatus returns closed status value if campaign isClosed', () => { - sandbox.stub(campaignHelper, 'isClosed') - .returns(true); - campaignHelper.parseStatus(campaign).should.equal(config.statuses.closed); -}); - // parseCampaign -test('parseCampaign returns an object with parsed properties from a Phoenix campaign', (t) => { +test('parseCampaign returns an object with parsed properties from a Rogue campaign', (t) => { const mockStatus = 'active'; - sandbox.stub(campaignHelper, 'parseStatus') + sandbox.stub(campaignHelper, 'parseCampaignStatus') .returns(mockStatus); - const result = campaignHelper.parseCampaign(campaign); - result.id.should.equal(Number(campaign.legacyCampaignId)); - result.title.should.equal(campaign.title); - result.tagline.should.equal(campaign.tagline); - campaignHelper.parseStatus.should.have.been.called; + const result = campaignHelper.parseCampaign(rogueCampaign); + result.id.should.equal(rogueCampaign.id); + result.title.should.equal(rogueCampaign.internal_title); result.status.should.equal(mockStatus); - t.deepEqual(result.endDate, campaign.endDate); - result.currentCampaignRun.id.should.equal(Number(campaign.legacyCampaignRunId)); + // TODO: Test for campaign with endDate.date + t.is(result.endDate, null); }); // parseCampaignConfig diff --git a/test/utils/factories/campaign.js b/test/utils/factories/campaign.js index c37b0036..1f3577d8 100644 --- a/test/utils/factories/campaign.js +++ b/test/utils/factories/campaign.js @@ -6,8 +6,13 @@ function getValidCampaign() { return { id: stubs.getCampaignId(), title: stubs.getRandomMessageText(), - currentCampaignRun: { - id: stubs.getCampaignRunId(), + status: 'active', + endDate: null, + config: { + webSignup: { + text: stubs.getRandomMessageText(), + topic: {}, + }, }, }; } diff --git a/test/utils/factories/rogue/campaign.js b/test/utils/factories/rogue/campaign.js new file mode 100644 index 00000000..f70c5861 --- /dev/null +++ b/test/utils/factories/rogue/campaign.js @@ -0,0 +1,20 @@ +'use strict'; + +const stubs = require('../../stubs'); + +function getValidCampaign() { + return { + id: stubs.getCampaignId(), + internal_title: stubs.getRandomMessageText(), + start_date: { + date: '2018-03-29 00:00:00.000000', + timezone_type: 3, + timezone: 'UTC', + }, + end_date: null, + }; +} + +module.exports = { + getValidCampaign, +}; diff --git a/test/utils/factories/topic.js b/test/utils/factories/topic.js index 3451d363..ab2e596c 100644 --- a/test/utils/factories/topic.js +++ b/test/utils/factories/topic.js @@ -15,9 +15,6 @@ function getValidTopic() { id: stubs.getCampaignId(), title: stubs.getRandomName(), status: 'active', - currentCampaignRun: { - id: stubs.getCampaignRunId(), - }, }, templates: { askText: stubs.getRandomMessageText(), From db5859257e5903e0e6197f517f1b2f47d20ad9d3 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Fri, 7 Dec 2018 15:39:24 -0800 Subject: [PATCH 04/24] Removes lib/phoenix --- lib/phoenix.js | 51 ------------------------- test/lib/phoenix.test.js | 52 -------------------------- test/stubs/phoenix/campaign.json | 21 ----------- test/utils/factories/rogue/campaign.js | 3 ++ 4 files changed, 3 insertions(+), 124 deletions(-) delete mode 100644 lib/phoenix.js delete mode 100644 test/lib/phoenix.test.js delete mode 100644 test/stubs/phoenix/campaign.json diff --git a/lib/phoenix.js b/lib/phoenix.js deleted file mode 100644 index e4b6461e..00000000 --- a/lib/phoenix.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; - -// TODO: Deprecate this when ready to add fetchCampaignById to lib/rogue - -/** - * Imports. - */ -const superagent = require('superagent'); -const logger = require('winston'); -const Promise = require('bluebird'); -const config = require('../config/lib/phoenix'); - -/** - * @param {string} endpoint - * @param {object} query - * @param {object} data - */ -function executeGet(endpoint, query = {}) { - const url = `${config.clientOptions.baseUri}/${endpoint}`; - - return new Promise((resolve, reject) => { - logger.debug('executeGet', { url }); - return superagent - .get(url) - .query(query) - .then(res => resolve(res.body)) - .catch(err => reject(module.exports.parsePhoenixError(err))); - }); -} - -/** - * @param {object} data - * @return {object} - */ -module.exports.parsePhoenixError = function (err, campaignId) { - const scope = err; - scope.message = `phoenix campaignId=${campaignId} error=${err.message}`; - return scope; -}; - -/** - * Fetches a DS Campaign for the given campaignId. - * - * @param {number} campaignId - * @return {Promise} - */ -module.exports.fetchCampaignById = function (campaignId) { - logger.debug(`phoenix.fetchCampaignById:${campaignId}`); - const endpoint = `campaigns/${campaignId}`; - return executeGet(endpoint); -}; diff --git a/test/lib/phoenix.test.js b/test/lib/phoenix.test.js deleted file mode 100644 index 0b58fc91..00000000 --- a/test/lib/phoenix.test.js +++ /dev/null @@ -1,52 +0,0 @@ -'use strict'; - -require('dotenv').config(); - -const test = require('ava'); -const chai = require('chai'); -const sinonChai = require('sinon-chai'); -const sinon = require('sinon'); -const nock = require('nock'); - -const campaignHelper = require('../../lib/helpers/campaign'); -const stubs = require('../../test/utils/stubs'); -const config = require('../../config/lib/phoenix'); - -const baseUri = config.clientOptions.baseUri; -const campaignId = stubs.getCampaignId(); - -chai.should(); -chai.use(sinonChai); -const sandbox = sinon.sandbox.create(); - -// Module to test -const phoenix = require('../../lib/phoenix'); - -test.beforeEach(() => { - sandbox.stub(campaignHelper, 'parseCampaign') - .returns({ id: campaignId }); - sandbox.spy(phoenix, 'parsePhoenixError'); -}); - -test.afterEach(() => { - sandbox.restore(); -}); - -test('phoenix should respond to fetchCampaignById', () => { - phoenix.should.respondTo('fetchCampaignById'); -}); - -test('phoenix.fetchCampaignById should call parsePhoenixError on error', async () => { - const message = 'Miley'; - const status = 500; - nock(baseUri) - .get(/$/) - .reply(status, { error: { message } }); - - try { - await phoenix.fetchCampaignById(campaignId); - } catch (error) { - error.status.should.be.equal(status); - } - phoenix.parsePhoenixError.should.have.been.called; -}); diff --git a/test/stubs/phoenix/campaign.json b/test/stubs/phoenix/campaign.json deleted file mode 100644 index 9a19aaeb..00000000 --- a/test/stubs/phoenix/campaign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "id": "5LrwzAQA9OGkAkciu4GUAy", - "legacyCampaignId": "8038", - "legacyCampaignRunId": "8039", - "type": "campaign", - "template": "mosaic", - "title": "#SaveTheMascots", - "slug": "savethemascots", - "status": null, - "endDate": "2018-04-30T05:00:00Z", - "callToAction": "Tag your school to help us make every college campus tobacco-free!", - "tagline": "Tag your school to help us make every college campus tobacco-free!", - "blurb": "", - "coverImage": { - "description": null, - "url": "https://images.ctfassets.net/81iqaqpfd8fy/23SezyWgGwSSu6IkWaCA2w/393aef189a42bba9e0aca2d91fb97fad/8D3A9015.jpg", - "landscapeUrl": "https://images.ctfassets.net/81iqaqpfd8fy/23SezyWgGwSSu6IkWaCA2w/393aef189a42bba9e0aca2d91fb97fad/8D3A9015.jpg?w=1440&h=620&fm=jpg&fit=fill" - } - } -} diff --git a/test/utils/factories/rogue/campaign.js b/test/utils/factories/rogue/campaign.js index f70c5861..e63d3878 100644 --- a/test/utils/factories/rogue/campaign.js +++ b/test/utils/factories/rogue/campaign.js @@ -2,6 +2,9 @@ const stubs = require('../../stubs'); +/** + * @see https://github.com/DoSomething/rogue/blob/master/docs/endpoints/campaigns.md + */ function getValidCampaign() { return { id: stubs.getCampaignId(), From f0656655d98f91f722d57ef4150ad679204b1ac2 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Fri, 7 Dec 2018 15:45:02 -0800 Subject: [PATCH 05/24] more cleanup --- .env.example | 22 +++++----------- config/lib/phoenix.js | 7 ------ test/stubs/northstar/user-by-mobile.json | 32 ------------------------ 3 files changed, 6 insertions(+), 55 deletions(-) delete mode 100644 config/lib/phoenix.js delete mode 100644 test/stubs/northstar/user-by-mobile.json diff --git a/.env.example b/.env.example index 6ce4e024..9b9afab8 100644 --- a/.env.example +++ b/.env.example @@ -1,20 +1,9 @@ ## Used to authenticate requests to API endpoints provided by this app -GAMBIT_API_KEY=totallysecret - -## -## DS Campaigns -## - -DS_CAMPAIGNS_API_BASEURI=https://www.dosomething.org/api/v2 - -## -## DS Activity -## -DS_ROGUE_API_BASEURI=https://activity.dosomething.org/api/v3 +GAMBIT_API_KEY=totallysecret ## -## DS Northstar Oauth +## Gateway ## DS_NORTHSTAR_API_OAUTH_CLIENT_ID=puppet @@ -22,14 +11,15 @@ DS_NORTHSTAR_API_OAUTH_CLIENT_SECRET=totallysecret DS_NORTHSTAR_API_OAUTH_TOKEN_HOST=https://identity.dosomething.org DS_NORTHSTAR_API_OAUTH_TOKEN_PATH=/v2/auth/token DS_NORTHSTAR_API_OAUTH_SCOPES="admin activity write" +DS_ROGUE_API_BASEURI=https://activity.dosomething.org/api/v3 ## -## Chatbot content (replies, broadcasts) is created via Contentful. +## Contentful ## + CONTENTFUL_SPACE_ID=puP43Ts70tH CONTENTFUL_ACCESS_TOKEN=totallysecret -## This is only used for dev or staging environments, to view draft Contentful entries via Preview API. -## The CONTENTFUL_ACCESS_TOKEN value is different depending on whther to use the Preview API or production CDN API. +## The CONTENTFUL_HOST is set for Preview API. The CONTENTFUL_ACCESS_TOKEN value is different depending on whether to use Preview API or production CDN API. CONTENTFUL_HOST=preview.contentful.com ## diff --git a/config/lib/phoenix.js b/config/lib/phoenix.js deleted file mode 100644 index a38d2898..00000000 --- a/config/lib/phoenix.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -module.exports = { - clientOptions: { - baseUri: process.env.DS_CAMPAIGNS_API_BASEURI || 'https://www.dosomething.org/api/v2', - }, -}; diff --git a/test/stubs/northstar/user-by-mobile.json b/test/stubs/northstar/user-by-mobile.json deleted file mode 100644 index 16c1b011..00000000 --- a/test/stubs/northstar/user-by-mobile.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "id": "58d2bbe1a0bfad73b9461848", - "_id": "58d2bbe1a0bfad73b9461848", - "first_name": null, - "last_name": null, - "last_initial": "", - "photo": null, - "email": null, - "mobile": "5559108329", - "facebook_id": null, - "interests": null, - "birthdate": null, - "addr_street1": null, - "addr_street2": null, - "addr_city": null, - "addr_state": null, - "addr_zip": null, - "source": "sms", - "source_detail": "other", - "slack_id": null, - "mobilecommons_id": "222764258", - "parse_installation_ids": null, - "mobilecommons_status": "undeliverable", - "language": null, - "country": null, - "drupal_id": "8786876", - "role": "user", - "last_accessed_at": null, - "last_authenticated_at": null, - "updated_at": "2017-03-22T18:01:05+00:00", - "created_at": "2017-03-22T17:56:01+00:00" -} From e97ac272003ffcab7fd1d5b8791ff226d71046cb Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Fri, 7 Dec 2018 16:06:08 -0800 Subject: [PATCH 06/24] Updates docs per switch from Phoenix to Rogue --- documentation/endpoints/campaigns.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/documentation/endpoints/campaigns.md b/documentation/endpoints/campaigns.md index b4cce9be..dc34e7a3 100644 --- a/documentation/endpoints/campaigns.md +++ b/documentation/endpoints/campaigns.md @@ -1,6 +1,6 @@ # Campaigns -The `campaigns` resource queries the Phoenix API for a campaign, and our Contentful space for chatbot configurations. +The `campaigns` resource queries the Rogue API for a campaign, and our Contentful space for chatbot configurations. Fields: @@ -8,10 +8,9 @@ Fields: Name | Type | Description -----|------|------------ `id` | Number | The campaign id -`title` | String | The campaign title, available as a `{{title}}` tag within a topic template -`tagline` | String | The campaign tagline, available as a `{{tagline}}` tag within a topic template +`title` | String | The internal campaign title `status` | String | Either `'active'` or `'closed'`. Users may not participate in chatbot topics for closed campaigns. -`currentCampaignRun` | Object | Contains a numeric `id` property to be passed when creating a post for the campaign +`endDate` | Date | Used to determine `status` - if endDate is set and passed, status is `closed` `config` | Object | The chatbot configuration for this campaign `config.id` | String | The id of the chatbot configuration `config.templates` | Object | Message templates defined for the campaign @@ -28,7 +27,7 @@ Returns a campaign and its config if set. Name | Type | Description -----|------|------------ -`cache` | string | If set to `false`, fetches campaign from Phoenix and campaignConfig from Contentful and resets each cache. +`cache` | string | If set to `false`, fetches campaign from Rogue and campaignConfig from Contentful and resets each cache.
**Example Request**

@@ -47,11 +46,8 @@ curl http://localhost:5000/v1/campaigns/7 "data": { "id": 7, "title": "Mirror Messages", - "tagline": "Boost a stranger's self-esteem with just a sticky note!", "status": "active", - "currentCampaignRun": { - "id": 8076 - }, + "endDate": null, "config": { "id": "68Oy1FcaR2EiaMieicaoom", "templates": { From dcf66e57cda3867c740fa8c67e97e3533c704e2f Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Mon, 10 Dec 2018 15:06:56 -0800 Subject: [PATCH 07/24] Changes per Rogue API --- lib/helpers/campaign.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/helpers/campaign.js b/lib/helpers/campaign.js index 2d756458..d3aa5f74 100644 --- a/lib/helpers/campaign.js +++ b/lib/helpers/campaign.js @@ -117,7 +117,7 @@ module.exports = { */ parseCampaignStatus: function parseCampaignStatus(campaign) { const endDate = campaign.end_date; - if (endDate && endDate.date && dateFns.isPast(dateFns.parse(endDate.date))) { + if (endDate && dateFns.isPast(dateFns.parse(endDate))) { return config.statuses.closed; } return config.statuses.active; @@ -131,7 +131,7 @@ module.exports = { id: campaign.id, title: campaign.internal_title, status: this.parseCampaignStatus(campaign), - endDate: campaign.end_date ? campaign.end_date.date : null, + endDate: campaign.end_date, }; }, parseCampaignConfig, From b4c6d7e127c900f8f48027b331f64a780c200473 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 10:54:54 -0800 Subject: [PATCH 08/24] Updates gateway-js to 1.5.0 --- package-lock.json | 47 ++++++++++++++++++++--------------------------- package.json | 2 +- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index de6326e3..05bc7342 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "gambit-content", - "version": "6.0.0", + "version": "6.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -199,44 +199,37 @@ } }, "@dosomething/gateway": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@dosomething/gateway/-/gateway-1.4.0.tgz", - "integrity": "sha512-eLEn2EksRxNRZwAabg3YNZ2FceU2gk0Tpi9/7Qx68oIN8KWnKhVRSfjfS5RMRXVlp5E8vkLxoF/0ffz9ulzGTQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@dosomething/gateway/-/gateway-1.5.0.tgz", + "integrity": "sha512-0C7WxjYJGm+u4u52tyHNlR5EOI7Xo6sxh4n3I003aqOS+sFq9+2g5dpnri9IdMRASgmthvLntRakEOcxtJx8Xg==", "requires": { - "date-fns": "1.29.0", - "lodash": "4.17.10", + "date-fns": "1.30.1", + "lodash": "4.17.11", "simple-oauth2": "1.6.0", "superagent": "3.8.3", "superagent-use": "0.1.0", - "winston": "2.4.3" + "winston": "2.4.4" }, "dependencies": { "async": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.0.0.tgz", "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" }, - "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "requires": { - "component-emitter": "1.2.1", - "cookiejar": "2.1.2", - "debug": "3.1.0", - "extend": "3.0.2", - "form-data": "2.3.2", - "formidable": "1.2.1", - "methods": "1.1.2", - "mime": "1.6.0", - "qs": "6.5.2", - "readable-stream": "2.3.6" - } + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" }, "winston": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.3.tgz", - "integrity": "sha512-GYKuysPz2pxYAVJD2NPsDLP5Z79SDEzPm9/j4tCjkF/n89iBNGBMJcR+dMUqxgPNgoSs6fVygPi+Vl2oxIpBuw==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.4.tgz", + "integrity": "sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q==", "requires": { "async": "1.0.0", "colors": "1.0.3", diff --git a/package.json b/package.json index ab7b9bcf..fe27def9 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "npm": "5.7.1" }, "dependencies": { - "@dosomething/gateway": "^1.4.0", + "@dosomething/gateway": "^1.5.0", "@risingstack/v8-profiler": "^5.7.11", "async": "^2.6.0", "aws-sdk": "2.36.0", From 00c6c3d0933ac1116ce51e32bffbf63c034b9e3e Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 12:22:44 -0800 Subject: [PATCH 09/24] Cleanup, remove deprecated getByIds --- lib/helpers/campaign.js | 35 +++++++++++++------------- test/lib/lib-helpers/campaign.test.js | 2 ++ test/utils/factories/rogue/campaign.js | 6 +---- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/lib/helpers/campaign.js b/lib/helpers/campaign.js index d3aa5f74..99fa8596 100644 --- a/lib/helpers/campaign.js +++ b/lib/helpers/campaign.js @@ -74,6 +74,23 @@ async function getCampaignConfigByCampaignId(campaignId, resetCache = false) { return module.exports.fetchCampaignConfigByCampaignId(campaignId); } +/** + * @param {Object} campaign + * @return {Object} + */ +function parseCampaign(campaign) { + const internalTitle = campaign.internal_title; + return { + id: campaign.id, + internalTitle, + startDate: campaign.start_date, + endDate: campaign.end_date, + status: this.parseCampaignStatus(campaign), + // TODO: Remove this once Gambit Admin references internalTitle. + title: internalTitle, + }; +} + /** * @param {Object} contentfulEntry * @return {Promise} @@ -105,11 +122,6 @@ module.exports = { fetchById, fetchCampaignConfigByCampaignId, getById, - getByIds: function fetchByIds(campaignIds) { - const promises = []; - campaignIds.forEach(campaignId => promises.push(this.getById(campaignId))); - return Promise.all(promises); - }, getCampaignConfigByCampaignId, /** * @param {Object} campaign @@ -122,17 +134,6 @@ module.exports = { } return config.statuses.active; }, - /** - * @param {Object} campaign - * @return {Object} - */ - parseCampaign: function parseCampaign(campaign) { - return { - id: campaign.id, - title: campaign.internal_title, - status: this.parseCampaignStatus(campaign), - endDate: campaign.end_date, - }; - }, + parseCampaign, parseCampaignConfig, }; diff --git a/test/lib/lib-helpers/campaign.test.js b/test/lib/lib-helpers/campaign.test.js index a00d582f..e5a88264 100644 --- a/test/lib/lib-helpers/campaign.test.js +++ b/test/lib/lib-helpers/campaign.test.js @@ -131,7 +131,9 @@ test('parseCampaign returns an object with parsed properties from a Rogue campai const result = campaignHelper.parseCampaign(rogueCampaign); result.id.should.equal(rogueCampaign.id); result.title.should.equal(rogueCampaign.internal_title); + result.internalTitle.should.equal(rogueCampaign.internal_title); result.status.should.equal(mockStatus); + result.startDate.should.equal(rogueCampaign.start_date); // TODO: Test for campaign with endDate.date t.is(result.endDate, null); }); diff --git a/test/utils/factories/rogue/campaign.js b/test/utils/factories/rogue/campaign.js index e63d3878..486144ba 100644 --- a/test/utils/factories/rogue/campaign.js +++ b/test/utils/factories/rogue/campaign.js @@ -9,11 +9,7 @@ function getValidCampaign() { return { id: stubs.getCampaignId(), internal_title: stubs.getRandomMessageText(), - start_date: { - date: '2018-03-29 00:00:00.000000', - timezone_type: 3, - timezone: 'UTC', - }, + start_date: '2018-03-29 00:00:00.000000', end_date: null, }; } From 5fcae9ce73b5cb5d4bebec8ca399cfd1eecd334c Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 12:35:52 -0800 Subject: [PATCH 10/24] Adds tests for parseCampaignStatus --- lib/helpers/campaign.js | 2 +- test/lib/lib-helpers/campaign.test.js | 13 +++++++++++++ test/utils/factories/rogue/campaign.js | 9 +++++++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/helpers/campaign.js b/lib/helpers/campaign.js index 99fa8596..c5c102cc 100644 --- a/lib/helpers/campaign.js +++ b/lib/helpers/campaign.js @@ -2,7 +2,6 @@ const dateFns = require('date-fns'); const logger = require('winston'); -const Promise = require('bluebird'); const helpers = require('../helpers'); const contentful = require('../contentful'); const gateway = require('../gateway'); @@ -85,6 +84,7 @@ function parseCampaign(campaign) { internalTitle, startDate: campaign.start_date, endDate: campaign.end_date, + // TODO: Determine this in Conversations instead? status: this.parseCampaignStatus(campaign), // TODO: Remove this once Gambit Admin references internalTitle. title: internalTitle, diff --git a/test/lib/lib-helpers/campaign.test.js b/test/lib/lib-helpers/campaign.test.js index e5a88264..0d3d9c63 100644 --- a/test/lib/lib-helpers/campaign.test.js +++ b/test/lib/lib-helpers/campaign.test.js @@ -24,6 +24,8 @@ const campaignId = campaign.id; const campaignConfigEntry = campaignEntryFactory.getValidCampaign(); const parsedCampaignConfig = { id: stubs.getContentfulId() }; +const config = require('../../../config/lib/helpers/campaign'); + // Module to test const campaignHelper = require('../../../lib/helpers/campaign'); @@ -152,3 +154,14 @@ test('parseCampaignConfig should return object with id and templates properties' result.id.should.equal(campaignConfigEntry.sys.id); result.templates.webSignup.should.deep.equal(stubTemplate); }); + +test('parseCampaignStatus should return active status if Rogue campaign has no end_date', () => { + const result = campaignHelper.parseCampaignStatus(rogueCampaign); + result.should.equal(config.statuses.active); +}); + +test('parseCampaignStatus should return closed status if Rogue campaign end_date has past', () => { + const closedRogueCampaign = rogueCampaignFactory.getValidClosedCampaign(); + const result = campaignHelper.parseCampaignStatus(closedRogueCampaign); + result.should.equal(config.statuses.closed); +}); diff --git a/test/utils/factories/rogue/campaign.js b/test/utils/factories/rogue/campaign.js index 486144ba..6fdf8ee9 100644 --- a/test/utils/factories/rogue/campaign.js +++ b/test/utils/factories/rogue/campaign.js @@ -5,15 +5,20 @@ const stubs = require('../../stubs'); /** * @see https://github.com/DoSomething/rogue/blob/master/docs/endpoints/campaigns.md */ -function getValidCampaign() { +function getValidCampaign(endDate = null) { return { id: stubs.getCampaignId(), internal_title: stubs.getRandomMessageText(), start_date: '2018-03-29 00:00:00.000000', - end_date: null, + end_date: endDate, }; } +function getValidClosedCampaign() { + return getValidCampaign('2018-04-29 00:00:00.000000'); +} + module.exports = { getValidCampaign, + getValidClosedCampaign, }; From ec8a4c3d3bd21ebafa38dac875ba2e205ee399b9 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 12:57:39 -0800 Subject: [PATCH 11/24] Cleanup --- lib/helpers/campaign.js | 24 +++++++++++++----------- test/lib/lib-helpers/campaign.test.js | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/lib/helpers/campaign.js b/lib/helpers/campaign.js index c5c102cc..9290470d 100644 --- a/lib/helpers/campaign.js +++ b/lib/helpers/campaign.js @@ -118,22 +118,24 @@ async function parseCampaignConfig(contentfulEntry) { return data; } +/** + * @param {Object} campaign + * @return {String} + */ +function parseCampaignStatus(campaign) { + const endDate = campaign.end_date; + if (endDate && dateFns.isPast(dateFns.parse(endDate))) { + return config.statuses.closed; + } + return config.statuses.active; +} + module.exports = { fetchById, fetchCampaignConfigByCampaignId, getById, getCampaignConfigByCampaignId, - /** - * @param {Object} campaign - * @return {String} - */ - parseCampaignStatus: function parseCampaignStatus(campaign) { - const endDate = campaign.end_date; - if (endDate && dateFns.isPast(dateFns.parse(endDate))) { - return config.statuses.closed; - } - return config.statuses.active; - }, parseCampaign, parseCampaignConfig, + parseCampaignStatus, }; diff --git a/test/lib/lib-helpers/campaign.test.js b/test/lib/lib-helpers/campaign.test.js index 0d3d9c63..aba5459c 100644 --- a/test/lib/lib-helpers/campaign.test.js +++ b/test/lib/lib-helpers/campaign.test.js @@ -146,7 +146,7 @@ test('parseCampaignConfig should return empty object if contentfulEntry undefine result.should.deep.equal({}); }); -test('parseCampaignConfig should return object with id and templates properties', async () => { +test('parseCampaignConfig should return templates object with webSignup if contentfulEntry webSignup field is set', async () => { const stubTemplate = { text: stubs.getRandomMessageText() }; sandbox.stub(helpers.contentfulEntry, 'getMessageTemplate') .returns(Promise.resolve(stubTemplate)); From 33c18b50583fed7dccd8e9f3b9280543c6819517 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 14:55:21 -0800 Subject: [PATCH 12/24] Adds test for fetchCampaignById --- test/lib/gateway.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/lib/gateway.test.js b/test/lib/gateway.test.js index 1372e5f3..27d39e50 100644 --- a/test/lib/gateway.test.js +++ b/test/lib/gateway.test.js @@ -12,6 +12,10 @@ chai.should(); chai.use(sinonChai); const sandbox = sinon.sandbox.create(); +// app modules +const stubs = require('../../test/utils/stubs'); +const rogueCampaignFactory = require('../../test/utils/factories/rogue/campaign'); + // Module to test const gateway = rewire('../../lib/gateway'); @@ -28,3 +32,15 @@ test('gateway.getClient() should return the same instance', () => { const newClient = gateway.getClient(); client.should.be.equal(newClient); }); + +test('gateway.fetchCampaignById() should GatewayClient.Rogue.Campaigns.get', async () => { + const client = gateway.getClient(); + const campaign = rogueCampaignFactory.getValidCampaign(); + sandbox.stub(client.Rogue.Campaigns, 'get') + .returns(Promise.resolve(campaign)); + const campaignId = stubs.getCampaignId(); + + const result = await gateway.fetchCampaignById(campaignId); + client.Rogue.Campaigns.get.should.have.been.calledWith(campaignId); + result.should.be.deep.equal(campaign); +}); From 860fb615a43f82b8bae5a576a4331981f4d4a609 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 15:05:06 -0800 Subject: [PATCH 13/24] Adds startDate --- documentation/endpoints/campaigns.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/documentation/endpoints/campaigns.md b/documentation/endpoints/campaigns.md index dc34e7a3..12e1aad8 100644 --- a/documentation/endpoints/campaigns.md +++ b/documentation/endpoints/campaigns.md @@ -8,8 +8,10 @@ Fields: Name | Type | Description -----|------|------------ `id` | Number | The campaign id -`title` | String | The internal campaign title +`internal_title` | String | The internal campaign title +`title` | String | To be deprecated (same as `internal_title`) `status` | String | Either `'active'` or `'closed'`. Users may not participate in chatbot topics for closed campaigns. +`startDate` | Date | `endDate` | Date | Used to determine `status` - if endDate is set and passed, status is `closed` `config` | Object | The chatbot configuration for this campaign `config.id` | String | The id of the chatbot configuration @@ -44,15 +46,16 @@ curl http://localhost:5000/v1/campaigns/7 ``` { "data": { - "id": 7, - "title": "Mirror Messages", + "id": 72332, + "title": "Mirror Messages Run 87", + "startDate": "2018-03-29T00:00:00+00:00", + "endDate": "2029-03-29T00:00:00+00:00", "status": "active", - "endDate": null, "config": { "id": "68Oy1FcaR2EiaMieicaoom", "templates": { "webSignup": { - "text": "Hi this is Freddie from DoSomething! Thanks for signing up for mirror messages. When youve posted some notes and ready to send a photo, text START", + "text": "Hi this is Freddie from DoSomething! Thanks for signing up for Mirror Messages. When you've posted some notes and ready to send a photo, text START", "attachments": [], "template": "webSignup", "topic": { From f676679a99e055137f77cd27b3775e7a39d4a762 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 15:08:54 -0800 Subject: [PATCH 14/24] Adds internalTitle --- documentation/endpoints/campaigns.md | 1 + 1 file changed, 1 insertion(+) diff --git a/documentation/endpoints/campaigns.md b/documentation/endpoints/campaigns.md index 12e1aad8..e05f90c6 100644 --- a/documentation/endpoints/campaigns.md +++ b/documentation/endpoints/campaigns.md @@ -47,6 +47,7 @@ curl http://localhost:5000/v1/campaigns/7 { "data": { "id": 72332, + "internal_title": "Mirror Messages Run 87", "title": "Mirror Messages Run 87", "startDate": "2018-03-29T00:00:00+00:00", "endDate": "2029-03-29T00:00:00+00:00", From 77819cf972edeb026f3433ab48c3a3a136754d4e Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 15:12:35 -0800 Subject: [PATCH 15/24] Removes deprecated replacePhoenixCampaignVars --- lib/helpers.js | 25 ------------------------- test/lib/helpers.test.js | 28 ---------------------------- 2 files changed, 53 deletions(-) diff --git a/lib/helpers.js b/lib/helpers.js index e87bd659..aba39547 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -12,31 +12,6 @@ Object.keys(helpers).forEach((helperName) => { module.exports[helperName] = helpers[helperName]; }); -/** - * Replaces mustache tags used in raw Campaign Template strings with given variables. - * @param {string} input - * @param {object} campaign - * @return string. - */ -module.exports.replacePhoenixCampaignVars = function (input, campaign) { - if (!input) { - return ''; - } - - let scope = input; - if (campaign) { - scope = scope.replace(/{{title}}/gi, campaign.title); - scope = scope.replace(/{{tagline}}/i, campaign.tagline); - } - - // TODO: Get tags to search for from helpers.command instead of hardcoding here. - // This whole function should be refactored with Mustache and moved into the topic helper. - scope = scope.replace(/{{cmd_reportback}}/i, helpers.command.getStartCommand()); - scope = scope.replace(/{{cmd_member_support}}/i, helpers.command.getRequestSupportCommand()); - - return scope; -}; - /** * Formats given Express response and sends an object including given message, with given code. * @param {object} res - Express response diff --git a/test/lib/helpers.test.js b/test/lib/helpers.test.js index f5d990a1..67aca9da 100644 --- a/test/lib/helpers.test.js +++ b/test/lib/helpers.test.js @@ -45,34 +45,6 @@ test.afterEach((t) => { t.context = {}; }); -/** - * Tests - */ - -// replacePhoenixCampaignVars -test('replacePhoenixCampaignVars', async () => { - const phoenixCampaign = stubs.getPhoenixCampaign(); - let renderedMessage = ''; - // signedup through gambit - const signedupGambitMsg = stubs.getDefaultContenfulCampaignMessage('gambitSignupMenu'); - renderedMessage = await helpers - .replacePhoenixCampaignVars(signedupGambitMsg, phoenixCampaign); - renderedMessage.should.have.string(phoenixCampaign.title); - // invalid sign up command - const invalidSignedupCmdMsg = stubs.getDefaultContenfulCampaignMessage('invalidSignupMenuCommand'); - renderedMessage = await helpers - .replacePhoenixCampaignVars(invalidSignedupCmdMsg, phoenixCampaign); - renderedMessage.should.have.string('Sorry, I didn\'t understand that.'); - - // TODO: test more messages! -}); - -test('replacePhoenixCampaignVars with no message should return empty string', () => { - const phoenixCampaign = stubs.getPhoenixCampaign(); - const renderedMessage = helpers.replacePhoenixCampaignVars(undefined, phoenixCampaign); - renderedMessage.should.equal(''); -}); - // sendTimeoutResponse test('sendTimeoutResponse', (t) => { sandbox.spy(t.context.res, 'status'); From 8964beb2395c26b5d0d2934301eec2643dffd917 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 15:25:11 -0800 Subject: [PATCH 16/24] Removes defaultText from all but askCaption photoPost templates --- config/lib/helpers/contentfulEntry.js | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/config/lib/helpers/contentfulEntry.js b/config/lib/helpers/contentfulEntry.js index d1772430..e7735420 100644 --- a/config/lib/helpers/contentfulEntry.js +++ b/config/lib/helpers/contentfulEntry.js @@ -5,13 +5,6 @@ const templateFieldTypes = { transition: 'transition', }; -// Defaults for templates fields that are optional. -const campaignTitleTag = '{{topic.campaign.title}}'; -const startCommand = 'START'; -const askWhyParticipatedText = `Why was participating in ${campaignTitleTag} important to you? (No need to write an essay, one sentence is good).`; -const completedPhotoPostText = `To submit another post for ${campaignTitleTag}, text ${startCommand}.`; -const invalidInputText = 'Sorry, I didn\'t get that. Text Q if you have a question.'; - /** * This maps the fields in our Contentful types into broadcast, topic, and defaultTopicTriggers. * @@ -117,20 +110,17 @@ module.exports = { type: 'photoPostConfig', templates: { startPhotoPostAutoReply: { - defaultText: `${invalidInputText}\n\nText ${startCommand} when you're ready to submit a post for ${campaignTitleTag}.`, fieldName: 'invalidSignupMenuCommandMessage', fieldType: templateFieldTypes.text, name: 'startPhotoPostAutoReply', }, completedPhotoPost: { - defaultText: `Thanks for your submission. ${completedPhotoPostText}`, fieldName: 'completedMenuMessage', fieldType: templateFieldTypes.text, name: 'completedPhotoPost', }, completedPhotoPostAutoReply: { fieldName: 'invalidCompletedMenuCommandMessage', - defaultText: `${invalidInputText}\n\n${completedPhotoPostText}`, fieldType: templateFieldTypes.text, name: 'completedPhotoPostAutoReply', }, @@ -161,19 +151,17 @@ module.exports = { name: 'askCaption', }, invalidCaption: { - defaultText: `${invalidInputText}\n\nText back a caption for your photo -- keep it short & sweet, under 60 characters please. (but more than 3!)`, + defaultText: 'Sorry, I didn\'t get that. Text Q if you have a question.\n\nText back a caption for your photo -- keep it short & sweet, under 60 characters please. (but more than 3!)', fieldName: 'invalidCaptionMessage', fieldType: templateFieldTypes.text, name: 'invalidCaption', }, askWhyParticipated: { - defaultText: `Last question: ${askWhyParticipatedText}`, fieldName: 'askWhyParticipatedMessage', fieldType: templateFieldTypes.text, name: 'askWhyParticipated', }, invalidWhyParticipated: { - defaultText: `${invalidInputText}\n\n${askWhyParticipatedText}`, fieldName: 'invalidWhyParticipatedMessage', fieldType: templateFieldTypes.text, name: 'askWhyParticipated', From ae66918abcd7158ca7388fec004665776d9f60ae Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 15:31:43 -0800 Subject: [PATCH 17/24] Removes deprecated command helper --- config/lib/helpers/command.js | 14 -------------- lib/helpers/command.js | 22 ---------------------- lib/helpers/index.js | 2 -- test/lib/lib-helpers/command.test.js | 24 ------------------------ 4 files changed, 62 deletions(-) delete mode 100644 config/lib/helpers/command.js delete mode 100644 lib/helpers/command.js delete mode 100644 test/lib/lib-helpers/command.test.js diff --git a/config/lib/helpers/command.js b/config/lib/helpers/command.js deleted file mode 100644 index 87157075..00000000 --- a/config/lib/helpers/command.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -module.exports = { - commands: { - start: { - tag: '{{cmd_reportback}}', - value: 'START', - }, - requestSupport: { - tag: '{{cmd_member_support}}', - value: 'Q', - }, - }, -}; diff --git a/lib/helpers/command.js b/lib/helpers/command.js deleted file mode 100644 index 285242a3..00000000 --- a/lib/helpers/command.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -const config = require('../../config/lib/helpers/command'); - -/** - * @return {String} - */ -function getRequestSupportCommand() { - return config.commands.requestSupport.value; -} - -/** - * @return {String} - */ -function getStartCommand() { - return config.commands.start.value; -} - -module.exports = { - getRequestSupportCommand, - getStartCommand, -}; diff --git a/lib/helpers/index.js b/lib/helpers/index.js index 055a88cf..76cc2a3a 100644 --- a/lib/helpers/index.js +++ b/lib/helpers/index.js @@ -3,7 +3,6 @@ const broadcast = require('./broadcast'); const cache = require('./cache'); const campaign = require('./campaign'); -const command = require('./command'); const contentfulEntry = require('./contentfulEntry'); const defaultTopicTrigger = require('./defaultTopicTrigger'); const request = require('./request'); @@ -17,7 +16,6 @@ module.exports = { campaign, contentfulEntry, defaultTopicTrigger, - command, request, response, topic, diff --git a/test/lib/lib-helpers/command.test.js b/test/lib/lib-helpers/command.test.js deleted file mode 100644 index ac94d813..00000000 --- a/test/lib/lib-helpers/command.test.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -const test = require('ava'); -const chai = require('chai'); -const sinonChai = require('sinon-chai'); - -const config = require('../../../config/lib/helpers/command'); - -// Module to test -const commandHelper = require('../../../lib/helpers/command'); - -chai.should(); -chai.use(sinonChai); - -// getRequestSupportCommand -test('getRequestSupportCommand returns a string', () => { - const result = commandHelper.getRequestSupportCommand(); - result.should.equal(config.commands.requestSupport.value); -}); - -test('getStartCommand returns a string', () => { - const result = commandHelper.getStartCommand(); - result.should.equal(config.commands.start.value); -}); From 285861118e4bafd71b862b01a46cfe408ee6983e Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 16:09:49 -0800 Subject: [PATCH 18/24] Adds tests for resetCache args --- test/lib/lib-helpers/campaign.test.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/lib/lib-helpers/campaign.test.js b/test/lib/lib-helpers/campaign.test.js index aba5459c..7d25d1b2 100644 --- a/test/lib/lib-helpers/campaign.test.js +++ b/test/lib/lib-helpers/campaign.test.js @@ -99,6 +99,18 @@ test('getById returns fetchById if cache not set', async () => { result.should.deep.equal(campaign); }); +test('getById returns fetchById if called with a false resetCache arg', async () => { + sandbox.stub(helpers.cache.campaigns, 'get') + .returns(Promise.resolve(null)); + sandbox.stub(campaignHelper, 'fetchById') + .returns(Promise.resolve(campaign)); + + const result = await campaignHelper.getById(campaignId, false); + helpers.cache.campaigns.get.should.have.been.calledWith(campaignId); + campaignHelper.fetchById.should.have.been.calledWith(campaignId); + result.should.deep.equal(campaign); +}); + // getCampaignConfigByCampaignId test('getCampaignConfigByCampaignId returns campaignConfigs cache if set', async () => { sandbox.stub(helpers.cache.campaignConfigs, 'get') @@ -124,6 +136,18 @@ test('getCampaignConfigByCampaignId returns fetchCampaignConfigByCampaignId if c result.should.deep.equal(parsedCampaignConfig); }); +test('getCampaignConfigByCampaignId returns fetchCampaignConfigByCampaignId if called with a false resetCache arg', async () => { + sandbox.stub(helpers.cache.campaignConfigs, 'get') + .returns(Promise.resolve(null)); + sandbox.stub(campaignHelper, 'fetchCampaignConfigByCampaignId') + .returns(Promise.resolve(parsedCampaignConfig)); + + const result = await campaignHelper.getCampaignConfigByCampaignId(campaignId, false); + helpers.cache.campaignConfigs.get.should.have.been.calledWith(campaignId); + campaignHelper.fetchCampaignConfigByCampaignId.should.have.been.calledWith(campaignId); + result.should.deep.equal(parsedCampaignConfig); +}); + // parseCampaign test('parseCampaign returns an object with parsed properties from a Rogue campaign', (t) => { const mockStatus = 'active'; From dfe4d869e74ca682b78f81d4c85f6b9ef67cf587 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 16:17:57 -0800 Subject: [PATCH 19/24] Updates nested campaigns in docs --- documentation/endpoints/broadcasts.md | 15 +-------------- documentation/endpoints/topics.md | 7 ++----- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/documentation/endpoints/broadcasts.md b/documentation/endpoints/broadcasts.md index 93b186fa..9e49f5ca 100644 --- a/documentation/endpoints/broadcasts.md +++ b/documentation/endpoints/broadcasts.md @@ -91,20 +91,7 @@ curl http://localhost:5000/v1/broadcasts?skip=20 "createdAt": "2018-08-01T14:41:30.242Z", "updatedAt": "2018-08-13T13:31:32.583Z", "postType": "photo", - "campaign": { - "id": 8142, - "title": "Pump It Up", - "tagline": "Print & post our tire flyers to keep friends safe on the road.", - "status": "active", - "currentCampaignRun": { - "id": 8161 - }, - "endDate": { - "date": "2018-09-30 23:59:00.000000", - "timezone_type": 1, - "timezone": "-04:00" - } - }, + "campaign": { ... }, "templates": { ... } diff --git a/documentation/endpoints/topics.md b/documentation/endpoints/topics.md index 211d9ef9..803bff55 100644 --- a/documentation/endpoints/topics.md +++ b/documentation/endpoints/topics.md @@ -64,12 +64,9 @@ curl http://localhost:5000/v1/topics/6swLaA7HKE8AGI6iQuWk4y?cache=false \ "updatedAt": "2018-11-01T17:06:26.833Z", "campaign": { "id": 8190, - "title": "Escape the Vape", - "tagline": "Take this 5-question quiz to learn what's really in e-cigs.", + "internal_title": "Escape the Vape", "status": "active", - "currentCampaignRun": { - "id": 8191 - }, + "startDate": "2015-12-16T03:59:00Z", "endDate": "2018-12-16T03:59:00Z" }, "templates": { From 440fe5f319d110d9d8d9848f1b5af5d0d374b45c Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 16:37:17 -0800 Subject: [PATCH 20/24] Removes deprecated helpers.topic.fetch --- lib/helpers/topic.js | 22 +++------------------ test/lib/lib-helpers/topic.test.js | 31 ------------------------------ 2 files changed, 3 insertions(+), 50 deletions(-) diff --git a/lib/helpers/topic.js b/lib/helpers/topic.js index 3e0b5c17..be153c9e 100644 --- a/lib/helpers/topic.js +++ b/lib/helpers/topic.js @@ -5,31 +5,16 @@ const contentful = require('../contentful'); const helpers = require('../helpers'); /** + * TODO: Move this into contentfulEntry. * @return {Array} */ function getContentTypes() { const configs = Object.values(helpers.contentfulEntry.getContentTypeConfigs()); - // Return any configs that have templates set, or a postType. - // We'll eventually refactor this config to only check for existence of templates, with each item - // corresponding to a reference field to a message or changeTopicMessage entry, like how it does - // in an askYesNo or autoReply topic (vs a textPostConfig or photoPostConfig, where we're using - // text fields and the fieldName map defined in the topic helper config). - return configs.filter(typeConfig => typeConfig.templates || typeConfig.postType) + // Topic content types have a templates property. + return configs.filter(typeConfig => typeConfig.templates) .map(typeConfig => typeConfig.type); } -/** - * @param {Object} query - * @return {Promise} - */ -async function fetch(query = {}) { - const contentfulRes = await contentful - .fetchByContentTypes(module.exports.getContentTypes(), query); - const topics = await Promise - .all(contentfulRes.data.map(module.exports.parseTopicFromContentfulEntry)); - return Object.assign(contentfulRes, { data: topics }); -} - /** * @param {String} topicId * @return {Promise} @@ -106,7 +91,6 @@ async function parseTopicFromContentfulEntry(contentfulEntry) { } module.exports = { - fetch, fetchById, getById, getContentTypes, diff --git a/test/lib/lib-helpers/topic.test.js b/test/lib/lib-helpers/topic.test.js index f384b65c..3ba33f1a 100644 --- a/test/lib/lib-helpers/topic.test.js +++ b/test/lib/lib-helpers/topic.test.js @@ -31,37 +31,6 @@ test.afterEach(() => { sandbox.restore(); }); -// fetch -test('fetch returns contentful.fetchByContentTypes parsed as topic objects', async () => { - const contentTypes = ['textPostConfig']; - const entries = [textPostConfigFactory.getValidTextPostConfig()]; - const fetchEntriesResult = stubs.contentful.getFetchByContentTypesResultWithArray(entries); - sandbox.stub(topicHelper, 'getContentTypes') - .returns(contentTypes); - sandbox.stub(contentful, 'fetchByContentTypes') - .returns(Promise.resolve(fetchEntriesResult)); - sandbox.stub(topicHelper, 'parseTopicFromContentfulEntry') - .returns(Promise.resolve(topic)); - - const result = await topicHelper.fetch(); - contentful.fetchByContentTypes.should.have.been.calledWith(contentTypes, {}); - entries.forEach((entry) => { - topicHelper.parseTopicFromContentfulEntry.should.have.been.calledWith(entry); - }); - result.data.should.deep.equal([topic]); -}); - -test('fetch throws if contentful.fetchByContentTypes fails', async (t) => { - const error = new Error('epic fail'); - sandbox.stub(contentful, 'fetchByContentTypes') - .returns(Promise.reject(error)); - sandbox.stub(topicHelper, 'parseTopicFromContentfulEntry') - .returns(Promise.resolve(topic)); - - const result = await t.throws(topicHelper.fetch()); - result.should.deep.equal(error); -}); - // fetchById test('fetchById returns contentful.fetchByContentfulId parsed as cached topic object', async () => { const fetchEntryResult = { id: '132' }; From c04a38918c4aa9156496518c77bc28d39cf59d53 Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 16:39:13 -0800 Subject: [PATCH 21/24] Removes deprecated helpers.topic.isTopicForCampaignId --- lib/helpers/topic.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/lib/helpers/topic.js b/lib/helpers/topic.js index be153c9e..374a9897 100644 --- a/lib/helpers/topic.js +++ b/lib/helpers/topic.js @@ -47,16 +47,6 @@ function getById(topicId, resetCache = false) { }); } -/** - * @param {Object} topic - * @param {String} campaignId - * @return {Boolean} - */ -function isTopicForCampaignId(topic, campaignId) { - const result = topic.campaign && topic.campaign.id === Number(campaignId); - return result; -} - /** * @param {Object} contentfulEntry * @return {Promise} @@ -94,6 +84,5 @@ module.exports = { fetchById, getById, getContentTypes, - isTopicForCampaignId, parseTopicFromContentfulEntry, }; From 5ffc987e41adc502cf52a6e736b9d7eb9cf39fcb Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Tue, 11 Dec 2018 17:11:09 -0800 Subject: [PATCH 22/24] Adds test for helpers.topic.getContentTypes --- lib/helpers/topic.js | 5 ++--- test/lib/lib-helpers/topic.test.js | 8 ++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/helpers/topic.js b/lib/helpers/topic.js index 374a9897..c502f4b1 100644 --- a/lib/helpers/topic.js +++ b/lib/helpers/topic.js @@ -5,13 +5,12 @@ const contentful = require('../contentful'); const helpers = require('../helpers'); /** - * TODO: Move this into contentfulEntry. * @return {Array} */ function getContentTypes() { - const configs = Object.values(helpers.contentfulEntry.getContentTypeConfigs()); // Topic content types have a templates property. - return configs.filter(typeConfig => typeConfig.templates) + return Object.values(helpers.contentfulEntry.getContentTypeConfigs()) + .filter(typeConfig => typeConfig.templates) .map(typeConfig => typeConfig.type); } diff --git a/test/lib/lib-helpers/topic.test.js b/test/lib/lib-helpers/topic.test.js index 3ba33f1a..fb8471d3 100644 --- a/test/lib/lib-helpers/topic.test.js +++ b/test/lib/lib-helpers/topic.test.js @@ -86,6 +86,14 @@ test('getById returns fetchById if resetCache arg is true', async () => { result.should.deep.equal(topic); }); +// getContentTypes +test('getContentTypes returns types that have templates in contentfulEntry config', () => { + const expected = Object.values(helpers.contentfulEntry.getContentTypeConfigs()) + .filter(typeConfig => typeConfig.templates) + .map(typeConfig => typeConfig.type); + expected.should.deep.equal(topicHelper.getContentTypes()); +}); + // parseTopicFromContentfulEntry test('parseTopicFromContentfulEntry returns parseBroadcastFromContentfulEntry if contentfulEntry is broadcastable', async () => { const askYesNo = askYesNoFactory.getValidAskYesNo(); From 18ecda0e92db4705a518ad886a5ae0a3c142651a Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Wed, 12 Dec 2018 06:38:18 -0800 Subject: [PATCH 23/24] Fixes internalTitle in docs --- documentation/endpoints/campaigns.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/endpoints/campaigns.md b/documentation/endpoints/campaigns.md index e05f90c6..cb97ae3a 100644 --- a/documentation/endpoints/campaigns.md +++ b/documentation/endpoints/campaigns.md @@ -8,8 +8,8 @@ Fields: Name | Type | Description -----|------|------------ `id` | Number | The campaign id -`internal_title` | String | The internal campaign title -`title` | String | To be deprecated (same as `internal_title`) +`internalTitle` | String | The internal campaign title +`title` | String | To be deprecated (same as `internalTitle`) `status` | String | Either `'active'` or `'closed'`. Users may not participate in chatbot topics for closed campaigns. `startDate` | Date | `endDate` | Date | Used to determine `status` - if endDate is set and passed, status is `closed` @@ -47,7 +47,7 @@ curl http://localhost:5000/v1/campaigns/7 { "data": { "id": 72332, - "internal_title": "Mirror Messages Run 87", + "internalTitle": "Mirror Messages Run 87", "title": "Mirror Messages Run 87", "startDate": "2018-03-29T00:00:00+00:00", "endDate": "2029-03-29T00:00:00+00:00", From 6772d603837ab419b3376d3068c43c7b01d68cad Mon Sep 17 00:00:00 2001 From: Aaron Schachter Date: Wed, 12 Dec 2018 12:09:17 -0800 Subject: [PATCH 24/24] Bumped version number to 6.1.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2fbfe90f..a16bbc39 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "gambit-content", - "version": "6.0.1", + "version": "6.1.0", "description": "Content API for the DoSomething.org chatbot.", "license": "MIT", "repository": { "type": "git", - "url": "git+https://github.com/DoSomething/gambit-campaigns.git" + "url": "git+https://github.com/DoSomething/gambit-content.git" }, "scripts": { "test": "NODE_ENV=test ava --serial",