diff --git a/app/controllers/notifications-setup.controller.js b/app/controllers/notifications-setup.controller.js index ad9580d1c2..795fd3eddb 100644 --- a/app/controllers/notifications-setup.controller.js +++ b/app/controllers/notifications-setup.controller.js @@ -2,6 +2,7 @@ const ReturnsPeriodService = require('../services/notifications/setup/returns-period.service.js') const SubmitReturnsPeriodService = require('../services/notifications/setup/submit-returns-period.service.js') +const InitiateSessionService = require('../services/notifications/setup/initiate-session.service') /** * Controller for /notifications/setup endpoints @@ -18,6 +19,12 @@ async function viewReturnsPeriod(_request, h) { }) } +async function setup(_request, h) { + const session = await InitiateSessionService.go() + + return h.redirect(`/system/${basePath}/${session.id}/returns-period`) +} + async function submitReturnsPeriod(request, h) { const { payload } = request @@ -34,5 +41,6 @@ async function submitReturnsPeriod(request, h) { module.exports = { viewReturnsPeriod, + setup, submitReturnsPeriod } diff --git a/app/routes/notifications-setup.routes.js b/app/routes/notifications-setup.routes.js index 857cb3616d..536898673f 100644 --- a/app/routes/notifications-setup.routes.js +++ b/app/routes/notifications-setup.routes.js @@ -2,12 +2,24 @@ const NotificationsSetupController = require('../controllers/notifications-setup.controller.js') -const basePath = '/notifications/setup/' +const basePath = '/notifications/setup' const routes = [ { method: 'GET', - path: basePath + 'returns-period', + path: basePath, + options: { + handler: NotificationsSetupController.setup, + auth: { + access: { + scope: ['returns'] + } + } + } + }, + { + method: 'GET', + path: basePath + '/{sessionId}/returns-period', options: { handler: NotificationsSetupController.viewReturnsPeriod, auth: { @@ -19,7 +31,7 @@ const routes = [ }, { method: 'POST', - path: basePath + 'returns-period', + path: basePath + '/{sessionId}/returns-period', options: { handler: NotificationsSetupController.submitReturnsPeriod, auth: { diff --git a/app/services/notifications/setup/initiate-session.service.js b/app/services/notifications/setup/initiate-session.service.js new file mode 100644 index 0000000000..e404a647b2 --- /dev/null +++ b/app/services/notifications/setup/initiate-session.service.js @@ -0,0 +1,31 @@ +'use strict' + +/** + * Initiates the session record used for setting up a new ad-hoc returns notification + * @module InitiateSessionService + */ + +const SessionModel = require('../../../models/session.model.js') + +/** + * Initiates the session record used for setting up a new ad-hoc returns notification + * + * During the setup journey for a new ad-hoc returns notification we temporarily store the data in a `SessionModel` + * instance. It is expected that on each page of the journey the GET will fetch the session record and use it to + * populate the view. + * When the page is submitted the session record will be updated with the next piece of data. + * + * At the end when the journey is complete the data from the session will be used to create the ad-hoc returns + * notification and the session record itself deleted. + * + * @returns {Promise} the newly created session record + */ +async function go() { + // NOTE: data defaults to {} when a new record is created. But Objection.js throws a 'The query is empty' if we pass + // nothing into `insert()`. + return SessionModel.query().insert({ data: {} }).returning('id') +} + +module.exports = { + go +} diff --git a/test/controllers/notifications.controller.test.js b/test/controllers/notifications-setup.controller.test.js similarity index 71% rename from test/controllers/notifications.controller.test.js rename to test/controllers/notifications-setup.controller.test.js index 9603fdba53..d01aeb5e56 100644 --- a/test/controllers/notifications.controller.test.js +++ b/test/controllers/notifications-setup.controller.test.js @@ -11,6 +11,7 @@ const { expect } = Code const { postRequestOptions } = require('../support/general.js') // Things we need to stub +const InitiateSessionService = require('../../app/services/notifications/setup/initiate-session.service.js') const ReturnsPeriodService = require('../../app/services/notifications/setup/returns-period.service.js') const SubmitReturnsPeriodService = require('../../app/services/notifications/setup/submit-returns-period.service.js') @@ -19,6 +20,7 @@ const { init } = require('../../app/server.js') describe('Notifications Setup controller', () => { const basePath = '/notifications/setup' + const session = { id: 'e0c77b74-7326-493d-be5e-0d1ad41594b5', data: {} } let getOptions let postOptions @@ -42,12 +44,40 @@ describe('Notifications Setup controller', () => { Sinon.restore() }) + describe('notifications/setup', () => { + describe('GET', () => { + beforeEach(async () => { + getOptions = { + method: 'GET', + url: '/notifications/setup', + auth: { + strategy: 'session', + credentials: { scope: ['returns'] } + } + } + }) + + describe('when a request is valid', () => { + beforeEach(async () => { + Sinon.stub(InitiateSessionService, 'go').resolves(session) + }) + + it('redirects successfully', async () => { + const response = await server.inject(getOptions) + + expect(response.statusCode).to.equal(302) + expect(response.headers.location).to.equal(`/system/notifications/setup/${session.id}/returns-period`) + }) + }) + }) + }) + describe('notifications/setup/returns-period', () => { describe('GET', () => { beforeEach(async () => { getOptions = { method: 'GET', - url: basePath + '/returns-period', + url: basePath + `/${session.id}/returns-period`, auth: { strategy: 'session', credentials: { scope: ['returns'] } @@ -56,6 +86,7 @@ describe('Notifications Setup controller', () => { }) describe('when a request is valid', () => { beforeEach(async () => { + Sinon.stub(InitiateSessionService, 'go').resolves(session) Sinon.stub(ReturnsPeriodService, 'go').returns(_viewReturnsPeriod()) }) @@ -75,11 +106,12 @@ describe('Notifications Setup controller', () => { describe('when the request succeeds', () => { describe('and the validation fails', () => { beforeEach(async () => { + Sinon.stub(InitiateSessionService, 'go').resolves(session) Sinon.stub(SubmitReturnsPeriodService, 'go').returns({ ..._viewReturnsPeriod(), error: 'Something went wrong' }) - postOptions = postRequestOptions(basePath + '/returns-period', {}) + postOptions = postRequestOptions(basePath + `/${session.id}/returns-period`, {}) }) it('returns the page successfully with the error summary banner', async () => { @@ -93,7 +125,7 @@ describe('Notifications Setup controller', () => { describe('and the validation succeeds', () => { beforeEach(async () => { Sinon.stub(SubmitReturnsPeriodService, 'go').returns({ redirect: 'send-notice' }) - postOptions = postRequestOptions(basePath + '/returns-period', {}) + postOptions = postRequestOptions(basePath + `/${session.id}/returns-period`, {}) }) it('redirects the to the next page', async () => { diff --git a/test/services/notifications/setup/initiate-session.service.test.js b/test/services/notifications/setup/initiate-session.service.test.js new file mode 100644 index 0000000000..dce38fb4bf --- /dev/null +++ b/test/services/notifications/setup/initiate-session.service.test.js @@ -0,0 +1,26 @@ +'use strict' + +// Test framework dependencies +const Lab = require('@hapi/lab') +const Code = require('@hapi/code') + +const { describe, it } = (exports.lab = Lab.script()) +const { expect } = Code + +// Test helpers +const SessionModel = require('../../../../app/models/session.model.js') + +// Thing under test +const InitiateSessionService = require('../../../../app/services/notifications/setup/initiate-session.service.js') + +describe('Notifications Setup - Initiate Session service', () => { + describe('when called', () => { + it('creates a new session record with an empty data property', async () => { + const result = await InitiateSessionService.go() + + const matchingSession = await SessionModel.query().findById(result.id) + + expect(matchingSession.data).to.equal({}) + }) + }) +})