diff --git a/package-lock.json b/package-lock.json index d69a75c53..18077a2de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { - "@defra/forms-model": "^3.0.674", + "@defra/forms-model": "^3.0.677", "@defra/hapi-tracing": "^1.29.0", "@defra/interactive-map": "^0.0.22-alpha", "@elastic/ecs-pino-format": "^1.5.0", @@ -239,7 +239,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -2085,7 +2084,6 @@ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@keyv/serialize": "^1.1.1" } @@ -2228,7 +2226,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -2268,7 +2265,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -3520,9 +3516,9 @@ } }, "node_modules/@defra/forms-model": { - "version": "3.0.675", - "resolved": "https://registry.npmjs.org/@defra/forms-model/-/forms-model-3.0.675.tgz", - "integrity": "sha512-78j5PrvUFaRYT5u4nsdxd8MizJqCaEarHIuPd5qTr/0PwS5j5Au0oT1wmWwki+9trkfz6it/r8kVXHL+/Zfwjw==", + "version": "3.0.677", + "resolved": "https://registry.npmjs.org/@defra/forms-model/-/forms-model-3.0.677.tgz", + "integrity": "sha512-VTTELU2dSd6JJ8dUkijZsWg02p51SbGssIKMG4FKWXyzERgvU9f7daIWd4KZZMEfzHdx/Jue+BYIvWLsdHrUaw==", "license": "OGL-UK-3.0", "dependencies": { "@joi/date": "^2.1.1", @@ -4419,7 +4415,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/babel": "3.10.1", "@docusaurus/bundler": "3.10.1", @@ -4594,7 +4589,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.10.1.tgz", "integrity": "sha512-2jRVrtzjf8LClGTHQlwlwuD3wQXRx3WEoF7XUarJ8Ou+0onV+SLtejsyfY9JLpfUh9hPhXM4pbBGkyAY4Bi3HQ==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/core": "3.10.1", "@docusaurus/logger": "3.10.1", @@ -4628,7 +4622,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.10.1.tgz", "integrity": "sha512-0YtmIeoNo1fIw65LO8+/1dPgmDV86UmhMkow37gzjytuiCSQm9xob6PJy0L4kuQEMTLfUOGvkXvZr7GPrHquMA==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/mdx-loader": "3.10.1", "@docusaurus/module-type-aliases": "3.10.1", @@ -7368,7 +7361,6 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", "license": "MIT", - "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -11323,7 +11315,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -11520,7 +11511,6 @@ "integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.56.1", @@ -11560,7 +11550,6 @@ "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", @@ -12365,7 +12354,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -12442,7 +12430,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -13491,7 +13478,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -13850,7 +13836,6 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "license": "MIT", - "peer": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -17392,7 +17377,6 @@ "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -17580,7 +17564,6 @@ "integrity": "sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/types": "^8.35.0", "comment-parser": "^1.4.1", @@ -21383,7 +21366,6 @@ "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "30.2.0", "@jest/types": "30.2.0", @@ -22601,7 +22583,6 @@ "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", "license": "BSD-3-Clause", - "peer": true, "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", @@ -22668,7 +22649,6 @@ "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", @@ -27582,7 +27562,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -28979,7 +28958,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -29557,7 +29535,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -29567,7 +29544,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -29612,7 +29588,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/react": "*" }, @@ -29641,7 +29616,6 @@ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -31168,7 +31142,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -32421,7 +32394,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-syntax-patches-for-csstree": "^1.0.19", @@ -33171,7 +33143,6 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -33408,8 +33379,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/tsx": { "version": "4.21.0", @@ -33417,7 +33387,6 @@ "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" @@ -33612,7 +33581,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -34289,7 +34257,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.4.tgz", "integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==", "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", diff --git a/package.json b/package.json index c2fe13540..9ef4a4e11 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ }, "license": "SEE LICENSE IN LICENSE", "dependencies": { - "@defra/forms-model": "^3.0.674", + "@defra/forms-model": "^3.0.677", "@defra/hapi-tracing": "^1.29.0", "@defra/interactive-map": "^0.0.22-alpha", "@elastic/ecs-pino-format": "^1.5.0", diff --git a/src/server/plugins/engine/components/FormComponent.ts b/src/server/plugins/engine/components/FormComponent.ts index d6686fd3c..04a4a8d04 100644 --- a/src/server/plugins/engine/components/FormComponent.ts +++ b/src/server/plugins/engine/components/FormComponent.ts @@ -44,10 +44,20 @@ export class FormComponent extends ComponentBase { this.type = type this.hint = hint - this.label = - 'shortDescription' in def && def.shortDescription - ? def.shortDescription - : def.title + + this.label = this.getLabel(def) + } + + getLabel(def: FormComponentsDef) { + if ('errorDescription' in def && def.errorDescription) { + return def.errorDescription + } + + if ('shortDescription' in def && def.shortDescription) { + return def.shortDescription + } + + return def.title } get keys() { diff --git a/src/server/plugins/engine/components/TextField.test.ts b/src/server/plugins/engine/components/TextField.test.ts index 492e0fff5..5b2d8a1e2 100644 --- a/src/server/plugins/engine/components/TextField.test.ts +++ b/src/server/plugins/engine/components/TextField.test.ts @@ -209,7 +209,33 @@ describe('TextField', () => { describe('Validation', () => { describe.each([ { - description: 'Use short description if it exists', + description: 'Use error description if it exists', + component: { + title: 'What is your example text?', + errorDescription: 'Example text', + shortDescription: 'Your example text', + name: 'myComponent', + type: ComponentType.TextField, + options: {}, + schema: {} + } satisfies TextFieldComponent, + assertions: [ + { + input: getFormData(''), + output: { + value: getFormData(''), + errors: [ + expect.objectContaining({ + text: 'Enter example text' + }) + ] + } + } + ] + }, + { + description: + 'Use short description if it exists and error description does not', component: { title: 'What is your example text?', shortDescription: 'Your example text', diff --git a/src/server/plugins/engine/components/UkAddressField.ts b/src/server/plugins/engine/components/UkAddressField.ts index f21ea4a7e..5b27d9b37 100644 --- a/src/server/plugins/engine/components/UkAddressField.ts +++ b/src/server/plugins/engine/components/UkAddressField.ts @@ -1,8 +1,4 @@ -import { - ComponentType, - type FormComponentsDef, - type UkAddressFieldComponent -} from '@defra/forms-model' +import { ComponentType, type UkAddressFieldComponent } from '@defra/forms-model' import { type ObjectSchema } from 'joi' import lowerFirst from 'lodash/lowerFirst.js' @@ -34,15 +30,13 @@ export class UkAddressField extends FormComponent { declare stateSchema: ObjectSchema declare collection: ComponentCollection - shortDescription: FormComponentsDef['shortDescription'] - constructor( def: UkAddressFieldComponent, props: ConstructorParameters[1] ) { super(def, props) - const { name, options, shortDescription } = def + const { name, options } = def const isRequired = options.required !== false const hideOptional = !!options.optionalText @@ -126,7 +120,6 @@ export class UkAddressField extends FormComponent { this.options = options this.formSchema = this.collection.formSchema this.stateSchema = this.collection.stateSchema - this.shortDescription = shortDescription } getFormValueFromState(state: FormSubmissionState) { @@ -174,14 +167,14 @@ export class UkAddressField extends FormComponent { // When using postcode lookup, the address fields are hidden // so we replace any individual validation messages with a single one if (this.shouldUsePostcodeLookup() && uniqueErrors?.length) { - const { name, shortDescription } = this + const { name, label } = this return [ { name, path: [name], href: `#${name}`, - text: `Enter ${lowerFirst(shortDescription)}` + text: `Enter ${lowerFirst(label)}` } ] } diff --git a/test/form/definitions/postcode-lookup.js b/test/form/definitions/postcode-lookup.js index 2426d1511..99278716a 100644 --- a/test/form/definitions/postcode-lookup.js +++ b/test/form/definitions/postcode-lookup.js @@ -20,6 +20,7 @@ export default /** @satisfies {FormDefinition} */ ({ title: 'What is your address?', name: 'ybMHIv', shortDescription: 'Address', + errorDescription: 'Your address', hint: '', options: { required: true, diff --git a/test/form/postcode-lookup.test.js b/test/form/postcode-lookup.test.js index 29e9ae1e2..2eca19dad 100644 --- a/test/form/postcode-lookup.test.js +++ b/test/form/postcode-lookup.test.js @@ -101,7 +101,7 @@ describe('Postcode lookup form pages', () => { const $errorItems = within($errorSummary).getAllByRole('listitem') expect($errorItems).toHaveLength(1) - expect($errorItems[0]).toHaveTextContent('Enter address') + expect($errorItems[0]).toHaveTextContent('Enter your address') }) it('should dispatch to details page on POST', async () => {