Skip to content

Commit

Permalink
Merge pull request #47 from ministryofjustice/CBA-73-add-a-new-questi…
Browse files Browse the repository at this point in the history
…on-flow-for-community-supervision

CBA-73 - update current offences task with community supervision and CPP details pages
  • Loading branch information
libuk authored Jan 8, 2025
2 parents 1eea7b1 + 774ab28 commit 51cddfb
Show file tree
Hide file tree
Showing 21 changed files with 462 additions and 32 deletions.
7 changes: 5 additions & 2 deletions e2e-tests/steps/apply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import {
} from './aboutThePersonSection'
import { completeHealthNeedsTask, completeRiskToSelfTask, completeRoshTask } from './risksAndNeedsSection'
import { completeAreaInformationTask, completeFundingInformationTask } from './areaAndFundingSection'
import { completeCurrentOffencesTask, completeOffenceHistoryTask } from './offenceAndLicenceInformationSection'
import {
completeCommunitySupervisionAndCurrentOffencesTask,
completeOffenceHistoryTask,
} from './offenceAndLicenceInformationSection'
import { completeCheckAnswersTask } from './checkAnswersSection'
import { TestOptions } from '../testOptions'
import {
Expand Down Expand Up @@ -75,7 +78,7 @@ export const completeRisksAndNeedsSection = async (page: Page, name: string) =>
}

export const completeOffenceInformationSection = async (page: Page, name: string) => {
await completeCurrentOffencesTask(page, name)
await completeCommunitySupervisionAndCurrentOffencesTask(page, name)
await completeOffenceHistoryTask(page, name)
}

Expand Down
21 changes: 19 additions & 2 deletions e2e-tests/steps/offenceAndLicenceInformationSection.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
import { Page } from '@playwright/test'
import { ApplyPage, TaskListPage } from '../pages/apply'

