Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIR-932 : Story – Odour – Remit - Can you give details about the source of the smell? #175

Merged
merged 5 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions server/routes/__tests__/smell/source-details.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { submitGetRequest, submitPostRequest } from '../../../__test-helpers__/server.js'
import { questionSets } from '../../../utils/question-sets.js'
import constants from '../../../utils/constants.js'

const url = constants.routes.SMELL_SOURCE_DETAILS
const question = questionSets.SMELL.questions.SMELL_SOURCE_DETAILS
const header = question.text
const baseAnswer = {
questionId: question.questionId,
questionAsked: question.text,
questionResponse: true
}

const payload = {
answerId: 'yes',
siteName: 'Site name',
sourceAddress: 'Address Line',
sourceTown: 'town or city',
sourcePostcode: 'WA4 1HT'
}

describe(url, () => {
describe('GET', () => {
it(`Should return success response and correct view for ${url}`, async () => {
await submitGetRequest({ url }, header)
})
})

describe('POST', () => {
it('Happy: accepts valid answerId no and redirects to smell/contact-local-council', async () => {
const answerId = 'no'
const options = {
url,
payload: {
answerId
}
}
const response = await submitPostRequest(options)
expect(response.headers.location).toEqual(constants.routes.SMELL_CONTACT_LOCAL_COUNCIL)
})

// Happy: Accepts a complete address
it('Happy: accepts valid answerId yes and complete address with valid postcode', async () => {
const options = {
url,
payload
}
const response = await submitPostRequest(options)
expect(response.headers.location).toEqual(constants.routes.SMELL_LOCATION_HOME)
expect(response.request.yar.get(constants.redisKeys.SMELL_SOURCE_DETAILS)).toEqual([{
...baseAnswer,
answerId: question.answers.siteName.answerId,
otherDetails: payload.siteName
}, {
...baseAnswer,
answerId: question.answers.sourceAddress.answerId,
otherDetails: payload.sourceAddress
}, {
...baseAnswer,
answerId: question.answers.sourceTown.answerId,
otherDetails: payload.sourceTown
}, {
...baseAnswer,
answerId: question.answers.sourcePostcode.answerId,
otherDetails: payload.sourcePostcode
}])
})
// Happy: Accepts a partial address, but with complete mandatory fields
it('Happy: accepts valid answerId yes and complete address with valid postcode', async () => {
const partialPayload = JSON.parse(JSON.stringify(payload))
partialPayload.sourceAddress = ''

const options = {
url,
payload: partialPayload
}
const response = await submitPostRequest(options)
expect(response.headers.location).toEqual(constants.routes.SMELL_LOCATION_HOME)
expect(response.request.yar.get(constants.redisKeys.SMELL_SOURCE_DETAILS)).toEqual([{
...baseAnswer,
answerId: question.answers.siteName.answerId,
otherDetails: payload.siteName
}, {
...baseAnswer,
answerId: question.answers.sourceAddress.answerId,
otherDetails: ''
}, {
...baseAnswer,
answerId: question.answers.sourceTown.answerId,
otherDetails: payload.sourceTown
}, {
...baseAnswer,
answerId: question.answers.sourcePostcode.answerId,
otherDetails: payload.sourcePostcode
}])
})
it('Happy: accepts valid answerId yes and strips out postcode with special characters', async () => {
const partialPayload = JSON.parse(JSON.stringify(payload))
partialPayload.sourcePostcode = 'WA4 &^%$%$--1HT'

const options = {
url,
payload: partialPayload
}
const response = await submitPostRequest(options)
expect(response.headers.location).toEqual(constants.routes.SMELL_LOCATION_HOME)
expect(response.request.yar.get(constants.redisKeys.SMELL_SOURCE_DETAILS)).toEqual([{
...baseAnswer,
answerId: question.answers.siteName.answerId,
otherDetails: payload.siteName
}, {
...baseAnswer,
answerId: question.answers.sourceAddress.answerId,
otherDetails: payload.sourceAddress
}, {
...baseAnswer,
answerId: question.answers.sourceTown.answerId,
otherDetails: payload.sourceTown
}, {
...baseAnswer,
answerId: question.answers.sourcePostcode.answerId,
otherDetails: 'WA4 1HT'
}])
})
it('Sad: errors on no fields provided', async () => {
const options = {
url,
payload: {}
}
const response = await submitPostRequest(options, constants.statusCodes.OK)
expect(response.payload).toContain('There is a problem')
expect(response.payload).toContain('Answer yes if you can give details about where the smell is coming from')
})
it('Sad: valid answerId yes but errors on no fields provided', async () => {
const options = {
url,
payload: {
answerId: 'yes'
}
}
const response = await submitPostRequest(options, constants.statusCodes.OK)
expect(response.payload).toContain('There is a problem')
expect(response.payload).toContain('Enter a name')
expect(response.payload).toContain('Enter a town or city')
expect(response.payload).toContain('Enter a postcode')
})
it('Sad: errors on invalid postcode provided', async () => {
const options = {
url,
payload: {
...payload,
sourcePostcode: 'sdgfsfdgfdsgfdg'
}
}
const response = await submitPostRequest(options, constants.statusCodes.OK)
expect(response.payload).toContain('There is a problem')
expect(response.payload).toContain('Enter a full UK postcode')
})
})
})
3 changes: 2 additions & 1 deletion server/routes/__tests__/smell/start-date-time.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@ describe(url, () => {
it('Happy: accept a valid time for today and continue to SMELL_CURRENT', async () => {
const date = new Date()
const period = date.getHours() > 11 ? 'pm' : 'am'
const hours = date.getHours() > 12 ? date.getHours() - 12 : date.getHours()
const options = {
url,
payload: {
current: '0',
'date-day': '1',
'date-month': '1',
'date-year': '2024',
hour: [date.getHours().toString(), '1', '1'],
hour: [hours.toString(), '1', '1'],
minute: ['0', '1', '1'],
period: [period, 'am', 'am']
}
Expand Down
117 changes: 116 additions & 1 deletion server/routes/smell/source-details.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,130 @@
import constants from '../../utils/constants.js'
import { getErrorSummary } from '../../utils/helpers.js'
import { questionSets } from '../../utils/question-sets.js'

const question = questionSets.SMELL.questions.SMELL_SOURCE_DETAILS
const postcodeRegExp = /^([A-Za-z][A-Ha-hJ-Yj-y]?\d[A-Za-z0-9]? ?\d[A-Za-z]{2}|[Gg][Ii][Rr] ?0[Aa]{2})$/ // https://stackoverflow.com/a/51885364

const baseAnswer = {
questionId: question.questionId,
questionAsked: question.text,
questionResponse: true
}

const handlers = {
get: async (_request, h) => {
return h.view(constants.views.SMELL_SOURCE_DETAILS)
return h.view(constants.views.SMELL_SOURCE_DETAILS, {
...getContext()
})
},
post: async (request, h) => {
// cleanse postcode for special characters https://design-system.service.gov.uk/patterns/addresses/#allow-different-postcode-formats
if (request.payload.sourcePostcode) {
request.payload.sourcePostcode = request.payload.sourcePostcode.replace(/[^\w\s]/gi, '')
}

// validate payload for errors
const errorSummary = validatePayload(request.payload)
if (errorSummary.errorList.length > 0) {
return h.view(constants.views.SMELL_SOURCE_DETAILS, {
...getContext(),
errorSummary,
...request.payload,
yesChecked: request.payload.answerId === 'yes'
})
}

// handle redirects
if (request.payload.answerId === 'yes') {
// set answer in session
request.yar.set(constants.redisKeys.SMELL_SOURCE_DETAILS, buildAnswers(request.payload))
return h.redirect(constants.routes.SMELL_LOCATION_HOME)
} else if (request.payload.answerId === 'no') {
return h.redirect(constants.routes.SMELL_CONTACT_LOCAL_COUNCIL)
} else {
// do nothing
}

return null
}
}

const getContext = () => {
return {
question
}
}

const validatePayload = payload => {
const errorSummary = getErrorSummary()
if (!payload.answerId) {
errorSummary.errorList.push({
text: 'Answer yes if you can give details about where the smell is coming from',
href: '#answerId'
})
} else if (payload.answerId === 'yes') {
if (!payload.siteName) {
errorSummary.errorList.push({
text: 'Enter a name',
href: '#siteName'
})
}
if (!payload.sourceTown) {
errorSummary.errorList.push({
text: 'Enter a town or city',
href: '#sourceTown'
})
}
if (!payload.sourcePostcode) {
errorSummary.errorList.push({
text: 'Enter a postcode',
href: '#sourcePostcode'
})
} else if (!postcodeRegExp.test(payload.sourcePostcode)) {
errorSummary.errorList.push({
text: 'Enter a full UK postcode',
href: '#sourcePostcode'
})
} else {
// do nothing
}
} else {
// do nothing
}

return errorSummary
}

const buildAnswers = payload => {
return [{
...baseAnswer,
answerId: question.answers.siteName.answerId,
otherDetails: payload.siteName
}, {
...baseAnswer,
answerId: question.answers.sourceAddress.answerId,
otherDetails: payload.sourceAddress
}, {
...baseAnswer,
answerId: question.answers.sourceTown.answerId,
otherDetails: payload.sourceTown
},
{
...baseAnswer,
answerId: question.answers.sourcePostcode.answerId,
otherDetails: payload.sourcePostcode
}]
}

export default [
{
method: 'GET',
path: constants.routes.SMELL_SOURCE_DETAILS,
handler: handlers.get
},
{
method: 'POST',
path: constants.routes.SMELL_SOURCE_DETAILS,
handler: handlers.post
}
]
1 change: 1 addition & 0 deletions server/routes/smell/source.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const handlers = {
// set answer in session
request.yar.set(constants.redisKeys.SMELL_SOURCE, buildAnswers(answerId))

// handle redirects
if (answerId === question.answers.local.answerId || answerId === question.answers.neighbour.answerId || answerId === question.answers.rubbish.answerId) {
return h.redirect(constants.routes.SMELL_REPORT_LOCAL_COUNCIL)
} else if (answerId === question.answers.unknown.answerId) {
Expand Down
23 changes: 23 additions & 0 deletions server/utils/question-sets.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,29 @@ const questionSets = {
}
}
},
SMELL_SOURCE_DETAILS: {
questionId: 200,
key: constants.redisKeys.SMELL_SOURCE_DETAILS,
text: 'Can you give details about where the smell is coming from?',
answers: {
siteName: {
answerId: 203,
text: 'Name of person or site'
},
sourceAddress: {
answerId: 204,
text: 'Street name and number (if known)'
},
sourceTown: {
answerId: 205,
text: 'Town or city'
},
sourcePostcode: {
answerId: 205,
text: 'Postcode (if known)'
}
}
},
SMELL_LOCATION_HOME: {
questionId: 1,
key: constants.redisKeys.SMELL_LOCATION_HOME,
Expand Down
Loading
Loading