From e3ec7f92efa4b29ff37b0d58f48c68f852f57e24 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Tue, 13 Jul 2021 07:41:35 -0700 Subject: [PATCH] Increased contact REST endpoint to 100% unit test coverage --- src/controllers/rest-api/contact/index.js | 51 ++++++++++-- src/controllers/rest-api/contact/router.js | 43 ---------- .../contact.rest.controller.unit.js} | 31 +++++++- .../contact/contact.rest.router.unit.js | 78 +++++++++++++++++++ 4 files changed, 153 insertions(+), 50 deletions(-) delete mode 100644 src/controllers/rest-api/contact/router.js rename test/unit/controllers/rest-api/{a04-contact.rest-api.js => contact/contact.rest.controller.unit.js} (63%) create mode 100644 test/unit/controllers/rest-api/contact/contact.rest.router.unit.js diff --git a/src/controllers/rest-api/contact/index.js b/src/controllers/rest-api/contact/index.js index 3ea84eb..e4db57a 100644 --- a/src/controllers/rest-api/contact/index.js +++ b/src/controllers/rest-api/contact/index.js @@ -2,16 +2,57 @@ REST API library for /contact route. */ -const ContactRESTRouter = require('./router') +// Public npm libraries. +const Router = require('koa-router') -class ContactRESTController { +// Local libraries. +const ContactRESTControllerLib = require('./controller') +const Validators = require('../middleware/validators') + +class ContactRouter { constructor (localConfig = {}) { - this.contactRESTRouter = new ContactRESTRouter() + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating Contact REST Controller.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating Contact REST Controller.' + ) + } + + const dependencies = { + adapters: this.adapters, + useCases: this.useCases + } + + // Encapsulate dependencies. + this.contactRESTController = new ContactRESTControllerLib(dependencies) + this.validators = new Validators() + + // Instantiate the router and set the base route. + const baseUrl = '/contact' + this.router = new Router({ prefix: baseUrl }) } attach (app) { - this.contactRESTRouter.attachControllers(app) + if (!app) { + throw new Error( + 'Must pass app object when attaching REST API controllers.' + ) + } + + // Define the routes and attach the controller. + this.router.post('/email', this.contactRESTController.email) + + // Attach the Controller routes to the Koa app. + app.use(this.router.routes()) + app.use(this.router.allowedMethods()) } } -module.exports = ContactRESTController +module.exports = ContactRouter diff --git a/src/controllers/rest-api/contact/router.js b/src/controllers/rest-api/contact/router.js deleted file mode 100644 index 02914f9..0000000 --- a/src/controllers/rest-api/contact/router.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - REST Router for the /contact route. -*/ - -// Public npm libraries. -const Router = require('koa-router') - -// Local libraries. -const ContactRESTControllerLib = require('./controller') -const Validators = require('../middleware/validators') - -// let _this - -class ContactRESTRouter { - constructor (localConfig = {}) { - // Encapsulate dependencies. - this.contactRESTController = new ContactRESTControllerLib() - this.validators = new Validators() - - // Instantiate the router and set the base route. - const baseUrl = '/contact' - this.router = new Router({ prefix: baseUrl }) - - // _this = this - } - - attachControllers (app) { - if (!app) { - throw new Error( - 'Must pass app object when attaching REST API controllers.' - ) - } - - // Define the routes and attach the controller. - this.router.post('/email', this.contactRESTController.email) - - // Attach the Controller routes to the Koa app. - app.use(this.router.routes()) - app.use(this.router.allowedMethods()) - } -} - -module.exports = ContactRESTRouter diff --git a/test/unit/controllers/rest-api/a04-contact.rest-api.js b/test/unit/controllers/rest-api/contact/contact.rest.controller.unit.js similarity index 63% rename from test/unit/controllers/rest-api/a04-contact.rest-api.js rename to test/unit/controllers/rest-api/contact/contact.rest.controller.unit.js index 9e30e79..73e2f07 100644 --- a/test/unit/controllers/rest-api/a04-contact.rest-api.js +++ b/test/unit/controllers/rest-api/contact/contact.rest.controller.unit.js @@ -6,12 +6,12 @@ const assert = require('chai').assert const sinon = require('sinon') -const ContactController = require('../../../../src/controllers/rest-api/contact/controller') +const ContactController = require('../../../../../src/controllers/rest-api/contact/controller') let uut let sandbox let ctx -const mockContext = require('../../../unit/mocks/ctx-mock').context +const mockContext = require('../../../../unit/mocks/ctx-mock').context describe('Contact', () => { before(async () => {}) @@ -58,4 +58,31 @@ describe('Contact', () => { assert.isTrue(ctx.response.body.success) }) }) + + describe('#handleError', () => { + it('should pass an error message', () => { + try { + const err = { + status: 422, + message: 'Unprocessable Entity' + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Unprocessable Entity') + } + }) + + it('should still throw error if there is no message', () => { + try { + const err = { + status: 404 + } + + uut.handleError(ctx, err) + } catch (err) { + assert.include(err.message, 'Not Found') + } + }) + }) }) diff --git a/test/unit/controllers/rest-api/contact/contact.rest.router.unit.js b/test/unit/controllers/rest-api/contact/contact.rest.router.unit.js new file mode 100644 index 0000000..d3e8934 --- /dev/null +++ b/test/unit/controllers/rest-api/contact/contact.rest.router.unit.js @@ -0,0 +1,78 @@ +/* + Unit tests for the REST API handler for the /users endpoints. +*/ + +// Public npm libraries +const assert = require('chai').assert +const sinon = require('sinon') + +// Local support libraries +const adapters = require('../../../mocks/adapters') +const UseCasesMock = require('../../../mocks/use-cases') +// const app = require('../../../mocks/app-mock') + +const ContactRouter = require('../../../../../src/controllers/rest-api/contact') +let uut +let sandbox +// let ctx + +// const mockContext = require('../../../../unit/mocks/ctx-mock').context + +describe('#Contact-REST-Router', () => { + // const testUser = {} + + beforeEach(() => { + const useCases = new UseCasesMock() + uut = new ContactRouter({ adapters, useCases }) + + sandbox = sinon.createSandbox() + + // Mock the context object. + // ctx = mockContext() + }) + + afterEach(() => sandbox.restore()) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new ContactRouter() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating Contact REST Controller.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new ContactRouter({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating Contact REST Controller.' + ) + } + }) + }) + + describe('#attach', () => { + it('should throw an error if app is not passed in.', () => { + try { + uut.attach() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Must pass app object when attaching REST API controllers.' + ) + } + }) + }) +})