Skip to content

Commit

Permalink
Describe E2E 'Manager creates new OOSB record' journey
Browse files Browse the repository at this point in the history
We start a new `/e2e/tests/v2Manage.spec` file to compartmentalise these
user journeys, starting with:

> Future manager marks a bed as out of service in the V2 Manage area
>
>   Given I am signed in as a future manager
>   And I am on the list of premises page
>
>   When choose to view the detail of a particular premises
>   Then I should see the premises page
>
>   When I choose to manage its beds
>   And I pick a particular bed to manage
>   Then I see the V2 Bed page
>   And I should be able to mark a bed as out of service
>
>   When I fill in and submit the v2 Manage out-of-service-bed form
>   Then I am redirected back to the V2 bed page
>   And I see the success message on the 'history' pane of the bed page

The differences in v2/v1 behaviour are achieved with:

- a new `v2BedLink()` 'Manage (bed)' link used on the premises' bed list to
  link to the new v2 bed page

- a new `v2BedActions()` widget which offers FUTURE_MANAGER the
  link to the new v2 "create out of service bed" form from the v2
  bed page

Also: the "Future manager creates V2 OOSB record" was duplicated in
both:

1. `integration_tests/tests/v2Manage/beds.cy.ts` and
2. `integration_tests/tests/v2Manage/outOfServiceBeds.cy.ts`

We delete [1].
  • Loading branch information
edavey committed Jul 8, 2024
1 parent f338f43 commit a71cc11
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 65 deletions.
25 changes: 25 additions & 0 deletions e2e/pages/manage/v2BedPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Page, expect } from '@playwright/test'
import { BasePage } from '../basePage'

export class V2BedPage extends BasePage {
static async initialize(page: Page, premisesName: string) {
await expect(page.locator('h1')).toContainText('View bed information')
await expect(page.locator('.moj-identity-bar__title')).toContainText(premisesName)
return new V2BedPage(page)
}

async clickActions() {
await this.page.getByRole('button', { name: 'Actions' }).click()
}

async clickMarkBedAsOutOfService() {
await this.clickActions()
await this.page.getByRole('menuitem', { name: 'Create out of service bed record' }).click()
}

async showsOutOfServiceBedRecordedSuccessMessage() {
await expect(this.page.locator('.govuk-notification-banner')).toContainText(
'The out of service bed has been recorded',
)
}
}
49 changes: 49 additions & 0 deletions e2e/pages/manage/v2MarkBedAsOutOfServicePage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Page, expect } from '@playwright/test'
import { getDate, getMonth, getYear } from 'date-fns'
import { faker } from '@faker-js/faker/locale/en_GB'
import { BasePage } from '../basePage'

export class V2MarkBedAsOutOfServicePage extends BasePage {
startDate: Date

static async initialize(page: Page, title?: string) {
if (title) {
await expect(page.locator('h1')).toContainText(title)
}
const instance = new V2MarkBedAsOutOfServicePage(page)
instance.startDate = faker.date.soon({ days: 600 })
return instance
}

endDate() {
const endDate = new Date(this.startDate)
endDate.setDate(endDate.getDate() + 2)
return endDate
}

async enterOutOfServiceFromDate() {
const { startDate } = this
await this.page.getByRole('group', { name: 'Start date' }).getByLabel('Day').fill(getDate(startDate).toString())
await this.page.getByRole('group', { name: 'Start date' }).getByLabel('Month').fill(getMonth(startDate).toString())
await this.page.getByRole('group', { name: 'Start date' }).getByLabel('Year').fill(getYear(startDate).toString())
}

async enterOutOfServiceToDate() {
const endDate = this.endDate()
await this.page.getByRole('group', { name: 'End date' }).getByLabel('Day').fill(getDate(endDate).toString())
await this.page.getByRole('group', { name: 'End date' }).getByLabel('Month').fill(getMonth(endDate).toString())
await this.page.getByRole('group', { name: 'End date' }).getByLabel('Year').fill(getYear(endDate).toString())
}

async completeForm() {
await this.enterOutOfServiceFromDate()
await this.enterOutOfServiceToDate()
await this.checkRadio('Planned Refurbishment')
await this.page.getByLabel('Work order reference number').fill('123456789')
await this.page
.getByLabel(
'Provide detail about why the bed is out of service. If FM works are required you should update this record with any progress on that work.',
)
.fill('Reasons for bed being out of service')
}
}
52 changes: 52 additions & 0 deletions e2e/tests/v2Manage.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { test } from '../test'
import { visitDashboard } from '../steps/apply'
import { PremisesListPage } from '../pages/manage/premisesListPage'
import { PremisesPage } from '../pages/manage/premisesPage'
import { BedsPage } from '../pages/manage/bedsPage'
import { V2BedPage } from '../pages/manage/v2BedPage'
import { V2MarkBedAsOutOfServicePage } from '../pages/manage/v2MarkBedAsOutOfServicePage'
import { signIn } from '../steps/signIn'

test.describe.configure({ mode: 'parallel' })

const premisesName = 'Test AP 10'

