Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,36 @@ describe('EastingNorthingField', () => {
const staticResult = EastingNorthingField.getAllPossibleErrors()
const instanceResult = field.getAllPossibleErrors()

expect(instanceResult).toEqual(staticResult)
// Compare structure and content
expect(instanceResult.baseErrors).toHaveLength(
staticResult.baseErrors.length
)
expect(instanceResult.advancedSettingsErrors).toHaveLength(
staticResult.advancedSettingsErrors.length
)

// Compare error types
expect(instanceResult.baseErrors.map((e) => e.type)).toEqual(
staticResult.baseErrors.map((e) => e.type)
)
expect(
instanceResult.advancedSettingsErrors.map((e) => e.type)
).toEqual(staticResult.advancedSettingsErrors.map((e) => e.type))

// Compare rendered templates
expect(
instanceResult.baseErrors.map((e) =>
typeof e.template === 'object' && 'rendered' in e.template
? e.template.rendered
: e.template
)
).toEqual(
staticResult.baseErrors.map((e) =>
typeof e.template === 'object' && 'rendered' in e.template
? e.template.rendered
: e.template
)
)
})
})
})
Expand Down
25 changes: 19 additions & 6 deletions src/server/plugins/engine/components/EastingNorthingField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
getLocationFieldViewModel
} from '~/src/server/plugins/engine/components/LocationFieldHelpers.js'
import { NumberField } from '~/src/server/plugins/engine/components/NumberField.js'
import { createLowerFirstExpression } from '~/src/server/plugins/engine/components/helpers/index.js'
import { type EastingNorthingState } from '~/src/server/plugins/engine/components/types.js'
import { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'
import {
Expand Down Expand Up @@ -198,29 +199,41 @@ export class EastingNorthingField extends FormComponent {
{ type: 'required', template: messageTemplate.required },
{
type: 'eastingFormat',
template: 'Easting for {{#title}} must be between 1 and 6 digits'
template: createLowerFirstExpression(
'Easting for {{lowerFirst(#title)}} must be between 1 and 6 digits'
)
},
{
type: 'northingFormat',
template: 'Northing for {{#title}} must be between 1 and 7 digits'
template: createLowerFirstExpression(
'Northing for {{lowerFirst(#title)}} must be between 1 and 7 digits'
)
}
],
advancedSettingsErrors: [
{
type: 'eastingMin',
template: `Easting for {{#title}} must be between ${DEFAULT_EASTING_MIN} and ${DEFAULT_EASTING_MAX}`
template: createLowerFirstExpression(
`Easting for {{lowerFirst(#title)}} must be between ${DEFAULT_EASTING_MIN} and ${DEFAULT_EASTING_MAX}`
)
},
{
type: 'eastingMax',
template: `Easting for {{#title}} must be between ${DEFAULT_EASTING_MIN} and ${DEFAULT_EASTING_MAX}`
template: createLowerFirstExpression(
`Easting for {{lowerFirst(#title)}} must be between ${DEFAULT_EASTING_MIN} and ${DEFAULT_EASTING_MAX}`
)
},
{
type: 'northingMin',
template: `Northing for {{#title}} must be between ${DEFAULT_NORTHING_MIN} and ${DEFAULT_NORTHING_MAX}`
template: createLowerFirstExpression(
`Northing for {{lowerFirst(#title)}} must be between ${DEFAULT_NORTHING_MIN} and ${DEFAULT_NORTHING_MAX}`
)
},
{
type: 'northingMax',
template: `Northing for {{#title}} must be between ${DEFAULT_NORTHING_MIN} and ${DEFAULT_NORTHING_MAX}`
template: createLowerFirstExpression(
`Northing for {{lowerFirst(#title)}} must be between ${DEFAULT_NORTHING_MIN} and ${DEFAULT_NORTHING_MAX}`
)
}
]
}
Expand Down
31 changes: 30 additions & 1 deletion src/server/plugins/engine/components/LatLongField.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,36 @@ describe('LatLongField', () => {
const staticResult = LatLongField.getAllPossibleErrors()
const instanceResult = field.getAllPossibleErrors()

expect(instanceResult).toEqual(staticResult)
// Compare structure and content
expect(instanceResult.baseErrors).toHaveLength(
staticResult.baseErrors.length
)
expect(instanceResult.advancedSettingsErrors).toHaveLength(
staticResult.advancedSettingsErrors.length
)

// Compare error types
expect(instanceResult.baseErrors.map((e) => e.type)).toEqual(
staticResult.baseErrors.map((e) => e.type)
)
expect(
instanceResult.advancedSettingsErrors.map((e) => e.type)
).toEqual(staticResult.advancedSettingsErrors.map((e) => e.type))

// Compare rendered templates
expect(
instanceResult.baseErrors.map((e) =>
typeof e.template === 'object' && 'rendered' in e.template
? e.template.rendered
: e.template
)
).toEqual(
staticResult.baseErrors.map((e) =>
typeof e.template === 'object' && 'rendered' in e.template
? e.template.rendered
: e.template
)
)
})
})
})
Expand Down
25 changes: 19 additions & 6 deletions src/server/plugins/engine/components/LatLongField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
getLocationFieldViewModel
} from '~/src/server/plugins/engine/components/LocationFieldHelpers.js'
import { NumberField } from '~/src/server/plugins/engine/components/NumberField.js'
import { createLowerFirstExpression } from '~/src/server/plugins/engine/components/helpers/index.js'
import { type LatLongState } from '~/src/server/plugins/engine/components/types.js'
import { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'
import {
Expand Down Expand Up @@ -194,29 +195,41 @@ export class LatLongField extends FormComponent {
{ type: 'required', template: messageTemplate.required },
{
type: 'latitudeFormat',
template: 'Enter a valid latitude for {{#title}} like 51.519450'
template: createLowerFirstExpression(
'Enter a valid latitude for {{lowerFirst(#title)}} like 51.519450'
)
},
{
type: 'longitudeFormat',
template: 'Enter a valid longitude for {{#title}} like -0.127758'
template: createLowerFirstExpression(
'Enter a valid longitude for {{lowerFirst(#title)}} like -0.127758'
)
}
],
advancedSettingsErrors: [
{
type: 'latitudeMin',
template: 'Latitude for {{#title}} must be between 49 and 60'
template: createLowerFirstExpression(
'Latitude for {{lowerFirst(#title)}} must be between 49 and 60'
)
},
{
type: 'latitudeMax',
template: 'Latitude for {{#title}} must be between 49 and 60'
template: createLowerFirstExpression(
'Latitude for {{lowerFirst(#title)}} must be between 49 and 60'
)
},
{
type: 'longitudeMin',
template: 'Longitude for {{#title}} must be between -9 and 2'
template: createLowerFirstExpression(
'Longitude for {{lowerFirst(#title)}} must be between -9 and 2'
)
},
{
type: 'longitudeMax',
template: 'Longitude for {{#title}} must be between -9 and 2'
template: createLowerFirstExpression(
'Longitude for {{lowerFirst(#title)}} must be between -9 and 2'
)
}
]
}
Expand Down
17 changes: 11 additions & 6 deletions src/server/plugins/engine/components/LocationFieldBase.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { type FormComponentsDef } from '@defra/forms-model'
import joi, { type LanguageMessages, type StringSchema } from 'joi'
import joi, {
type JoiExpression,
type LanguageMessages,
type StringSchema
} from 'joi'

import {
FormComponent,
Expand All @@ -15,6 +19,7 @@ import {
type FormSubmissionError,
type FormSubmissionState
} from '~/src/server/plugins/engine/types.js'
import { convertToLanguageMessages } from '~/src/server/utils/type-utils.js'

interface LocationFieldOptions {
instructionText?: string
Expand All @@ -26,8 +31,8 @@ interface LocationFieldOptions {

interface ValidationConfig {
pattern: RegExp
patternErrorMessage: string
requiredMessage?: string
patternErrorMessage: JoiExpression
requiredMessage?: JoiExpression
}

/**
Expand All @@ -42,7 +47,7 @@ export abstract class LocationFieldBase extends FormComponent {
protected abstract getValidationConfig(): ValidationConfig
protected abstract getErrorTemplates(): {
type: string
template: string
template: JoiExpression
}[]

constructor(
Expand All @@ -61,11 +66,11 @@ export abstract class LocationFieldBase extends FormComponent {
const requiredMessage =
config.requiredMessage ?? (messageTemplate.required as string)

const messages: LanguageMessages = {
const messages = convertToLanguageMessages({
'any.required': requiredMessage,
'string.empty': requiredMessage,
'string.pattern.base': config.patternErrorMessage
}
})

let formSchema = joi
.string()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ describe('NationalGridFieldNumberField', () => {

expect(result.errors).toEqual([
expect.objectContaining({
text: 'Enter Example National Grid field number'
text: 'Enter example National Grid field number'
})
])
})
Expand Down Expand Up @@ -293,7 +293,7 @@ describe('NationalGridFieldNumberField', () => {
value: getFormData('NG1234567'),
errors: expect.arrayContaining([
expect.objectContaining({
text: 'Enter a valid National Grid field number for Grid field like NG 1234 5678'
text: 'Enter a valid National Grid field number for grid field like NG 1234 5678'
})
])
}
Expand All @@ -304,7 +304,7 @@ describe('NationalGridFieldNumberField', () => {
value: getFormData('N123456789'),
errors: expect.arrayContaining([
expect.objectContaining({
text: 'Enter a valid National Grid field number for Grid field like NG 1234 5678'
text: 'Enter a valid National Grid field number for grid field like NG 1234 5678'
})
])
}
Expand All @@ -315,7 +315,7 @@ describe('NationalGridFieldNumberField', () => {
value: getFormData('NGABCDEFGH'),
errors: expect.arrayContaining([
expect.objectContaining({
text: 'Enter a valid National Grid field number for Grid field like NG 1234 5678'
text: 'Enter a valid National Grid field number for grid field like NG 1234 5678'
})
])
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type NationalGridFieldNumberFieldComponent } from '@defra/forms-model'

import { LocationFieldBase } from '~/src/server/plugins/engine/components/LocationFieldBase.js'
import { createLowerFirstExpression } from '~/src/server/plugins/engine/components/helpers/index.js'

export class NationalGridFieldNumberField extends LocationFieldBase {
declare options: NationalGridFieldNumberFieldComponent['options']
Expand All @@ -12,19 +13,25 @@ export class NationalGridFieldNumberField extends LocationFieldBase {
const pattern =
/^((([sS]|[nN])[a-hA-Hj-zJ-Z])|(([tT]|[oO])[abfglmqrvwABFGLMQRVW])|([hH][l-zL-Z])|([jJ][lmqrvwLMQRVW]))\s?([0-9]{4})\s?([0-9]{4})$/

const patternTemplate =
'Enter a valid National Grid field number for {{lowerFirst(#title)}} like NG 1234 5678'

return {
pattern,
patternErrorMessage: `Enter a valid National Grid field number for {{#title}} like NG 1234 5678`,
requiredMessage: 'Enter {{#title}}'
patternErrorMessage: createLowerFirstExpression(patternTemplate),
requiredMessage: createLowerFirstExpression(
'Enter {{lowerFirst(#title)}}'
)
}
}

protected getErrorTemplates() {
return [
{
type: 'pattern',
template:
'Enter a valid National Grid field number for {{#title}} like NG 1234 5678'
template: createLowerFirstExpression(
'Enter a valid National Grid field number for {{lowerFirst(#title)}} like NG 1234 5678'
)
}
]
}
Expand Down
8 changes: 4 additions & 4 deletions src/server/plugins/engine/components/OsGridRefField.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ describe('OsGridRefField', () => {

expect(result.errors).toEqual([
expect.objectContaining({
text: 'Enter Example OS grid reference'
text: 'Enter example OS grid reference'
})
])
})
Expand Down Expand Up @@ -308,7 +308,7 @@ describe('OsGridRefField', () => {
value: getFormData('TQ12345'),
errors: expect.arrayContaining([
expect.objectContaining({
text: 'Enter a valid OS grid reference for Grid reference like TQ123456'
text: 'Enter a valid OS grid reference for grid reference like TQ123456'
})
])
}
Expand All @@ -319,7 +319,7 @@ describe('OsGridRefField', () => {
value: getFormData('AA1234567'),
errors: expect.arrayContaining([
expect.objectContaining({
text: 'Enter a valid OS grid reference for Grid reference like TQ123456'
text: 'Enter a valid OS grid reference for grid reference like TQ123456'
})
])
}
Expand All @@ -330,7 +330,7 @@ describe('OsGridRefField', () => {
value: getFormData('TQABCDEF'),
errors: expect.arrayContaining([
expect.objectContaining({
text: 'Enter a valid OS grid reference for Grid reference like TQ123456'
text: 'Enter a valid OS grid reference for grid reference like TQ123456'
})
])
}
Expand Down
14 changes: 11 additions & 3 deletions src/server/plugins/engine/components/OsGridRefField.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type OsGridRefFieldComponent } from '@defra/forms-model'

import { LocationFieldBase } from '~/src/server/plugins/engine/components/LocationFieldBase.js'
import { createLowerFirstExpression } from '~/src/server/plugins/engine/components/helpers/index.js'

export class OsGridRefField extends LocationFieldBase {
declare options: OsGridRefFieldComponent['options']
Expand All @@ -15,18 +16,25 @@ export class OsGridRefField extends LocationFieldBase {
const pattern =
/^((([sS]|[nN])[a-hA-Hj-zJ-Z])|(([tT]|[oO])[abfglmqrvwABFGLMQRVW])|([hH][l-zL-Z])|([jJ][lmqrvwLMQRVW]))\s?(([0-9]{3})\s?([0-9]{3})|([0-9]{4})\s?([0-9]{4})|([0-9]{5})\s?([0-9]{5}))$/

const patternTemplate =
'Enter a valid OS grid reference for {{lowerFirst(#title)}} like TQ123456'

return {
pattern,
patternErrorMessage: `Enter a valid OS grid reference for {{#title}} like TQ123456`,
requiredMessage: 'Enter {{#title}}'
patternErrorMessage: createLowerFirstExpression(patternTemplate),
requiredMessage: createLowerFirstExpression(
'Enter {{lowerFirst(#title)}}'
)
}
}

protected getErrorTemplates() {
return [
{
type: 'pattern',
template: 'Enter a valid OS grid reference for {{#title}} like TQ123456'
template: createLowerFirstExpression(
'Enter a valid OS grid reference for {{lowerFirst(#title)}} like TQ123456'
)
}
]
}
Expand Down
Loading
Loading