-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
4 changed files
with
184 additions
and
2 deletions.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
runner/src/server/plugins/engine/components/EmailAddressField.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
//@ts-ignore | ||
import {InputFieldsComponentsDef} from "@xgovformbuilder/model"; | ||
import {AdapterFormModel} from "../models"; | ||
import { | ||
addClassOptionIfNone, | ||
} from "../../../../../../digital-form-builder/runner/src/server/plugins/engine/components/helpers"; | ||
import { | ||
EmailAddressField as XGovEmailAddressField | ||
} from "../../../../../../digital-form-builder/runner/src/server/plugins/engine/components"; | ||
import Joi from "joi"; | ||
|
||
export class EmailAddressField extends XGovEmailAddressField { | ||
private defaultMessage: string = "Enter an email address in the correct format, like [email protected]"; | ||
formSchema: Joi.StringSchema; | ||
options: InputFieldsComponentsDef["options"]; | ||
schema: InputFieldsComponentsDef["schema"]; | ||
|
||
constructor(def: InputFieldsComponentsDef, model: AdapterFormModel) { | ||
//@ts-ignore | ||
super(def, model); | ||
|
||
this.options = def.options; | ||
this.schema = def.schema; | ||
this.formSchema = Joi.string(); | ||
|
||
const isRequired = def.options.required ?? true; | ||
|
||
if (isRequired) { | ||
this.formSchema = this.formSchema.required(); | ||
} else { | ||
this.formSchema = this.formSchema.allow("").allow(null).optional(); | ||
} | ||
|
||
this.formSchema = this.formSchema | ||
.label(def.title.toLowerCase()) // Label for error messages | ||
.email({tlds: {allow: false}}) // Strict email format validation (without allowing specific TLDs) | ||
.messages({ | ||
//@ts-ignore | ||
"string.email": def.options?.customValidationMessage ?? this.defaultMessage, // Custom error message | ||
}); | ||
addClassOptionIfNone(this.options, "govuk-input--width-20"); | ||
|
||
} | ||
|
||
getFormSchemaKeys() { | ||
return { | ||
[this.name]: this.formSchema, | ||
}; | ||
} | ||
|
||
getStateSchemaKeys() { | ||
return { | ||
[this.name]: this.formSchema, | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
126 changes: 126 additions & 0 deletions
126
runner/test/cases/server/plugins/engine/components/EmailAddressField.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import * as Code from "@hapi/code"; | ||
import * as Lab from "@hapi/lab"; | ||
//@ts-ignore | ||
import {InputFieldsComponentsDef} from "@xgovformbuilder/model"; | ||
// @ts-ignore | ||
import {EmailAddressField} from "src/server/plugins/engine/components"; | ||
// @ts-ignore | ||
import {AdapterFormModel} from "src/server/plugins/engine/models"; | ||
// @ts-ignore | ||
import {TranslationLoaderService} from "src/server/services/TranslationLoaderService"; | ||
|
||
const lab = Lab.script(); | ||
exports.lab = lab; | ||
const {expect} = Code; | ||
const {beforeEach, suite, test} = lab; | ||
|
||
suite("EmailAddress field", () => { | ||
let model: AdapterFormModel; | ||
|
||
beforeEach(() => { | ||
const translationService: TranslationLoaderService = new TranslationLoaderService(); | ||
const translations = translationService.getTranslations(); | ||
model = { | ||
options: { | ||
translationEn: translations.en, | ||
translationCy: translations.cy | ||
} | ||
} as AdapterFormModel; | ||
}); | ||
|
||
test("should be required by default", () => { | ||
const def: InputFieldsComponentsDef = { | ||
name: "myComponent", | ||
title: "My component", | ||
type: "EmailAddressField", | ||
hint: "a hint", | ||
options: {}, | ||
schema: {}, | ||
}; | ||
|
||
const {formSchema} = new EmailAddressField(def, model); | ||
|
||
expect(formSchema.describe().flags!["presence"]).to.equal("required"); | ||
}); | ||
|
||
test("should validate email", () => { | ||
const def: InputFieldsComponentsDef = { | ||
name: "myComponent", | ||
title: "My component", | ||
type: "EmailAddressField", | ||
hint: "a hint", | ||
options: {}, | ||
schema: {}, | ||
}; | ||
|
||
const {formSchema} = new EmailAddressField(def, model); | ||
|
||
expect(formSchema.validate("[email protected]").error).to.be.undefined(); | ||
expect(formSchema.validate("test").error!.message).to.contain( | ||
`Enter an email address in the correct format, like [email protected]` | ||
); | ||
expect(formSchema.validate("test@email").error!.message).to.contain( | ||
`Enter an email address in the correct format, like [email protected]` | ||
); | ||
}); | ||
|
||
test("should display custom error message", () => { | ||
const def: InputFieldsComponentsDef = { | ||
name: "myComponent", | ||
title: "My component", | ||
type: "EmailAddressField", | ||
hint: "a hint", | ||
options: { | ||
customValidationMessage: "Enter valid email address", | ||
}, | ||
schema: {}, | ||
}; | ||
|
||
const {formSchema} = new EmailAddressField(def, model); | ||
|
||
expect(formSchema.validate("www.gov.uk").error?.message).to.contain( | ||
"Enter valid email address" | ||
); | ||
}); | ||
|
||
test("should be required by default", () => { | ||
const def: InputFieldsComponentsDef = { | ||
name: "myComponent", | ||
title: "My component", | ||
type: "EmailAddressField", | ||
hint: "a hint", | ||
options: {}, | ||
schema: {}, | ||
}; | ||
|
||
const {formSchema} = new EmailAddressField(def, model); | ||
|
||
expect(formSchema.validate("").error?.message).to.contain( | ||
`"my component" is not allowed to be empty` | ||
); | ||
|
||
expect(formSchema.validate(null).error?.message).to.contain( | ||
`"my component" must be a string` | ||
); | ||
}); | ||
|
||
test("should allow empty strings and null values when not required", () => { | ||
const def: InputFieldsComponentsDef = { | ||
name: "myComponent", | ||
title: "My component", | ||
type: "EmailAddressField", | ||
hint: "a hint", | ||
options: { | ||
required: false, | ||
}, | ||
schema: {}, | ||
}; | ||
|
||
const {formSchema} = new EmailAddressField(def, model); | ||
|
||
expect(formSchema.validate("").error).to.be.undefined(); | ||
|
||
expect(formSchema.validate(null).error).to.be.undefined(); | ||
}); | ||
|
||
}); |