test('Future manager marks a bed as out of service in the V2 Manage area', async ({ page, futureManager }) => {
// Given I am signed in as a future manager
await signIn(page, futureManager)

// And I am on the list of premises page
const dashboard = await visitDashboard(page)
await dashboard.clickManage()
const premisesListPage = await PremisesListPage.initialize(page, 'List of Approved Premises')

// When choose to view the detail of a particular premises
await premisesListPage.choosePremises(premisesName)

// Then I should see the premises page
const premisesPage = await PremisesPage.initialize(page, premisesName)

// When I choose to manage its beds
await premisesPage.viewRooms()
const manageBedsPage = await BedsPage.initialize(page, 'Manage beds')

// And I pick a particular bed to manage
await manageBedsPage.viewAvailableBed()

// Then I see the V2 Bed page
const v2BedPage = await V2BedPage.initialize(page, premisesName)

// And I should be able to mark a bed as out of service
await v2BedPage.clickMarkBedAsOutOfService()

// When I fill in and submit the v2 Manage out-of-service-bed form
const v2MarkBedAsOutOfServicePage = await V2MarkBedAsOutOfServicePage.initialize(page, 'Mark a bed as out of service')
await v2MarkBedAsOutOfServicePage.completeForm()
await v2MarkBedAsOutOfServicePage.clickSave()

// Then I am redirected back to the V2 bed page
const revisitedV2BedPage = await V2BedPage.initialize(page, premisesName)

// And I see the success message on the 'history' pane of the bed page
await revisitedV2BedPage.showsOutOfServiceBedRecordedSuccessMessage()
})
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ export class OutOfServiceBedCreatePage extends Page {
cy.get('input[name="outOfServiceBed[referenceNumber]"]').type(outOfServiceBed.referenceNumber)
}

if (outOfServiceBed.notes) {
cy.get('[name="outOfServiceBed[notes]"]').type(outOfServiceBed.notes)
}
cy.get(`input[name="outOfServiceBed[reason]"][value="${outOfServiceBed.reason.id}"]`).check()
cy.get('[name="outOfServiceBed[notes]"]').type(outOfServiceBed.notes)
}

public clickSubmit(): void {
Expand Down
47 changes: 0 additions & 47 deletions integration_tests/tests/v2Manage/beds.cy.ts

This file was deleted.

27 changes: 17 additions & 10 deletions integration_tests/tests/v2Manage/outOfServiceBeds.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
OutOfServiceBedIndexPage,
OutOfServiceBedShowPage,
} from '../../pages/v2Manage/outOfServiceBeds'
import BedShowPage from '../../pages/v2Manage/bed/bedShow'
import Page from '../../pages/page'
import { signIn } from '../signIn'

Expand All @@ -22,29 +23,31 @@ context('OutOfServiceBeds', () => {
cy.task('stubOutOfServiceBedReasons')
})

