Skip to content

Commit

Permalink
Add 'Credit for this win' form step
Browse files Browse the repository at this point in the history
  • Loading branch information
paulgain committed Jan 18, 2024
1 parent 685f005 commit 6cea61c
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/client/components/Resource/Resource.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ export const createMetadataResource = (name, endpoint) => {
rawResult,
]
const Component = (props) => (
<EntityResource transformer={transformer} {...props} id="__METADATA__" />
<EntityResource transformer={transformer} id="__METADATA__" {...props} />
)

Component.propTypes = _.omit(Component.propTypes, 'id')
Expand Down
102 changes: 96 additions & 6 deletions src/client/modules/ExportWins/Form/CreditForThisWinStep.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,111 @@
import React from 'react'
import { H3 } from '@govuk-react/heading'
import styled from 'styled-components'

import ResourceOptionsField from '../../../components/Form/elements/ResourceOptionsField'
import { useFormContext } from '../../../../client/components/Form/hooks'
import { Step, FieldInput } from '../../../components'
import { OPTION_YES, OPTIONS_YES_NO } from '../../../../common/constants'
import { MID_GREY } from '../../../../client/utils/colours'
import { StyledHintParagraph } from './styled'
import { steps } from './constants'
import {
TeamTypeResource,
HQTeamRegionOrPostsResource,
} from '../../../components/Resource'
import {
Step,
FieldRadios,
FieldTypeahead,
FieldAddAnother,
FieldAdvisersTypeahead,
} from '../../../components'

