Skip to content

Commit

Permalink
Merge pull request #112 from DEFRA/610
Browse files Browse the repository at this point in the history
[610] receive method for licence
  • Loading branch information
DrogoNevets authored Jan 13, 2025
2 parents 46a4738 + 825cfae commit 19a319d
Show file tree
Hide file tree
Showing 24 changed files with 465 additions and 18 deletions.
9 changes: 7 additions & 2 deletions src/server/check-answers/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const testAddress = {
addressPostcode: 'RG24 8RR'
}
const testEmailAddress = '[email protected]'
const testReceiveMethod = 'email'

const originDefaultState = {
onOffFarm: 'off',
Expand All @@ -28,7 +29,8 @@ const originDefaultState = {
}

const licenceDefaultState = {
emailAddress: testEmailAddress
emailAddress: testEmailAddress,
receiveMethod: testReceiveMethod
}

const destinationDefaultState = {
Expand Down Expand Up @@ -56,6 +58,8 @@ const emailContent = [
testAddress.addressPostcode,
'## Where are the animals going to?',
expectedDestinationText,
'## How would you like this licence sent to you?',
testReceiveMethod,
'## What email address would you like the licence sent to?',
testEmailAddress
].join('\n')
Expand Down Expand Up @@ -109,7 +113,8 @@ describe('#CheckAnswers', () => {
expect(taskListValues[2].innerHTML).toContain(testCphNumber)
expect(taskListValues[3].innerHTML).toContain(testAddress.addressLine1)
expect(taskListValues[4].innerHTML).toContain(expectedDestinationText)
expect(taskListValues[5].innerHTML).toContain(testEmailAddress)
expect(taskListValues[5].innerHTML).toContain(testReceiveMethod)
expect(taskListValues[6].innerHTML).toContain(testEmailAddress)

expect(statusCode).toBe(statusCodes.ok)
})
Expand Down
59 changes: 59 additions & 0 deletions src/server/common/model/answer/receiveMethod/receiveMethod.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import Joi from 'joi'
import { AnswerModel } from '../answer-model.js'
import { validateAnswerAgainstSchema } from '../validation.js'

export const receiveMethodPayloadSchema = Joi.object({
receiveMethod: Joi.string().required().valid('email', 'post').messages({
'any.required': 'Select how you would like this licence sent to you',
'any.only': 'Select how you would like this licence sent to you'
})
})

/**
* export @typedef {string} ReceiveMethodData
* @typedef {{ receiveMethod: string }} ReceiveMethodPayload
*/

/**
* @augments AnswerModel<ReceiveMethodPayload>
*/
export class ReceiveMethodAnswer extends AnswerModel {
/**
* @returns {string | undefined}
*/
get value() {
return this._data?.receiveMethod
}

get html() {
return this._data?.receiveMethod ?? ''
}

/**
* @returns { ReceiveMethodData}
*/
toState() {
return this.value?.replace(/\s+/g, '') ?? ''
}

validate() {
return validateAnswerAgainstSchema(
receiveMethodPayloadSchema,
this._data ?? {}
)
}

_extractFields({ receiveMethod }) {
return { receiveMethod }
}

/**
* @param { ReceiveMethodData | undefined} state
* @returns { ReceiveMethodAnswer}
*/
static fromState(state) {
return new ReceiveMethodAnswer(
state !== undefined ? { receiveMethod: state } : undefined
)
}
}
81 changes: 81 additions & 0 deletions src/server/common/model/answer/receiveMethod/receiveMethod.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { ReceiveMethodAnswer } from './receiveMethod.js'

const validReceiveMethodPayload = {
receiveMethod: 'email'
}

describe('#ReceiveMethod.validate', () => {
it('should return true for valid receiveMethod', () => {
const receiveMethod = new ReceiveMethodAnswer(validReceiveMethodPayload)
const { isValid } = receiveMethod.validate()

expect(isValid).toBe(true)
})

it('should return false for an empty input', () => {
const receiveMethod = new ReceiveMethodAnswer({
receiveMethod: 'invalid value'
})

const { isValid, errors } = receiveMethod.validate()

expect(isValid).toBe(false)
expect(errors.receiveMethod.text).toBe(
'Select how you would like this licence sent to you'
)
})
})

describe('#ReceiveMethod.toState', () => {
it('should replace missing data with blank string', () => {
const receiveMethod = new ReceiveMethodAnswer()
const data = receiveMethod.toState()

expect(data).toBe('')
})

it('should pass through valid data unaltered', () => {
const receiveMethod = new ReceiveMethodAnswer(validReceiveMethodPayload)
const data = receiveMethod.toState()

expect(data).toEqual(validReceiveMethodPayload.receiveMethod)
})

it('should remove whitespace', () => {
const receiveMethod = new ReceiveMethodAnswer({
receiveMethod: 'p o s t'
})

expect(receiveMethod.toState()).toBe('post')
})
})

describe('#ReceiveMethod.fromState', () => {
it('should return just the receiveMethod from the payload', () => {
const receiveMethod = new ReceiveMethodAnswer(validReceiveMethodPayload)
const state = receiveMethod.toState()
expect(ReceiveMethodAnswer.fromState(state).value).toEqual(
validReceiveMethodPayload.receiveMethod
)
})

it('should return an undefined value if the state is undefined', () => {
expect(ReceiveMethodAnswer.fromState(undefined).value).toBeUndefined()
})

it('should return an empty object if the state is undefined', () => {
expect(ReceiveMethodAnswer.fromState(undefined)._data).toBeUndefined()
})
})

describe('#ReceiveMethod.html', () => {
it('should return the receiveMethod if present', () => {
const receiveMethod = new ReceiveMethodAnswer(validReceiveMethodPayload)
expect(receiveMethod.html).toBe(validReceiveMethodPayload.receiveMethod)
})

it('should return an empty string if receiveMethod is not present', () => {
const receiveMethod = new ReceiveMethodAnswer()
expect(receiveMethod.html).toBe('')
})
})
4 changes: 2 additions & 2 deletions src/server/common/model/section/licence/licence.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SectionModel } from '../section-model/section-model.js'
import { emailAddressPage } from '~/src/server/licence/email-address/index.js'
import { receiveMethodPage } from '~/src/server/licence/receiveMethod/index.js'

/**
* export @typedef {{
Expand All @@ -9,7 +9,7 @@ import { emailAddressPage } from '~/src/server/licence/email-address/index.js'
*/

export class LicenceSection extends SectionModel {
static firstPageFactory = () => emailAddressPage
static firstPageFactory = () => receiveMethodPage

/**
* @param {LicenceData | undefined} data
Expand Down
7 changes: 4 additions & 3 deletions src/server/common/model/section/licence/licence.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EmailAddressPage } from '~/src/server/licence/email-address/index.js'
import { ReceiveMethodPage } from '~/src/server/licence/receiveMethod/index.js'
import { LicenceSection } from './licence.js'

const testEmail = '[email protected]'
Expand All @@ -7,7 +7,8 @@ describe('Licence', () => {
describe('validate', () => {
it('should return valid if all nested objects are valid', () => {
const originData = {
emailAddress: testEmail
emailAddress: testEmail,
receiveMethod: 'email'
}
const result = LicenceSection.fromState(originData).validate()

Expand All @@ -22,7 +23,7 @@ describe('Licence', () => {
const result = LicenceSection.fromState(originData).validate()

expect(result.isValid).toBe(false)
expect(result.firstInvalidPage).toBeInstanceOf(EmailAddressPage)
expect(result.firstInvalidPage).toBeInstanceOf(ReceiveMethodPage)
})
})
})
2 changes: 2 additions & 0 deletions src/server/destination/another-destination/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export class AnotherDestinationExitPage extends ExitPage {
pageTitle = 'This service is not available for your movement type'
urlPath = `/destination/can-not-use-service`
view = `destination/another-destination/index`
sectionKey = 'destination'
key = 'another-destination'
}
export const anotherDestinationPage = new AnotherDestinationExitPage()

Expand Down
22 changes: 22 additions & 0 deletions src/server/licence/postExitPage/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ExitPage } from '../../common/model/page/exit-page-model.js'
import { PageController } from '../../common/controller/page-controller/page-controller.js'

/**
* @import { ServerRegisterPluginObject } from '@hapi/hapi'
*/

export class ExitPagePost extends ExitPage {
urlPath = '/licence/post'
pageTitle = 'This service does not currently send licences by post'
view = `licence/postExitPage/index`
sectionKey = 'licence'
key = 'post'
}
export const exitPagePost = new ExitPagePost()

/**
* @satisfies {ServerRegisterPluginObject<void>}
*/
export const postExitPage = new PageController(exitPagePost, {
methods: ['GET']
}).plugin()
12 changes: 12 additions & 0 deletions src/server/licence/postExitPage/index.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{% from "govuk/components/radios/macro.njk" import govukRadios %}
{% extends 'layouts/page.njk' %}
{% block content %}
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<h1 class="gem-c-title__text govuk-heading-l"></h1>
<div class="govuk-body" data-testid="app-page-body">
<!-- put content here -->
</div>
</div>
</div>
{% endblock %}
12 changes: 12 additions & 0 deletions src/server/licence/postExitPage/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ExitPagePost } from './index.js'

describe('#PostController', () => {
it('should have the correct properties', () => {
const page = new ExitPagePost()
expect(page.pageTitle).toBe(
'This service does not currently send licences by post'
)
expect(page.urlPath).toBe('/licence/post')
expect(page.view).toBe('licence/postExitPage/index')
})
})
43 changes: 43 additions & 0 deletions src/server/licence/receiveMethod/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Sets up the routes used in the cph number page.
* These routes are registered in src/server/router.js.
*/

import { ReceiveMethodAnswer } from '~/src/server/common/model/answer/receiveMethod/receiveMethod.js'
import { QuestionPage } from '../../common/model/page/question-page-model.js'
import { QuestionPageController } from '../../common/controller/question-page-controller/question-page-controller.js'

import { emailAddressPage } from '../email-address/index.js'
import { exitPagePost } from '../postExitPage/index.js'

export class ReceiveMethodPage extends QuestionPage {
urlPath = '/receiving-the-licence/licence-email-or-post'
sectionKey = 'licence'

question = 'How would you like this licence sent to you?'

questionKey = 'receiveMethod'

view = 'licence/receiveMethod/index'
Answer = ReceiveMethodAnswer

/** @param {ReceiveMethodAnswer} answer */
nextPage(answer) {
if (answer.value === 'post') {
return exitPagePost
}
return emailAddressPage
}
}
export const receiveMethodPage = new ReceiveMethodPage()

/**
* @satisfies {ServerRegisterPluginObject<void>}
*/
export const receiveMethod = new QuestionPageController(
receiveMethodPage
).plugin()

/**
* @import { ServerRegisterPluginObject } from '@hapi/hapi'
*/
28 changes: 28 additions & 0 deletions src/server/licence/receiveMethod/index.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{% from "govuk/components/radios/macro.njk" import govukRadios %}
{% from "govuk/components/fieldset/macro.njk" import govukFieldset %}
{% extends 'layouts/questions.njk' %}
{% block questions %}
{% call govukFieldset() %}
{{
govukRadios({
name: "receiveMethod",
id: "receive-method",
fieldset:{},
value: value,
items: [
{
id: "receiveMethod",
value: "email",
text: "Email"
},
{
id: "post",
value: "post",
text: "Post"
}
],
errorMessage: errors.receiveMethod
})
}}
{% endcall %}
{% endblock %}
Loading

0 comments on commit 19a319d

Please sign in to comment.