it('should allow me to create a out of service bed', () => {
it('should allow me to create an out of service bed', () => {
const premises = extendedPremisesSummaryFactory.build()
cy.task('stubPremisesSummary', premises)
const fullPremises = premisesFactory.build({ id: premises.id })
cy.task('stubSinglePremises', fullPremises)

// Given I am signed in as a future manager
signIn(['future_manager'])

// When I navigate to the out of service bed form
const outOfServiceBed = outOfServiceBedFactory.build({
startDate: '2022-02-11',
endDate: '2022-03-11',
})
cy.task('stubOutOfServiceBedCreate', { premisesId: premises.id, outOfServiceBed })

// stub ultimate API call when redirecting to bed page
const bedDetail = bedDetailFactory.build({ id: outOfServiceBed.bed.id })
cy.task('stubBed', { premisesId: premises.id, bedDetail })

// Given I am signed in as a future manager
signIn(['future_manager'])

// When I navigate to the out of service bed form
const page = OutOfServiceBedCreatePage.visit(premises.id, outOfServiceBed.bed.id)

// And I fill out the form
page.completeForm(outOfServiceBed)
page.clickSubmit()

// Then a out of service bed should have been created in the API
// Then a POST to the API should be made to create the OOSB record
cy.task('verifyOutOfServiceBedCreate', {
premisesId: premises.id,
outOfServiceBed,
Expand All @@ -56,10 +59,14 @@ context('OutOfServiceBeds', () => {
expect(requestBody.endDate).equal(outOfServiceBed.endDate)
expect(requestBody.notes).equal(outOfServiceBed.notes)
expect(requestBody.referenceNumber).equal(outOfServiceBed.referenceNumber)
expect(requestBody.reason).equal(outOfServiceBed.reason.id)
})

// And I should be navigated to the premises detail page and see the confirmation message
page.shouldShowBanner('The out of service bed has been recorded')
// And I should be redirected to the v2 bed page
const v2BedPage = Page.verifyOnPage(BedShowPage)

// And I should see the confirmation message
v2BedPage.shouldShowBanner('The out of service bed has been recorded')
})

it('should show errors', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ describe('OutOfServiceBedsController', () => {
})

describe('create', () => {
it('creates a outOfService bed and redirects to the premises page', async () => {
it('creates a outOfService bed and redirects to the v2 bed page', async () => {
const requestHandler = outOfServiceBedController.create()

request.params = {
Expand All @@ -120,7 +120,9 @@ describe('OutOfServiceBedsController', () => {
bedId: request.params.bedId,
})
expect(request.flash).toHaveBeenCalledWith('success', 'The out of service bed has been recorded')
expect(response.redirect).toHaveBeenCalledWith(paths.premises.show({ premisesId: request.params.premisesId }))
expect(response.redirect).toHaveBeenCalledWith(
paths.v2Manage.premises.beds.show({ premisesId: request.params.premisesId, bedId: outOfServiceBed.bed.id }),
)
})

describe('when errors are raised', () => {
Expand Down
2 changes: 1 addition & 1 deletion server/controllers/v2Manage/outOfServiceBedsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default class OutOfServiceBedsController {
await this.outOfServiceBedService.createOutOfServiceBed(req.user.token, premisesId, outOfServiceBed)

req.flash('success', 'The out of service bed has been recorded')
return res.redirect(paths.premises.show({ premisesId }))
return res.redirect(paths.v2Manage.premises.beds.show({ premisesId, bedId }))
} catch (error) {
const redirectPath = paths.v2Manage.outOfServiceBeds.new({ premisesId, bedId })

Expand Down
2 changes: 1 addition & 1 deletion server/testutils/factories/outOfServiceBed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const outOfServiceBedFactory = Factory.define<OutOfServiceBed>(() => ({
apArea: namedIdFactory.build(),
reason: cas1ReferenceDataFactory.outOfServiceBedReason().build(),
referenceNumber: faker.helpers.arrayElement([faker.string.uuid(), undefined]),
notes: faker.helpers.arrayElement([faker.lorem.sentence(), undefined]),
notes: faker.lorem.sentence(),
daysLostCount: faker.number.int({ min: 1, max: 100 }),
temporality: faker.helpers.arrayElement(['past', 'current', 'future'] as const),
status: faker.helpers.arrayElement(['active', 'cancelled'] as const),
Expand Down
15 changes: 15 additions & 0 deletions server/utils/bedUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
statusRow,
title,
v1BedLink,
v2BedActions,
v2BedLink,
} from './bedUtils'
import { DateFormats } from './dateUtils'
Expand Down Expand Up @@ -187,6 +188,20 @@ describe('bedUtils', () => {
})
})

describe('v2BedActions', () => {
it('returns the actions for the V2 bed manage page', () => {
expect(v2BedActions(bedDetail, premisesId)).toEqual({
items: [
{
text: 'Create out of service bed record',
classes: 'govuk-button--secondary',
href: paths.v2Manage.outOfServiceBeds.new({ premisesId, bedId: bedDetail.id }),
},
],
})
})
})

describe('encodeOverbooking', () => {
it('encodes an overbooking entry to Base64', () => {
const overbooking = bedOccupancyEntryOverbookingUiFactory.build()
Expand Down
12 changes: 12 additions & 0 deletions server/utils/bedUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ export const bedActions = (bed: BedDetail, premisesId: string) => {
}
}

export const v2BedActions = (bed: BedDetail, premisesId: string) => {
return {
items: [
{
text: 'Create out of service bed record',
classes: 'govuk-button--secondary',
href: paths.v2Manage.outOfServiceBeds.new({ premisesId, bedId: bed.id }),
},
],
}
}

const bedLinkForUser = (bed: BedSummary, premisesId: string, user?: UserDetails): string => {
if (user && user.roles?.includes('future_manager')) {
return v2BedLink(bed, premisesId)
Expand Down
1 change: 1 addition & 0 deletions server/views/v2Manage/outOfServiceBeds/new.njk
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
{{ govukTextarea({
id: "notes",
name: "outOfServiceBed[notes]",
value: outOfServiceBed.notes,
label: {
text: "Provide detail about why the bed is out of service. If FM works are required you should update this record with any progress on that work.",
classes: "govuk-fieldset__legend--s"
Expand Down
5 changes: 4 additions & 1 deletion server/views/v2Manage/premises/beds/show.njk
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% from "govuk/components/notification-banner/macro.njk" import govukNotificationBanner %}
{% from "govuk/components/table/macro.njk" import govukTable %}
{% from "govuk/components/back-link/macro.njk" import govukBackLink %}

Expand All @@ -18,13 +19,15 @@
{% block content %}
<div class="govuk-grid-row">
<div class="govuk-grid-column-full-width">
{% include "../../../_messages.njk" %}

{% if UserUtils.hasManagerRole(user) %}
{{
mojIdentityBar({
title: {
html: '<span class="govuk-caption-l">' + premises.name + '</span> <h1 class="govuk-heading-l"><span class="govuk-caption-l">Room ' + bed.roomName + ', Bed ' + bed.name + '</span>' + pageHeading + '</h1>'
},
menus: [BedUtils.bedActions(bed, premises.id)]
menus: [BedUtils.v2BedActions(bed, premises.id)]
})
}}
{% else %}
Expand Down

0 comments on commit a71cc11

Please sign in to comment.