const StyledFieldInput = styled(FieldInput)({
display: 'none',
const Container = styled('div')({
borderLeft: `3px solid ${MID_GREY}`,
marginLeft: 18,
paddingLeft: 34,
})

const StyledFieldRadios = styled(FieldRadios)({
marginBottom: 0,
})

const CreditForThisWinStep = () => {
// eslint-disable-next-line no-unused-vars
const { values } = useFormContext()

// Determine the child group count by selecting any field
const officerCount = Object.keys(values).filter((key) =>
key.startsWith('contributing_officer')
).length

return (
<Step name={steps.CREDIT_FOR_THIS_WIN}>
<h1>Credit for this win</h1>
<StyledFieldInput name="hidden" type="text" />
<H3 data-test="step-heading">Credit for this win</H3>
<StyledHintParagraph data-test="hint">
Other teams that helped with this win should be added so they can be
credited, this will not reduce your credit for this win.
</StyledHintParagraph>
<StyledFieldRadios
name="credit_for_win"
label="Did any other teams help with this win?"
inline={true}
options={OPTIONS_YES_NO}
required="Select Yes or No"
/>
{values.credit_for_win === OPTION_YES && (
<Container>
<FieldAddAnother
name="addAnother"
label="Contributing advisers"
hint="Up to 5 advisers can be added."
itemName="contributing-adviser"
buttonText="Add another"
limitChildGroupCount={5}
dataTestPrefix="contributing-advisers-"
initialChildGroupCount={officerCount || 1}
>
{({ groupIndex }) => (
<>
<FieldAdvisersTypeahead
name={`contributing_officer_${groupIndex}`}
label="Contributing officer"
required="Enter a contributing officer"
/>
<ResourceOptionsField
name={`team_type_${groupIndex}`}
id={`contributors-${groupIndex}`}
resource={TeamTypeResource}
field={FieldTypeahead}
fullWidth={true}
label="Team type"
required="Enter a team type"
/>
{values[`team_type_${groupIndex}`] && (
// Should a user choose a team type, then choose a HQ team, region or post
// then change their mind and change the team type for a second time we
// want the component below to rerender and display 'Start typing'. We don't
// want the previous selection displayed after they've changed the team type.
// To ensure this happens we've added a key prop and set it to the team type
// id, when the id changes the component updates.
<ResourceOptionsField
key={values[`team_type_${groupIndex}`].value}
name={`hq_team_${groupIndex}`}
id={`contributors-${groupIndex}`}
resource={HQTeamRegionOrPostsResource}
field={FieldTypeahead}
fullWidth={true}
label="HQ team, region or post"
required="Enter a HQ team, region or post"
payload={{
team_type: values[`team_type_${groupIndex}`].value,
}}
/>
)}
</>
)}
</FieldAddAnother>
</Container>
)}
</Step>
)
}
Expand Down
8 changes: 7 additions & 1 deletion src/client/modules/ExportWins/Form/CustomerDetailsStep.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import React from 'react'
import styled from 'styled-components'

import { useFormContext } from '../../../../client/components/Form/hooks'
import { Step } from '../../../components'
import { Step, FieldInput } from '../../../components'
import { steps } from './constants'

const StyledFieldInput = styled(FieldInput)({
display: 'none',
})

const CustomerDetailsStep = () => {
// eslint-disable-next-line no-unused-vars
const { values } = useFormContext()
return (
<Step name={steps.CUSTOMER_DETAILS}>
<h1>Customer details</h1>
<StyledFieldInput name="hidden" type="text" />
</Step>
)
}
Expand Down
7 changes: 7 additions & 0 deletions src/client/modules/ExportWins/Form/styled.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import styled from 'styled-components'

import { DARK_GREY } from '../../../utils/colours'

export const StyledHintParagraph = styled('p')({
color: DARK_GREY,
})
123 changes: 122 additions & 1 deletion test/functional/cypress/specs/export-win/add-export-win-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
assertLocalHeader,
assertErrorSummary,
assertFieldTypeahead,
assertFieldRadiosWithLegend,
} from '../../support/assertions'
import { clickContinueButton } from '../../support/actions'
import { companyFaker } from '../../fakers/companies'
Expand Down Expand Up @@ -145,8 +146,128 @@ describe('Adding an export win', () => {
})

context('Credit for this win', () => {
it('should complete this step and continue to "Customer details"', () => {
beforeEach(() =>
cy.visit(`${urls.companies.exportWins.create()}${creditForThisWin}`)
)

it('should render a step heading', () => {
cy.get('[data-test="step-heading"]').should(
'have.text',
'Credit for this win'
)
})

it('should render a hint', () => {
cy.get('[data-test="hint"]').should(
'have.text',
'Other teams that helped with this win should be added so they can be credited, this will not reduce your credit for this win.'
)
})

it('should render two unselected radio buttons', () => {
cy.get('[data-test="field-credit_for_win"]').then((element) => {
assertFieldRadiosWithLegend({
element,
legend: 'Did any other teams help with this win?',
optionsCount: 2,
})
})
cy.get('[data-test="credit-for-win-yes"]').should('not.be.checked')
cy.get('[data-test="credit-for-win-no"]').should('not.be.checked')
})

it('should go to the next step when selecting "No" and then "Continue"', () => {
cy.get('[data-test="credit-for-win-no"]').check()
clickContinueAndAssertUrl(customerDetails)
})

it('should render a legend and hint text', () => {
cy.get('[data-test="credit-for-win-yes"]').check()
cy.get('[data-test="field-addAnother"]')
.find('legend')
.eq(0)
.should('have.text', 'Contributing advisers')
cy.get('[data-test="hint-text"]').should(
'have.text',
'Up to 5 advisers can be added.'
)
})

it('should render a Typeahead for the contributing officer', () => {
cy.get('[data-test="credit-for-win-yes"]').check()
cy.get('[data-test="field-contributing_officer_0"]').then((element) => {
assertFieldTypeahead({
element,
label: 'Contributing officer',
})
})
})

it('should render a Typeahead for the team type', () => {
cy.get('[data-test="credit-for-win-yes"]').check()
cy.get('[data-test="field-team_type_0"]').then((element) => {
assertFieldTypeahead({
element,
label: 'Team type',
})
})
})

it('should render an "Add another" button', () => {
cy.get('[data-test="credit-for-win-yes"]').check()
cy.get('[data-test="add-another"]').should('exist')
})

it('should display validation error messages on mandatory fields', () => {
clickContinueButton()
// Assert Yes and No radio buttons
assertErrorSummary(['Select Yes or No'])
assertFieldError(
cy.get('[data-test="field-credit_for_win"]'),
'Select Yes or No',
true
)
cy.get('[data-test="credit-for-win-yes"]').check()
clickContinueButton()
// Assert Contributing officer and Team type
assertErrorSummary(['Enter a contributing officer', 'Enter a team type'])
assertFieldError(
cy.get('[data-test="field-contributing_officer_0"]'),
'Enter a contributing officer',
false
)
assertFieldError(
cy.get('[data-test="field-team_type_0"]'),
'Enter a team type',
false
)
// Select a team type to render the HQ team, region or post field
cy.get('[data-test="field-team_type_0"]')
.find('input')
.as('teamTypeInput')
cy.get('@teamTypeInput').type('Inv')
cy.get('@teamTypeInput').type('{downarrow}{enter}{esc}')
clickContinueButton()
// Assert HQ team, region or post
assertErrorSummary([
'Enter a contributing officer',
'Enter a HQ team, region or post',
])
assertFieldError(
cy.get('[data-test="field-hq_team_0"]'),
'Enter a HQ team, region or post',
false
)
})

it('should complete this step and continue to "Credit for this win"', () => {
const contributingOfficer = '[data-test="field-contributing_officer_0"]'
const teamType = '[data-test="field-team_type_0"]'
const hqTeam = '[data-test="field-hq_team_0"]'
cy.get('[data-test="credit-for-win-yes"]').check()
cy.get(contributingOfficer).selectTypeaheadOption('David')
cy.get(teamType).selectTypeaheadOption('Investment (ITFG or IG)')
cy.get(hqTeam).selectTypeaheadOption('DIT Education')
clickContinueAndAssertUrl(customerDetails)
})
})
Expand Down

0 comments on commit 6cea61c

Please sign in to comment.