diff --git a/src/server/plugins/engine/components/helpers/helpers.test.ts b/src/server/plugins/engine/components/helpers/helpers.test.ts index e597fa0d1..9ed971030 100644 --- a/src/server/plugins/engine/components/helpers/helpers.test.ts +++ b/src/server/plugins/engine/components/helpers/helpers.test.ts @@ -9,7 +9,8 @@ import { OsGridRefField } from '~/src/server/plugins/engine/components/OsGridRef import { createComponent } from '~/src/server/plugins/engine/components/helpers/components.js' import { createLowerFirstExpression, - lowerFirstExpressionOptions + lowerFirstExpressionOptions, + lowerFirstPreserveProperNouns } from '~/src/server/plugins/engine/components/helpers/index.js' import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js' import definition from '~/test/form/definitions/basic.js' @@ -145,6 +146,42 @@ describe('ComponentBase tests', () => { }) }) +describe('lowerFirstPreserveProperNouns', () => { + test('should preserve "National Grid" capitalisation', () => { + expect(lowerFirstPreserveProperNouns('National Grid field number')).toBe( + 'National Grid field number' + ) + }) + + test('should preserve "Ordnance Survey" capitalisation', () => { + expect( + lowerFirstPreserveProperNouns('Ordnance Survey (OS) grid reference') + ).toBe('Ordnance Survey (OS) grid reference') + }) + + test('should preserve "OS" capitalisation', () => { + expect(lowerFirstPreserveProperNouns('OS grid reference')).toBe( + 'OS grid reference' + ) + }) + + test('should lowercase first character for regular text', () => { + expect(lowerFirstPreserveProperNouns('Enter your name')).toBe( + 'enter your name' + ) + }) + + test('should handle text without special terms', () => { + expect(lowerFirstPreserveProperNouns('Latitude and longitude')).toBe( + 'latitude and longitude' + ) + }) + + test('should handle empty string', () => { + expect(lowerFirstPreserveProperNouns('')).toBe('') + }) +}) + describe('lowerFirst expression helpers', () => { test('lowerFirstExpressionOptions should have lowerFirst function', () => { expect(lowerFirstExpressionOptions).toHaveProperty('functions') diff --git a/src/server/plugins/engine/components/helpers/index.ts b/src/server/plugins/engine/components/helpers/index.ts index d7dd1a748..88e4c78de 100644 --- a/src/server/plugins/engine/components/helpers/index.ts +++ b/src/server/plugins/engine/components/helpers/index.ts @@ -39,12 +39,24 @@ export const addClassOptionIfNone = ( options.classes ??= className } +/** + * Applies lowerFirst but preserves capitalisation of proper nouns + * like "National Grid", "Ordnance Survey" and "OS". + */ +export function lowerFirstPreserveProperNouns(text: string): string { + const result = lowerFirst(text) + return result + .replace(/\bnational [Gg]rid\b/g, 'National Grid') + .replace(/\bordnance [Ss]urvey\b/g, 'Ordnance Survey') + .replace(/\b[oO][sS]\b/g, 'OS') +} + /** * Configuration for Joi expressions that use lowerFirst function */ export const lowerFirstExpressionOptions = { functions: { - lowerFirst + lowerFirst: lowerFirstPreserveProperNouns } } as ReferenceOptions diff --git a/src/server/plugins/engine/pageControllers/validationOptions.ts b/src/server/plugins/engine/pageControllers/validationOptions.ts index 2c20a6b3e..da35f0489 100644 --- a/src/server/plugins/engine/pageControllers/validationOptions.ts +++ b/src/server/plugins/engine/pageControllers/validationOptions.ts @@ -8,11 +8,12 @@ import joi, { type ReferenceOptions, type ValidationOptions } from 'joi' -import lowerFirst from 'lodash/lowerFirst.js' + +import { lowerFirstPreserveProperNouns } from '~/src/server/plugins/engine/components/helpers/index.js' const opts = { functions: { - lowerFirst + lowerFirst: lowerFirstPreserveProperNouns } } as ReferenceOptions