From 6184fb5d2482f356b960eafbcb9194deeae22a79 Mon Sep 17 00:00:00 2001 From: Keith Holliday Date: Tue, 15 Mar 2016 20:37:30 -0500 Subject: [PATCH 1/4] Added development controller, middleware, and initial tests --- .../POST-development_addHourglass.test.js | 35 ++++++++++++ .../POST-development_addTenGems.test.js | 35 ++++++++++++ website/src/controllers/api-v3/development.js | 53 +++++++++++++++++++ .../src/middlewares/api-v3/developmentMode.js | 12 +++++ 4 files changed, 135 insertions(+) create mode 100644 test/api/v3/integration/development/POST-development_addHourglass.test.js create mode 100644 test/api/v3/integration/development/POST-development_addTenGems.test.js create mode 100644 website/src/controllers/api-v3/development.js create mode 100644 website/src/middlewares/api-v3/developmentMode.js diff --git a/test/api/v3/integration/development/POST-development_addHourglass.test.js b/test/api/v3/integration/development/POST-development_addHourglass.test.js new file mode 100644 index 0000000000..6ef111c130 --- /dev/null +++ b/test/api/v3/integration/development/POST-development_addHourglass.test.js @@ -0,0 +1,35 @@ +import nconf from 'nconf'; +import { + generateUser, +} from '../../../../helpers/api-v3-integration.helper'; + +describe('POST /development/addHourglass', () => { + let userToGetHourGlass; + + before(async () => { + userToGetHourGlass = await generateUser(); + }); + + it('adds Hourglass to the current user', async () => { + await userToGetHourGlass.post('/development/addHourglass'); + + let userWithHourGlass = await userToGetHourGlass.get('/user'); + + expect(userWithHourGlass.purchased.plan.consecutive.trinkets).to.equal(1); + }); + + it('returns error when not in production mode', async () => { + nconf.set('IS_PROD', true); + + await expect(userToGetHourGlass.post('/development/addHourglass')) + .eventually.be.rejected.and.to.deep.equal({ + code: 404, + error: 'NotFound', + message: 'Not found.', + }); + }); + + after(() => { + nconf.set('IS_PROD', false); + }); +}); diff --git a/test/api/v3/integration/development/POST-development_addTenGems.test.js b/test/api/v3/integration/development/POST-development_addTenGems.test.js new file mode 100644 index 0000000000..82594c4d07 --- /dev/null +++ b/test/api/v3/integration/development/POST-development_addTenGems.test.js @@ -0,0 +1,35 @@ +import nconf from 'nconf'; +import { + generateUser, +} from '../../../../helpers/api-v3-integration.helper'; + +describe('POST /development/addTenGems', () => { + let userToGainTenGems; + + before(async () => { + userToGainTenGems = await generateUser(); + }); + + it('adds ten gems to the current user', async () => { + await userToGainTenGems.post('/development/addTenGems'); + + let userWithTenGems = await userToGainTenGems.get('/user'); + + expect(userWithTenGems.balance).to.equal(2.5); + }); + + it('returns error when not in production mode', async () => { + nconf.set('IS_PROD', true); + + await expect(userToGainTenGems.post('/development/addTenGems')) + .eventually.be.rejected.and.to.deep.equal({ + code: 404, + error: 'NotFound', + message: 'Not found.', + }); + }); + + after(() => { + nconf.set('IS_PROD', false); + }); +}); diff --git a/website/src/controllers/api-v3/development.js b/website/src/controllers/api-v3/development.js new file mode 100644 index 0000000000..321fe6ebf3 --- /dev/null +++ b/website/src/controllers/api-v3/development.js @@ -0,0 +1,53 @@ +import { authWithHeaders } from '../../middlewares/api-v3/auth'; +import cron from '../../middlewares/api-v3/cron'; +import checkForDevelopmentMode from '../../middlewares/api-v3/developmentMode'; + +let api = {}; + +/** + * @api {post} /development/addTenGems Add ten gems to the current user + * @apiVersion 3.0.0 + * @apiName AddTenGems + * @apiGroup Development + * + * @apiSuccess {} An empty Object + */ +api.addTenGems = { + method: 'POST', + url: '/development/addTenGems', + middlewares: [checkForDevelopmentMode, authWithHeaders(), cron], + async handler (req, res) { + let user = res.locals.user; + + user.balance += 2.5; + + await user.save(); + + res.respond(200, {}); + }, +}; + +/** + * @api {post} /development/addHourglass Add Hourglass to the current user + * @apiVersion 3.0.0 + * @apiName AddHourglass + * @apiGroup Development + * + * @apiSuccess {} An empty Object + */ +api.addHourglass = { + method: 'POST', + url: '/development/addHourglass', + middlewares: [checkForDevelopmentMode, authWithHeaders(), cron], + async handler (req, res) { + let user = res.locals.user; + + user.purchased.plan.consecutive.trinkets += 1; + + await user.save(); + + res.respond(200, {}); + }, +}; + +module.exports = api; diff --git a/website/src/middlewares/api-v3/developmentMode.js b/website/src/middlewares/api-v3/developmentMode.js new file mode 100644 index 0000000000..5c068df0ab --- /dev/null +++ b/website/src/middlewares/api-v3/developmentMode.js @@ -0,0 +1,12 @@ +import nconf from 'nconf'; +import { + NotFound, +} from '../../libs/api-v3/errors'; + +module.exports = function checkForDevelopmentMode (req, res, next) { + if (nconf.get('IS_PROD')) { + next(new NotFound()); + } else { + next(); + } +}; From 6921c1694a1e2c84265344f228b122b2d899a5d8 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Tue, 15 Mar 2016 21:53:11 -0500 Subject: [PATCH 2/4] feat: Allow routes to not need an async handler --- website/src/libs/api-v3/setupRoutes.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/website/src/libs/api-v3/setupRoutes.js b/website/src/libs/api-v3/setupRoutes.js index 99dca871a9..3b91b81f25 100644 --- a/website/src/libs/api-v3/setupRoutes.js +++ b/website/src/libs/api-v3/setupRoutes.js @@ -9,6 +9,7 @@ let router = express.Router(); // eslint-disable-line babel/new-cap // Wrapper function to handler `async` route handlers that return promises // It takes the async function, execute it and pass any error to next (args[2]) let _wrapAsyncFn = fn => (...args) => fn(...args).catch(args[2]); +let noop = (req, res, next) => next(); function walkControllers (filePath) { fs @@ -23,7 +24,9 @@ function walkControllers (filePath) { let {method, url, middlewares = [], handler} = action; method = method.toLowerCase(); - router[method](url, ...middlewares, _wrapAsyncFn(handler)); + let fn = handler ? _wrapAsyncFn(handler) : noop; + + router[method](url, ...middlewares, fn); }); } }); From e056a62af02973a80fdd42cc8b2f52df1ccf200c Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Tue, 15 Mar 2016 22:02:36 -0500 Subject: [PATCH 3/4] refactor: Setup middleware for all development routes --- website/src/controllers/api-v3/development.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/website/src/controllers/api-v3/development.js b/website/src/controllers/api-v3/development.js index 321fe6ebf3..2b252bbb8e 100644 --- a/website/src/controllers/api-v3/development.js +++ b/website/src/controllers/api-v3/development.js @@ -4,6 +4,12 @@ import checkForDevelopmentMode from '../../middlewares/api-v3/developmentMode'; let api = {}; +api.development = { + method: 'all', + url: '/development/*', + middlewares: [checkForDevelopmentMode, authWithHeaders(), cron], +}; + /** * @api {post} /development/addTenGems Add ten gems to the current user * @apiVersion 3.0.0 @@ -15,7 +21,6 @@ let api = {}; api.addTenGems = { method: 'POST', url: '/development/addTenGems', - middlewares: [checkForDevelopmentMode, authWithHeaders(), cron], async handler (req, res) { let user = res.locals.user; @@ -38,7 +43,6 @@ api.addTenGems = { api.addHourglass = { method: 'POST', url: '/development/addHourglass', - middlewares: [checkForDevelopmentMode, authWithHeaders(), cron], async handler (req, res) { let user = res.locals.user; From a3d7edd0c154a5101c387f44d4e40964ab302451 Mon Sep 17 00:00:00 2001 From: Keith Holliday Date: Fri, 18 Mar 2016 14:05:14 -0500 Subject: [PATCH 4/4] Renamed namespace to debug and added unit test for middleware --- .../POST-debug_addHourglass.test.js} | 14 ++++---- .../POST-debug_addTenGems.test.js} | 14 ++++---- .../unit/middlewares/ensureDevelpmentMode.js | 36 +++++++++++++++++++ .../api-v3/{development.js => debug.js} | 16 ++++----- ...lopmentMode.js => ensureDevelpmentMode.js} | 2 +- 5 files changed, 59 insertions(+), 23 deletions(-) rename test/api/v3/integration/{development/POST-development_addHourglass.test.js => debug/POST-debug_addHourglass.test.js} (79%) rename test/api/v3/integration/{development/POST-development_addTenGems.test.js => debug/POST-debug_addTenGems.test.js} (79%) create mode 100644 test/api/v3/unit/middlewares/ensureDevelpmentMode.js rename website/src/controllers/api-v3/{development.js => debug.js} (66%) rename website/src/middlewares/api-v3/{developmentMode.js => ensureDevelpmentMode.js} (71%) diff --git a/test/api/v3/integration/development/POST-development_addHourglass.test.js b/test/api/v3/integration/debug/POST-debug_addHourglass.test.js similarity index 79% rename from test/api/v3/integration/development/POST-development_addHourglass.test.js rename to test/api/v3/integration/debug/POST-debug_addHourglass.test.js index 6ef111c130..767fa840f2 100644 --- a/test/api/v3/integration/development/POST-development_addHourglass.test.js +++ b/test/api/v3/integration/debug/POST-debug_addHourglass.test.js @@ -3,15 +3,19 @@ import { generateUser, } from '../../../../helpers/api-v3-integration.helper'; -describe('POST /development/addHourglass', () => { +describe('POST /debug/add-hourglass', () => { let userToGetHourGlass; before(async () => { userToGetHourGlass = await generateUser(); }); + after(() => { + nconf.set('IS_PROD', false); + }); + it('adds Hourglass to the current user', async () => { - await userToGetHourGlass.post('/development/addHourglass'); + await userToGetHourGlass.post('/debug/add-hourglass'); let userWithHourGlass = await userToGetHourGlass.get('/user'); @@ -21,15 +25,11 @@ describe('POST /development/addHourglass', () => { it('returns error when not in production mode', async () => { nconf.set('IS_PROD', true); - await expect(userToGetHourGlass.post('/development/addHourglass')) + await expect(userToGetHourGlass.post('/debug/add-hourglass')) .eventually.be.rejected.and.to.deep.equal({ code: 404, error: 'NotFound', message: 'Not found.', }); }); - - after(() => { - nconf.set('IS_PROD', false); - }); }); diff --git a/test/api/v3/integration/development/POST-development_addTenGems.test.js b/test/api/v3/integration/debug/POST-debug_addTenGems.test.js similarity index 79% rename from test/api/v3/integration/development/POST-development_addTenGems.test.js rename to test/api/v3/integration/debug/POST-debug_addTenGems.test.js index 82594c4d07..fd01aea5d3 100644 --- a/test/api/v3/integration/development/POST-development_addTenGems.test.js +++ b/test/api/v3/integration/debug/POST-debug_addTenGems.test.js @@ -3,15 +3,19 @@ import { generateUser, } from '../../../../helpers/api-v3-integration.helper'; -describe('POST /development/addTenGems', () => { +describe('POST /debug/add-ten-gems', () => { let userToGainTenGems; before(async () => { userToGainTenGems = await generateUser(); }); + after(() => { + nconf.set('IS_PROD', false); + }); + it('adds ten gems to the current user', async () => { - await userToGainTenGems.post('/development/addTenGems'); + await userToGainTenGems.post('/debug/add-ten-gems'); let userWithTenGems = await userToGainTenGems.get('/user'); @@ -21,15 +25,11 @@ describe('POST /development/addTenGems', () => { it('returns error when not in production mode', async () => { nconf.set('IS_PROD', true); - await expect(userToGainTenGems.post('/development/addTenGems')) + await expect(userToGainTenGems.post('/debug/add-ten-gems')) .eventually.be.rejected.and.to.deep.equal({ code: 404, error: 'NotFound', message: 'Not found.', }); }); - - after(() => { - nconf.set('IS_PROD', false); - }); }); diff --git a/test/api/v3/unit/middlewares/ensureDevelpmentMode.js b/test/api/v3/unit/middlewares/ensureDevelpmentMode.js new file mode 100644 index 0000000000..8d0f8efbab --- /dev/null +++ b/test/api/v3/unit/middlewares/ensureDevelpmentMode.js @@ -0,0 +1,36 @@ +/* eslint-disable global-require */ +import { + generateRes, + generateReq, + generateNext, +} from '../../../../helpers/api-unit.helper'; +import ensureDevelpmentMode from '../../../../../website/src/middlewares/api-v3/ensureDevelpmentMode'; +import { NotFound } from '../../../../../website/src/libs/api-v3/errors'; +import nconf from 'nconf'; + +describe('developmentMode middleware', () => { + let res, req, next; + + beforeEach(() => { + res = generateRes(); + req = generateReq(); + next = generateNext(); + }); + + it('returns not found when in production mode', () => { + sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true); + + ensureDevelpmentMode(req, res, next); + + expect(next).to.be.calledWith(new NotFound()); + }); + + it('passes when not in production', () => { + sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(false); + + ensureDevelpmentMode(req, res, next); + + expect(next).to.be.calledOnce; + expect(next.args[0]).to.be.empty; + }); +}); diff --git a/website/src/controllers/api-v3/development.js b/website/src/controllers/api-v3/debug.js similarity index 66% rename from website/src/controllers/api-v3/development.js rename to website/src/controllers/api-v3/debug.js index 2b252bbb8e..1aa5b08ffb 100644 --- a/website/src/controllers/api-v3/development.js +++ b/website/src/controllers/api-v3/debug.js @@ -1,17 +1,17 @@ import { authWithHeaders } from '../../middlewares/api-v3/auth'; import cron from '../../middlewares/api-v3/cron'; -import checkForDevelopmentMode from '../../middlewares/api-v3/developmentMode'; +import ensureDevelpmentMode from '../../middlewares/api-v3/ensureDevelpmentMode'; let api = {}; -api.development = { +api.debug = { method: 'all', - url: '/development/*', - middlewares: [checkForDevelopmentMode, authWithHeaders(), cron], + url: '/debug/*', + middlewares: [ensureDevelpmentMode, authWithHeaders(), cron], }; /** - * @api {post} /development/addTenGems Add ten gems to the current user + * @api {post} /debug/add-ten-gems Add ten gems to the current user * @apiVersion 3.0.0 * @apiName AddTenGems * @apiGroup Development @@ -20,7 +20,7 @@ api.development = { */ api.addTenGems = { method: 'POST', - url: '/development/addTenGems', + url: '/debug/add-ten-gems', async handler (req, res) { let user = res.locals.user; @@ -33,7 +33,7 @@ api.addTenGems = { }; /** - * @api {post} /development/addHourglass Add Hourglass to the current user + * @api {post} /debug/add-hourglass Add Hourglass to the current user * @apiVersion 3.0.0 * @apiName AddHourglass * @apiGroup Development @@ -42,7 +42,7 @@ api.addTenGems = { */ api.addHourglass = { method: 'POST', - url: '/development/addHourglass', + url: '/debug/add-hourglass', async handler (req, res) { let user = res.locals.user; diff --git a/website/src/middlewares/api-v3/developmentMode.js b/website/src/middlewares/api-v3/ensureDevelpmentMode.js similarity index 71% rename from website/src/middlewares/api-v3/developmentMode.js rename to website/src/middlewares/api-v3/ensureDevelpmentMode.js index 5c068df0ab..98f70d33f5 100644 --- a/website/src/middlewares/api-v3/developmentMode.js +++ b/website/src/middlewares/api-v3/ensureDevelpmentMode.js @@ -3,7 +3,7 @@ import { NotFound, } from '../../libs/api-v3/errors'; -module.exports = function checkForDevelopmentMode (req, res, next) { +module.exports = function ensureDevelpmentMode (req, res, next) { if (nconf.get('IS_PROD')) { next(new NotFound()); } else {