export const completeCurrentOffencesTask = async (page: Page, name: string) => {
export const completeCommunitySupervisionAndCurrentOffencesTask = async (page: Page, name: string) => {
const taskListPage = new TaskListPage(page)
await taskListPage.clickTask('Add current offences')
await taskListPage.clickTask('Community supervision and current offences')

await completeCommunitySupervisionPage(page, name)
await completeCPPDetailsPage(page, name)
await completeCurrentOffenceDetailsPage(page, name)
await completeCurrentOffencesPage(page, name)
}

async function completeCommunitySupervisionPage(page: Page, name: string) {
const communitySupervisionPage = await ApplyPage.initialize(page, `Is ${name} currently supervised by probation?`)
await communitySupervisionPage.checkRadio('Yes')
await communitySupervisionPage.clickButton('Save and continue')
}

async function completeCPPDetailsPage(page: Page, name: string) {
const cppDetailsPage = await ApplyPage.initialize(page, `Who is ${name}'s Community Probation Practitioner (CPP)?`)
await cppDetailsPage.fillField('Full name', 'A. CPP')
await cppDetailsPage.fillField('Probation region', 'south')
await cppDetailsPage.fillField('Contact email address', '[email protected]')
await cppDetailsPage.fillField('Contact number', '12345')
await cppDetailsPage.clickSave()
}

async function completeCurrentOffenceDetailsPage(page: Page, name: string) {
const currentOffenceDetailsPage = await ApplyPage.initialize(page, `Add ${name}'s current offence details`)
await currentOffenceDetailsPage.fillField('Offence title', 'Stalking')
Expand Down
13 changes: 12 additions & 1 deletion integration_tests/fixtures/applicationData.json
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,18 @@
"additionalInformationDetail": "some information"
}
},
"current-offences": {
"community-supervision-and-current-offences": {
"community-supervision": {
"probationSupervision": "yes"
},
"cpp-details": {
"cppDetails": {
"name": "A. CPP",
"probationRegion": "some region",
"email": "[email protected]",
"telephone": "012345"
}
},
"current-offence-data": [
{
"titleAndNumber": "Arson",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { itShouldHaveNextValue, itShouldHavePreviousValue } from '../../../shared-examples'
import { personFactory, applicationFactory } from '../../../../testutils/factories/index'
import CommunitySupervision from './communitySupervision'

describe('Community supervision', () => {
const application = applicationFactory.build({ person: personFactory.build({ name: 'Roger Smith' }) })

describe('when the applicant is under probation supervision', () => {
itShouldHaveNextValue(new CommunitySupervision({ probationSupervision: 'yes' }, application), 'cpp-details')
})

describe('when the applicant is not under probation supervision', () => {
itShouldHaveNextValue(new CommunitySupervision({ probationSupervision: 'no' }, application), '')
})

itShouldHavePreviousValue(new CommunitySupervision({}, application), 'taskList')

describe('items', () => {
it('returns the radio with the expected label text', () => {
const page = new CommunitySupervision({ probationSupervision: 'yes' }, application)
expect(page.items()).toEqual([
{
checked: true,
text: 'Yes',
value: 'yes',
},
{
checked: false,
text: 'No',
value: 'no',
},
])
})
})

describe('errors', () => {
it('should return errors when the questions are blank', () => {
const page = new CommunitySupervision({}, application)

expect(page.errors()).toEqual({
probationSupervision: 'Confirm whether the applicant is currently supervised by probation',
})
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Radio, TaskListErrors, YesOrNo } from '@approved-premises/ui'
import { Cas2Application as Application } from '@approved-premises/api'
import { Page } from '../../../utils/decorators'
import TaskListPage from '../../../taskListPage'
import { nameOrPlaceholderCopy } from '../../../../utils/utils'
import { getQuestions } from '../../../utils/questions'
import { convertKeyValuePairToRadioItems } from '../../../../utils/formUtils'

export type CommunitySupervisionBody = {
probationSupervision: YesOrNo
}

@Page({
name: 'community-supervision',
bodyProperties: ['probationSupervision'],
})
export default class CommunitySupervision implements TaskListPage {
documentTitle = 'Is the person currently supervised by probation?'

personName = nameOrPlaceholderCopy(this.application.person)

title

questions = getQuestions(this.personName)['community-supervision-and-current-offences']['community-supervision']

body: CommunitySupervisionBody

constructor(
body: Partial<CommunitySupervisionBody>,
private readonly application: Application,
) {
this.body = body as CommunitySupervisionBody
this.title = this.questions.probationSupervision.question
}

previous() {
return 'taskList'
}

next() {
if (this.body.probationSupervision === 'yes') {
return 'cpp-details'
}
return ''
}

items() {
return convertKeyValuePairToRadioItems(
this.questions.probationSupervision.answers,
this.body.probationSupervision,
) as Array<Radio>
}

errors() {
const errors: TaskListErrors<this> = {}
if (!this.body.probationSupervision) {
errors.probationSupervision = 'Confirm whether the applicant is currently supervised by probation'
}
return errors
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { itShouldHavePreviousValue, itShouldHaveNextValue } from '../../../shared-examples'
import { personFactory, applicationFactory } from '../../../../testutils/factories/index'
import CPPDetails from './cppDetails'

describe('CPPDetails', () => {
const application = applicationFactory.build({ person: personFactory.build({ name: 'Roger Smith' }) })

describe('title', () => {
it('personalises the page title', () => {
const page = new CPPDetails({}, application)

expect(page.title).toEqual("Who is Roger Smith's Community Probation Practitioner (CPP)?")
})
})

itShouldHavePreviousValue(new CPPDetails({}, application), 'community-supervision')
itShouldHaveNextValue(new CPPDetails({}, application), 'current-offences')

describe('errors', () => {
describe('when they have not provided any answer', () => {
it('returns errors', () => {
const page = new CPPDetails({}, application)
expect(page.errors()).toEqual({
name: "Enter the CPP's full name",
probationRegion: 'Enter the probation region',
email: "Enter the CPP's email address",
telephone: "Enter the CPP's contact number",
})
})
})
})

describe('response', () => {
it('returns data in expected format', () => {
const page = new CPPDetails(
{
name: 'a name',
probationRegion: 'a probation region',
email: 'an email address',
telephone: 'a phone number',
},
application,
)

expect(page.response()).toEqual({
"Who is Roger Smith's Community Probation Practitioner (CPP)?": `a name\r\na probation region\r\nan email address\r\na phone number`,
})
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { TaskListErrors } from '@approved-premises/ui'
import { Cas2Application as Application } from '@approved-premises/api'
import { Page } from '../../../utils/decorators'
import TaskListPage from '../../../taskListPage'
import { nameOrPlaceholderCopy } from '../../../../utils/utils'
import { getQuestions } from '../../../utils/questions'

type CPPDetailsBody = {
name: string
probationRegion: string
email: string
telephone: string
}

@Page({
name: 'cpp-details',
bodyProperties: ['name', 'probationRegion', 'email', 'telephone'],
})
export default class CPPDetails implements TaskListPage {
documentTitle = "Who is the person's Community Probation Practitioner (CPP)?"

personName = nameOrPlaceholderCopy(this.application.person)

title

questions = getQuestions(this.personName)['community-supervision-and-current-offences']['cpp-details']

options: Record<string, string>

body: CPPDetailsBody

constructor(
body: Partial<CPPDetailsBody>,
private readonly application: Application,
) {
this.body = body as CPPDetailsBody
this.title = this.questions.cppDetails.question
}

previous() {
return 'community-supervision'
}

next() {
return 'current-offences'
}

response() {
return {
[this.title]: `${this.body.name}\r\n${this.body.probationRegion}\r\n${this.body.email}\r\n${this.body.telephone}`,
}
}

errors() {
const errors: TaskListErrors<this> = {}
if (!this.body.name) {
errors.name = "Enter the CPP's full name"
}
if (!this.body.probationRegion) {
errors.probationRegion = 'Enter the probation region'
}
if (!this.body.email) {
errors.email = "Enter the CPP's email address"
}
if (!this.body.telephone) {
errors.telephone = "Enter the CPP's contact number"
}
return errors
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('CurrentOffences', () => {
const applicationWithData = applicationFactory.build({
person: personFactory.build({ name: 'Roger Smith' }),
data: {
'current-offences': {
'community-supervision-and-current-offences': {
'current-offence-data': [
{
titleAndNumber: 'Stalking',
Expand Down Expand Up @@ -63,7 +63,7 @@ describe('CurrentOffences', () => {
summary: 'summary detail',
outstandingCharges: 'Yes',
outstandingChargesDetail: 'some detail',
removeLink: `/applications/${applicationWithData.id}/tasks/current-offences/pages/current-offence-data/0/removeFromList?redirectPage=current-offences`,
removeLink: `/applications/${applicationWithData.id}/tasks/community-supervision-and-current-offences/pages/current-offence-data/0/removeFromList?redirectPage=current-offences`,
},
{
titleAndNumber: 'Arson',
Expand All @@ -74,7 +74,7 @@ describe('CurrentOffences', () => {
summary: 'second summary detail',
outstandingCharges: 'No',
outstandingChargesDetail: '',
removeLink: `/applications/${applicationWithData.id}/tasks/current-offences/pages/current-offence-data/1/removeFromList?redirectPage=current-offences`,
removeLink: `/applications/${applicationWithData.id}/tasks/community-supervision-and-current-offences/pages/current-offence-data/1/removeFromList?redirectPage=current-offences`,
},
])
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ export default class CurrentOffences implements TaskListPage {

dataPageName = 'current-offence-data'

taskName = 'current-offences'
taskName = 'community-supervision-and-current-offences'

currentOffenceQuestions = getQuestions('')['current-offences']['current-offence-data']
currentOffenceQuestions = getQuestions('')['community-supervision-and-current-offences']['current-offence-data']

constructor(
body: Partial<CurrentOffencesBody>,
Expand Down Expand Up @@ -86,7 +86,7 @@ export default class CurrentOffences implements TaskListPage {
}

static async initialize(body: Partial<CurrentOffenceDataBody>, application: Application) {
if (!application.data['current-offences']?.['current-offence-data']) {
if (!application.data['community-supervision-and-current-offences']?.['current-offence-data']) {
return new CurrentOffenceData(body, application)
}
return new CurrentOffences({}, application)
Expand All @@ -103,7 +103,7 @@ export default class CurrentOffences implements TaskListPage {
errors() {
const errors: TaskListErrors<this> = {}

if (!this.application.data['current-offences']?.['current-offence-data'].length) {
if (!this.application.data['community-supervision-and-current-offences']?.['current-offence-data'].length) {
errors.offenceList = 'Current offences must be added to the application'
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ export default class CurrentOffenceData implements TaskListPage {

body: CurrentOffenceDataBody

taskName = 'current-offences'
taskName = 'community-supervision-and-current-offences'

pageName = 'current-offence-data'

questions = getQuestions('')['current-offences']['current-offence-data']
questions = getQuestions('')['community-supervision-and-current-offences']['current-offence-data']

offenceCategories: Array<SelectItem>

Expand All @@ -58,7 +58,9 @@ export default class CurrentOffenceData implements TaskListPage {
) {
this.body = body as CurrentOffenceDataBody
this.offenceCategories = this.getCategoriesAsItemsForSelect(this.body.offenceCategory)
this.hasPreviouslySavedACurrentOffence = Boolean(application.data['current-offences']?.['current-offence-data'])
this.hasPreviouslySavedACurrentOffence = Boolean(
application.data['community-supervision-and-current-offences']?.['current-offence-data'],
)
}

private getCategoriesAsItemsForSelect(selectedItem: string): Array<SelectItem> {
Expand Down
Loading

0 comments on commit 51cddfb

Please sign in to comment.