From 7c8c23706bc3a734e6003423587d5fe9e83081b3 Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Mon, 9 Sep 2024 16:00:10 -0400 Subject: [PATCH 01/17] 10466: start making email validation messages uniform --- shared/src/business/entities/contacts/Contact.ts | 4 +++- .../entities/contacts/DeceasedSpouseContact.ts | 3 ++- shared/src/business/entities/contacts/Petitioner.ts | 11 ++++++++--- .../src/business/entities/contacts/SpouseContact.ts | 3 ++- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/shared/src/business/entities/contacts/Contact.ts b/shared/src/business/entities/contacts/Contact.ts index 34e7c667cc4..4f1ea81c798 100644 --- a/shared/src/business/entities/contacts/Contact.ts +++ b/shared/src/business/entities/contacts/Contact.ts @@ -108,7 +108,9 @@ export class Contact extends JoiValidationEntity { paperPetitionEmail: JoiValidationConstants.EMAIL.optional() .allow(null) .description('Email provided by the petitioner on their petition form') - .messages({ '*': 'Enter email address in format: yourname@example.com' }), + .messages({ + 'string.email': 'Enter email address in format: yourname@example.com', + }), phone: JoiValidationConstants.STRING.max(100) .when('contactType', { is: CONTACT_TYPES.secondary, diff --git a/shared/src/business/entities/contacts/DeceasedSpouseContact.ts b/shared/src/business/entities/contacts/DeceasedSpouseContact.ts index a8a83145661..ae1065b7408 100644 --- a/shared/src/business/entities/contacts/DeceasedSpouseContact.ts +++ b/shared/src/business/entities/contacts/DeceasedSpouseContact.ts @@ -27,7 +27,8 @@ export class DeceasedSpouseContact extends ContactUpdated { then: joi.string().required(), }, ).messages({ - '*': 'Enter an email address to register for electronic service', + 'string.email': 'Enter email address in format: yourname@example.com', + 'string.empty': 'Enter a valid email address', }), phone: JoiValidationConstants.STRING.max(100).optional().allow(null), }; diff --git a/shared/src/business/entities/contacts/Petitioner.ts b/shared/src/business/entities/contacts/Petitioner.ts index 41653e4e4f8..b33b32eb7bf 100644 --- a/shared/src/business/entities/contacts/Petitioner.ts +++ b/shared/src/business/entities/contacts/Petitioner.ts @@ -78,6 +78,9 @@ export class Petitioner extends JoiValidationEntity { is: true, otherwise: joi.optional(), then: joi.required(), + }).messages({ + 'string.email': 'Enter email address in format: yourname@example.com', + 'string.empty': 'Enter a valid email address', }), hasConsentedToEService: joi .boolean() @@ -97,9 +100,11 @@ export class Petitioner extends JoiValidationEntity { '*': 'Enter name', 'string.max': 'Limit is 100 characters. Enter 100 or fewer characters.', }), - paperPetitionEmail: JoiValidationConstants.EMAIL.optional().description( - 'Email provided by the petitioner on a paper petition', - ), + paperPetitionEmail: JoiValidationConstants.EMAIL.optional() + .description('Email provided by the petitioner on a paper petition') + .messages({ + 'string.email': 'Enter email address in format: yourname@example.com', + }), sealedAndUnavailable: joi.boolean().optional(), serviceIndicator: JoiValidationConstants.STRING.valid( ...Object.values(SERVICE_INDICATOR_TYPES), diff --git a/shared/src/business/entities/contacts/SpouseContact.ts b/shared/src/business/entities/contacts/SpouseContact.ts index cd2239aeb2f..60f42df844b 100644 --- a/shared/src/business/entities/contacts/SpouseContact.ts +++ b/shared/src/business/entities/contacts/SpouseContact.ts @@ -24,7 +24,8 @@ export class SpouseContact extends ContactUpdated { then: joi.string().required(), }, ).messages({ - '*': 'Enter an email address to register for electronic service', + 'string.email': 'Enter email address in format: yourname@example.com', + 'string.empty': 'Enter a valid email address', }), phone: JoiValidationConstants.STRING.max(100).optional().allow(null), }; From 9b9f809a717259d8fcbe41838ab94c383751bc8c Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Tue, 10 Sep 2024 10:00:28 -0400 Subject: [PATCH 02/17] 10466: continue unifying email validation messages --- .../entities/NewPetitionerUser.test.ts | 30 +++++++++++++++++-- .../business/entities/NewPetitionerUser.ts | 5 ++-- shared/src/business/entities/Practitioner.ts | 7 +++-- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/shared/src/business/entities/NewPetitionerUser.test.ts b/shared/src/business/entities/NewPetitionerUser.test.ts index 4903ab1684e..9b72f835de5 100644 --- a/shared/src/business/entities/NewPetitionerUser.test.ts +++ b/shared/src/business/entities/NewPetitionerUser.test.ts @@ -17,7 +17,20 @@ describe('NewPetitionerUser', () => { }); describe('Email', () => { - it('should return error message for email', () => { + it('should return an error message for email when no email is provided', () => { + const { email, ...rest } = validEntity; + void email; + const formEntity = new NewPetitionerUser({ + ...rest, + }); + + expect(formEntity.isValid()).toBeFalsy(); + expect(formEntity.getValidationErrors()).toEqual({ + email: 'Enter a valid email address', + }); + }); + + it('should return an error message for email when an invalid email format is provided', () => { const formEntity = new NewPetitionerUser({ ...validEntity, email: 'hello', @@ -25,7 +38,20 @@ describe('NewPetitionerUser', () => { expect(formEntity.isValid()).toBeFalsy(); expect(formEntity.getValidationErrors()).toEqual({ - email: 'Enter a valid email address', + email: 'Enter email address in format: yourname@example.com', + }); + }); + + it('should return an error message for email when an email address exceeding the maximum number of characters is provided', () => { + const formEntity = new NewPetitionerUser({ + ...validEntity, + email: + 'horatio_says_tis_but_our_fantasy_and_will_not_let_belief_take_hold_of_him_touching_this_dreaded_sight_twice_seen_of_us@denmarkemailservice.com', + }); + + expect(formEntity.isValid()).toBeFalsy(); + expect(formEntity.getValidationErrors()).toEqual({ + email: 'Email address must contain fewer than 100 characters', }); }); }); diff --git a/shared/src/business/entities/NewPetitionerUser.ts b/shared/src/business/entities/NewPetitionerUser.ts index f02e7c85cb7..0072e0506b8 100644 --- a/shared/src/business/entities/NewPetitionerUser.ts +++ b/shared/src/business/entities/NewPetitionerUser.ts @@ -25,8 +25,9 @@ export class NewPetitionerUser extends JoiValidationEntity { .messages({ '*': 'Passwords must match' }), email: JoiValidationConstants.EMAIL.required() .messages({ - '*': 'Enter a valid email address', - 'string.max': 'Email address must contain fewer than 100 characters', //todo test + 'any.required': 'Enter a valid email address', + 'string.email': 'Enter email address in format: yourname@example.com', + 'string.max': 'Email address must contain fewer than 100 characters', }) .description('Email of user'), entityName: diff --git a/shared/src/business/entities/Practitioner.ts b/shared/src/business/entities/Practitioner.ts index aa88ae670e4..8758c3bd80e 100644 --- a/shared/src/business/entities/Practitioner.ts +++ b/shared/src/business/entities/Practitioner.ts @@ -113,7 +113,7 @@ export class Practitioner extends User { }).messages({ 'any.only': 'Email addresses do not match', 'any.required': 'Enter a valid email address', - 'string.email': 'Enter a valid email address', + 'string.email': 'Enter email address in format: yourname@example.com', }), entityName: JoiValidationConstants.STRING.valid('Practitioner').required(), firmName: JoiValidationConstants.STRING.max(100) @@ -183,7 +183,10 @@ export class Practitioner extends User { otherwise: JoiValidationConstants.EMAIL.optional().allow(null), then: JoiValidationConstants.EMAIL.required(), }) - .messages({ '*': 'Enter a valid email address' }), + .messages({ + 'any.required': 'Enter a valid email address', + 'string.email': 'Enter email address in format: yourname@example.com', + }), }; getValidationRules() { From 91ff1cac88c50e411969066c7dd1a51ccf906cd8 Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Tue, 10 Sep 2024 10:06:24 -0400 Subject: [PATCH 03/17] 10466: update test case --- shared/src/business/entities/Practitioner.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shared/src/business/entities/Practitioner.test.ts b/shared/src/business/entities/Practitioner.test.ts index 63e12e40b60..850ca285fac 100644 --- a/shared/src/business/entities/Practitioner.test.ts +++ b/shared/src/business/entities/Practitioner.test.ts @@ -254,7 +254,7 @@ describe('Practitioner', () => { expect(validPractitioner.isValid()).toBeFalsy(); expect(validPractitioner.getFormattedValidationErrors()).toEqual({ confirmEmail: 'Email addresses do not match', - updatedEmail: 'Enter a valid email address', + updatedEmail: 'Enter email address in format: yourname@example.com', }); }); @@ -274,7 +274,7 @@ describe('Practitioner', () => { expect(validPractitioner.isValid()).toBeFalsy(); expect(validPractitioner.getFormattedValidationErrors()).toEqual({ - confirmEmail: 'Enter a valid email address', + confirmEmail: 'Enter email address in format: yourname@example.com', }); }); @@ -305,7 +305,7 @@ describe('Practitioner', () => { expect(validPractitioner.isValid()).toBeFalsy(); expect(validPractitioner.getFormattedValidationErrors()).toEqual({ confirmEmail: 'Enter a valid email address', - updatedEmail: 'Enter a valid email address', + updatedEmail: 'Enter email address in format: yourname@example.com', }); }); }); From 0c2bb001e4ab7461dcb0151c7a1bf56b1ee4107a Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Tue, 10 Sep 2024 10:08:42 -0400 Subject: [PATCH 04/17] 10466: adjust NewPetitionerUser test case so that mock data is prepared the same way as in Practitioner.test.ts --- shared/src/business/entities/NewPetitionerUser.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/shared/src/business/entities/NewPetitionerUser.test.ts b/shared/src/business/entities/NewPetitionerUser.test.ts index 9b72f835de5..57e800209db 100644 --- a/shared/src/business/entities/NewPetitionerUser.test.ts +++ b/shared/src/business/entities/NewPetitionerUser.test.ts @@ -18,10 +18,9 @@ describe('NewPetitionerUser', () => { describe('Email', () => { it('should return an error message for email when no email is provided', () => { - const { email, ...rest } = validEntity; - void email; const formEntity = new NewPetitionerUser({ - ...rest, + ...validEntity, + email: undefined, }); expect(formEntity.isValid()).toBeFalsy(); From 81dbe05b09f6f1c57d400284da378fd5f52a0107 Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Tue, 10 Sep 2024 10:12:28 -0400 Subject: [PATCH 05/17] 10466: update Contact entity test case --- shared/src/business/entities/contacts/Contact.test.ts | 2 +- shared/src/business/entities/contacts/Contact.ts | 4 ++++ shared/src/business/entities/contacts/Petitioner.ts | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/shared/src/business/entities/contacts/Contact.test.ts b/shared/src/business/entities/contacts/Contact.test.ts index b50bfd1e4ba..13f7fc45fc2 100644 --- a/shared/src/business/entities/contacts/Contact.test.ts +++ b/shared/src/business/entities/contacts/Contact.test.ts @@ -14,7 +14,7 @@ describe('Contact', () => { ); expect(contact.getFormattedValidationErrors()!.email).toEqual( - '"email" is required', + 'Enter a valid email address', ); }); diff --git a/shared/src/business/entities/contacts/Contact.ts b/shared/src/business/entities/contacts/Contact.ts index 4f1ea81c798..fdf312295b4 100644 --- a/shared/src/business/entities/contacts/Contact.ts +++ b/shared/src/business/entities/contacts/Contact.ts @@ -87,6 +87,10 @@ export class Contact extends JoiValidationEntity { is: true, otherwise: joi.optional(), then: joi.required(), + }).messages({ + 'any.required': 'Enter a valid email address', + 'string.email': 'Enter email address in format: yourname@example.com', + 'string.empty': 'Enter a valid email address', }), hasConsentedToEService: joi .boolean() diff --git a/shared/src/business/entities/contacts/Petitioner.ts b/shared/src/business/entities/contacts/Petitioner.ts index b33b32eb7bf..39adb9a4132 100644 --- a/shared/src/business/entities/contacts/Petitioner.ts +++ b/shared/src/business/entities/contacts/Petitioner.ts @@ -79,8 +79,8 @@ export class Petitioner extends JoiValidationEntity { otherwise: joi.optional(), then: joi.required(), }).messages({ + 'any.required': 'Enter a valid email address', 'string.email': 'Enter email address in format: yourname@example.com', - 'string.empty': 'Enter a valid email address', }), hasConsentedToEService: joi .boolean() From c463f65dd572032d1c8b2e2f94b38cfc015a52ba Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Thu, 12 Sep 2024 10:02:35 -0400 Subject: [PATCH 06/17] 10466: continue updating validation rules for email addresses --- .../entities/ChangePasswordForm.test.ts | 17 +++++++++++++++++ .../src/business/entities/ChangePasswordForm.ts | 3 ++- .../business/entities/UpdateUserEmail.test.ts | 4 ++-- shared/src/business/entities/UpdateUserEmail.ts | 5 +++-- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/shared/src/business/entities/ChangePasswordForm.test.ts b/shared/src/business/entities/ChangePasswordForm.test.ts index d411b78e75e..71389d5c604 100644 --- a/shared/src/business/entities/ChangePasswordForm.test.ts +++ b/shared/src/business/entities/ChangePasswordForm.test.ts @@ -82,6 +82,23 @@ describe('ChangePasswordForm', () => { email: 'Enter a valid email address', }); }); + + it('should not be valid when an email in the correct format is not present', () => { + const inValidChangePasswordForm = { + confirmPassword: 'TestPassword!1', + email: 'myemailaddress', + password: 'TestPassword!1', + }; + + const changePasswordForm = new ChangePasswordForm( + inValidChangePasswordForm, + ); + + expect(changePasswordForm.isValid()).toBe(false); + expect(changePasswordForm.getFormattedValidationErrors()).toMatchObject({ + email: 'Enter email address in format: yourname@example.com', + }); + }); }); describe('Password Requirements', () => { diff --git a/shared/src/business/entities/ChangePasswordForm.ts b/shared/src/business/entities/ChangePasswordForm.ts index 4be5d2b67a9..2aacf584ca6 100644 --- a/shared/src/business/entities/ChangePasswordForm.ts +++ b/shared/src/business/entities/ChangePasswordForm.ts @@ -23,7 +23,8 @@ export class ChangePasswordForm extends JoiValidationEntity { .messages({ '*': 'Passwords must match' }), email: JoiValidationConstants.EMAIL.required() .messages({ - '*': 'Enter a valid email address', + 'any.required': 'Enter a valid email address', + 'string.email': 'Enter email address in format: yourname@example.com', 'string.max': 'Email address must contain fewer than 100 characters', }) .description('Email of user'), diff --git a/shared/src/business/entities/UpdateUserEmail.test.ts b/shared/src/business/entities/UpdateUserEmail.test.ts index f1164c3e446..194fe94f0ae 100644 --- a/shared/src/business/entities/UpdateUserEmail.test.ts +++ b/shared/src/business/entities/UpdateUserEmail.test.ts @@ -61,7 +61,7 @@ describe('UpdateUserEmail', () => { expect(updateUserEmailEntity.isValid()).toBeFalsy(); expect(updateUserEmailEntity.getFormattedValidationErrors()).toEqual({ confirmEmail: 'Email addresses do not match', - email: 'Enter a valid email address', + email: 'Enter email address in format: yourname@example.com', }); }); @@ -73,7 +73,7 @@ describe('UpdateUserEmail', () => { expect(updateUserEmailEntity.isValid()).toBeFalsy(); expect(updateUserEmailEntity.getFormattedValidationErrors()).toEqual({ - confirmEmail: 'Enter a valid email address', + confirmEmail: 'Enter email address in format: yourname@example.com', }); }); diff --git a/shared/src/business/entities/UpdateUserEmail.ts b/shared/src/business/entities/UpdateUserEmail.ts index c81b3d31c8a..6353128dd0e 100644 --- a/shared/src/business/entities/UpdateUserEmail.ts +++ b/shared/src/business/entities/UpdateUserEmail.ts @@ -19,10 +19,11 @@ export class UpdateUserEmail extends JoiValidationEntity { .messages({ 'any.only': 'Email addresses do not match', 'any.required': 'Enter a valid email address', - 'string.email': 'Enter a valid email address', + 'string.email': 'Enter email address in format: yourname@example.com', }), email: JoiValidationConstants.EMAIL.required().messages({ - '*': 'Enter a valid email address', + 'any.required': 'Enter a valid email address', + 'string.email': 'Enter email address in format: yourname@example.com', }), }; From fe37362961449c0c5baa3dcec73bff56e734357e Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Thu, 12 Sep 2024 10:31:39 -0400 Subject: [PATCH 07/17] Update NewPractitioner entity --- shared/src/business/entities/NewPractitioner.test.ts | 6 +++--- shared/src/business/entities/NewPractitioner.ts | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/shared/src/business/entities/NewPractitioner.test.ts b/shared/src/business/entities/NewPractitioner.test.ts index cb203a8548d..c303572fcb0 100644 --- a/shared/src/business/entities/NewPractitioner.test.ts +++ b/shared/src/business/entities/NewPractitioner.test.ts @@ -48,7 +48,7 @@ describe('NewPractitioner', () => { expect(user.isValid()).toBeFalsy(); expect(user.getFormattedValidationErrors()).toMatchObject({ - email: 'Enter email address', + email: 'Enter a valid email address', }); }); @@ -92,7 +92,7 @@ describe('NewPractitioner', () => { expect(validNewPractitioner.isValid()).toBeFalsy(); expect(validNewPractitioner.getFormattedValidationErrors()).toEqual({ confirmEmail: 'Enter a valid email address', - email: 'Enter email address', + email: 'Enter email address in format: yourname@example.com', }); }); @@ -112,7 +112,7 @@ describe('NewPractitioner', () => { expect(validNewPractitioner.isValid()).toBeFalsy(); expect(validNewPractitioner.getFormattedValidationErrors()).toEqual({ - confirmEmail: 'Enter a valid email address', + confirmEmail: 'Enter email address in format: yourname@example.com', }); }); diff --git a/shared/src/business/entities/NewPractitioner.ts b/shared/src/business/entities/NewPractitioner.ts index 3ead26a43a2..25fae80dda2 100644 --- a/shared/src/business/entities/NewPractitioner.ts +++ b/shared/src/business/entities/NewPractitioner.ts @@ -23,10 +23,11 @@ export class NewPractitioner extends Practitioner { }).messages({ 'any.only': 'Email addresses do not match', 'any.required': 'Enter a valid email address', - 'string.email': 'Enter a valid email address', + 'string.email': 'Enter email address in format: yourname@example.com', }), email: JoiValidationConstants.EMAIL.required().messages({ - '*': 'Enter email address', + 'any.required': 'Enter a valid email address', + 'string.email': 'Enter email address in format: yourname@example.com', }), firstName: JoiValidationConstants.STRING.max(100) .required() From ddd34353e01c2de6b89a5f6a7e6092fe1fb8eae7 Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Fri, 13 Sep 2024 08:50:52 -0400 Subject: [PATCH 08/17] 10466: update unit test --- .../createAccountHelper.test.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/web-client/src/presenter/computeds/CreatePetitionerAccount/createAccountHelper.test.ts b/web-client/src/presenter/computeds/CreatePetitionerAccount/createAccountHelper.test.ts index 726dfed345c..0716fa8e195 100644 --- a/web-client/src/presenter/computeds/CreatePetitionerAccount/createAccountHelper.test.ts +++ b/web-client/src/presenter/computeds/CreatePetitionerAccount/createAccountHelper.test.ts @@ -70,7 +70,7 @@ describe('createAccountHelper', () => { }); describe('email', () => { - it('should return the error message when "email" fails validation', () => { + it('should return the correct error message when an invalid email address is provided', () => { const result = runCompute(createAccountHelper, { state: { form: { @@ -79,6 +79,20 @@ describe('createAccountHelper', () => { }, }); + expect(result).toMatchObject({ + email: 'Enter email address in format: yourname@example.com', + }); + }); + + it('should return the correct error message when an invalid email address is provided', () => { + const result = runCompute(createAccountHelper, { + state: { + form: { + email: undefined, + }, + }, + }); + expect(result).toMatchObject({ email: 'Enter a valid email address', }); From 7c7204afd567b427f2d6785a27315d10a9f999c2 Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Mon, 16 Sep 2024 09:12:21 -0400 Subject: [PATCH 09/17] 10466: update test case description --- .../CreatePetitionerAccount/createAccountHelper.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-client/src/presenter/computeds/CreatePetitionerAccount/createAccountHelper.test.ts b/web-client/src/presenter/computeds/CreatePetitionerAccount/createAccountHelper.test.ts index 0716fa8e195..1d5ef90f9f7 100644 --- a/web-client/src/presenter/computeds/CreatePetitionerAccount/createAccountHelper.test.ts +++ b/web-client/src/presenter/computeds/CreatePetitionerAccount/createAccountHelper.test.ts @@ -84,7 +84,7 @@ describe('createAccountHelper', () => { }); }); - it('should return the correct error message when an invalid email address is provided', () => { + it('should return the correct error message when no email address is provided', () => { const result = runCompute(createAccountHelper, { state: { form: { From b586dd18834626abe558adeca031df74120f56cb Mon Sep 17 00:00:00 2001 From: TomElliottFlexion <66225176+TomElliottFlexion@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:10:07 -0500 Subject: [PATCH 10/17] 10466: correct validation rules for UpdateUserEmail entity/form --- shared/src/business/entities/UpdateUserEmail.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/shared/src/business/entities/UpdateUserEmail.ts b/shared/src/business/entities/UpdateUserEmail.ts index 6353128dd0e..53c3968133a 100644 --- a/shared/src/business/entities/UpdateUserEmail.ts +++ b/shared/src/business/entities/UpdateUserEmail.ts @@ -13,9 +13,13 @@ export class UpdateUserEmail extends JoiValidationEntity { this.confirmEmail = rawUpdateUserEmail.confirmEmail; } - static VALIDATION_RULES = { - confirmEmail: JoiValidationConstants.EMAIL.valid(joi.ref('email')) - .required() + static VALIDATION_RULES = joi.object({ + confirmEmail: joi + .when('email', { + is: JoiValidationConstants.EMAIL, + otherwise: JoiValidationConstants.EMAIL.required(), + then: joi.valid(joi.ref('email')).required(), + }) .messages({ 'any.only': 'Email addresses do not match', 'any.required': 'Enter a valid email address', @@ -25,7 +29,7 @@ export class UpdateUserEmail extends JoiValidationEntity { 'any.required': 'Enter a valid email address', 'string.email': 'Enter email address in format: yourname@example.com', }), - }; + }); getValidationRules() { return UpdateUserEmail.VALIDATION_RULES; From 9ade32ce2f7f7db63f9a98bba6d30df6fa2539a0 Mon Sep 17 00:00:00 2001 From: TomElliottFlexion <66225176+TomElliottFlexion@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:41:30 -0500 Subject: [PATCH 11/17] 10466: update paper petition validation logic to required email address when e-service consent box is checked --- shared/src/business/entities/contacts/Contact.ts | 10 +++++++--- web-client/src/views/StartCase/ContactPrimary.tsx | 6 +++++- web-client/src/views/StartCase/ContactSecondary.tsx | 6 +++++- .../src/views/StartCaseInternal/PaperPetitionEmail.tsx | 5 +++-- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/shared/src/business/entities/contacts/Contact.ts b/shared/src/business/entities/contacts/Contact.ts index fdf312295b4..213be2d6fe0 100644 --- a/shared/src/business/entities/contacts/Contact.ts +++ b/shared/src/business/entities/contacts/Contact.ts @@ -109,10 +109,14 @@ export class Contact extends JoiValidationEntity { name: JoiValidationConstants.STRING.max(100) .required() .messages({ '*': 'Enter name' }), - paperPetitionEmail: JoiValidationConstants.EMAIL.optional() - .allow(null) - .description('Email provided by the petitioner on their petition form') + paperPetitionEmail: joi + .when('hasConsentedToEService', { + is: true, + otherwise: JoiValidationConstants.EMAIL.optional(), + then: JoiValidationConstants.EMAIL.required(), + }) .messages({ + 'any.required': 'Enter a valid email address', 'string.email': 'Enter email address in format: yourname@example.com', }), phone: JoiValidationConstants.STRING.max(100) diff --git a/web-client/src/views/StartCase/ContactPrimary.tsx b/web-client/src/views/StartCase/ContactPrimary.tsx index 0f28fa6a5c2..d0c191b640c 100644 --- a/web-client/src/views/StartCase/ContactPrimary.tsx +++ b/web-client/src/views/StartCase/ContactPrimary.tsx @@ -223,7 +223,11 @@ export const ContactPrimary = connect( {contactsHelper.showPaperPetitionEmailFieldAndConsentBox && ( <> - + )} diff --git a/web-client/src/views/StartCase/ContactSecondary.tsx b/web-client/src/views/StartCase/ContactSecondary.tsx index cb3113833b1..abad39a8ac8 100644 --- a/web-client/src/views/StartCase/ContactSecondary.tsx +++ b/web-client/src/views/StartCase/ContactSecondary.tsx @@ -171,7 +171,11 @@ export const ContactSecondary = connect( {(contactsHelper.showPaperPetitionEmailFieldAndConsentBox || contactsHelper.showSecondaryContactEmailFieldAndConsentBox) && ( <> - + )} diff --git a/web-client/src/views/StartCaseInternal/PaperPetitionEmail.tsx b/web-client/src/views/StartCaseInternal/PaperPetitionEmail.tsx index 8898a37e0e1..6ec4b32ac10 100644 --- a/web-client/src/views/StartCaseInternal/PaperPetitionEmail.tsx +++ b/web-client/src/views/StartCaseInternal/PaperPetitionEmail.tsx @@ -10,6 +10,7 @@ export const PaperPetitionEmail = connect( bind: props.bind, contactType: props.contactType, data: state[props.bind], + onBlur: props.onBlur, updateFormValueAndSecondaryContactInfoSequence: sequences.updateFormValueAndSecondaryContactInfoSequence, validationErrors: state.validationErrors, @@ -17,7 +18,7 @@ export const PaperPetitionEmail = connect( function PaperPetitionEmail({ contactType, data, - onBlurSequence, + onBlur, updateFormValueAndSecondaryContactInfoSequence, validationErrors = {}, }) { @@ -42,7 +43,7 @@ export const PaperPetitionEmail = connect( type="email" value={data[contactType].paperPetitionEmail || ''} onBlur={() => { - onBlurSequence(); + onBlur(); }} onChange={e => { updateFormValueAndSecondaryContactInfoSequence({ From 18b01a9e958124ab5b81581d69c6aa9c8898d540 Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Wed, 23 Oct 2024 10:13:40 -0400 Subject: [PATCH 12/17] 10466: update entity validation test --- shared/src/business/entities/UpdateUserEmail.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shared/src/business/entities/UpdateUserEmail.test.ts b/shared/src/business/entities/UpdateUserEmail.test.ts index 194fe94f0ae..6bdbf0d02bd 100644 --- a/shared/src/business/entities/UpdateUserEmail.test.ts +++ b/shared/src/business/entities/UpdateUserEmail.test.ts @@ -60,7 +60,6 @@ describe('UpdateUserEmail', () => { expect(updateUserEmailEntity.isValid()).toBeFalsy(); expect(updateUserEmailEntity.getFormattedValidationErrors()).toEqual({ - confirmEmail: 'Email addresses do not match', email: 'Enter email address in format: yourname@example.com', }); }); @@ -73,7 +72,7 @@ describe('UpdateUserEmail', () => { expect(updateUserEmailEntity.isValid()).toBeFalsy(); expect(updateUserEmailEntity.getFormattedValidationErrors()).toEqual({ - confirmEmail: 'Enter email address in format: yourname@example.com', + confirmEmail: 'Email addresses do not match', }); }); From 60a806a9c6309ce1e5b61e62742b45e0482f86a4 Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Thu, 24 Oct 2024 10:04:02 -0400 Subject: [PATCH 13/17] 10466: remove modal from ChangeLoginAndServiceEmail component and use AppComponent --- web-client/src/views/ChangeLoginAndServiceEmail.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/web-client/src/views/ChangeLoginAndServiceEmail.tsx b/web-client/src/views/ChangeLoginAndServiceEmail.tsx index 29d7cdaea2b..2da8911d2f1 100644 --- a/web-client/src/views/ChangeLoginAndServiceEmail.tsx +++ b/web-client/src/views/ChangeLoginAndServiceEmail.tsx @@ -11,7 +11,6 @@ export const ChangeLoginAndServiceEmail = connect( { form: state.form, navigateToPathSequence: sequences.navigateToPathSequence, - showModal: state.modal.showModal, submitChangeLoginAndServiceEmailSequence: sequences.submitChangeLoginAndServiceEmailSequence, updateFormValueSequence: sequences.updateFormValueSequence, From 77235564f1a8f70a572a36cdd502213de9b007e2 Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Thu, 24 Oct 2024 10:45:51 -0400 Subject: [PATCH 14/17] 10466: fix type error in validatePetitionerInteractor --- shared/src/business/useCases/validatePetitionerInteractor.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/src/business/useCases/validatePetitionerInteractor.ts b/shared/src/business/useCases/validatePetitionerInteractor.ts index 250f6d0c6ce..c724b22d6e5 100644 --- a/shared/src/business/useCases/validatePetitionerInteractor.ts +++ b/shared/src/business/useCases/validatePetitionerInteractor.ts @@ -30,8 +30,8 @@ export const validatePetitionerInteractor = ( let updateUserEmailErrors; if (contactInfo.updatedEmail || contactInfo.confirmEmail) { updateUserEmailErrors = new UpdateUserEmail({ - ...contactInfo, - email: contactInfo.updatedEmail, + confirmEmail: contactInfo.confirmEmail!, + email: contactInfo.updatedEmail!, }).getFormattedValidationErrors(); } From 4f4a481e29561852954542c0d644378137652647 Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Thu, 24 Oct 2024 10:48:20 -0400 Subject: [PATCH 15/17] 10466: fix type error in PractitionerLoginServiceEmailForm --- .../PractitionerLoginServiceEmailForm.tsx | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/web-client/src/views/Practitioners/PractitionerLoginServiceEmailForm.tsx b/web-client/src/views/Practitioners/PractitionerLoginServiceEmailForm.tsx index b1f3a46e914..3b54b35d447 100644 --- a/web-client/src/views/Practitioners/PractitionerLoginServiceEmailForm.tsx +++ b/web-client/src/views/Practitioners/PractitionerLoginServiceEmailForm.tsx @@ -5,14 +5,23 @@ import { sequences } from '@web-client/presenter/app.cerebral'; import { state } from '@web-client/presenter/app.cerebral'; import React from 'react'; -export const PractitionerLoginServiceEmailForm = connect( - { - createPractitionerUserHelper: state.createPractitionerUserHelper, - form: state.form, - updateFormValueSequence: sequences.updateFormValueSequence, - validateSequence: sequences[props.validateSequenceName], - validationErrors: state.validationErrors, - }, +type PractitionerLoginServiceEmailFormProps = { + emailFormName: string; +}; + +const practitionerLoginServiceEmailFormDependencies = { + createPractitionerUserHelper: state.createPractitionerUserHelper, + form: state.form, + updateFormValueSequence: sequences.updateFormValueSequence, + validateSequence: sequences[props.validateSequenceName], + validationErrors: state.validationErrors, +}; + +export const PractitionerLoginServiceEmailForm = connect< + PractitionerLoginServiceEmailFormProps, + typeof practitionerLoginServiceEmailFormDependencies +>( + practitionerLoginServiceEmailFormDependencies, function PractitionerLoginServiceEmailForm({ createPractitionerUserHelper, emailFormName, From 76c2a5fde4bfbd7c6c62ef760afa5e4790ce5283 Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Tue, 29 Oct 2024 09:32:48 -0400 Subject: [PATCH 16/17] 10466: pass onblur handler to econsent component --- web-client/src/views/StartCase/ContactPrimary.tsx | 6 +++++- web-client/src/views/StartCase/ContactSecondary.tsx | 6 +++++- web-client/src/views/StartCaseInternal/EConsent.tsx | 11 ++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/web-client/src/views/StartCase/ContactPrimary.tsx b/web-client/src/views/StartCase/ContactPrimary.tsx index d0c191b640c..35b4946ddf6 100644 --- a/web-client/src/views/StartCase/ContactPrimary.tsx +++ b/web-client/src/views/StartCase/ContactPrimary.tsx @@ -228,7 +228,11 @@ export const ContactPrimary = connect( contactType="contactPrimary" onBlur={onBlur} /> - + )} diff --git a/web-client/src/views/StartCase/ContactSecondary.tsx b/web-client/src/views/StartCase/ContactSecondary.tsx index abad39a8ac8..8cad06ddc61 100644 --- a/web-client/src/views/StartCase/ContactSecondary.tsx +++ b/web-client/src/views/StartCase/ContactSecondary.tsx @@ -176,7 +176,11 @@ export const ContactSecondary = connect( contactType="contactSecondary" onBlur={onBlur} /> - + )} diff --git a/web-client/src/views/StartCaseInternal/EConsent.tsx b/web-client/src/views/StartCaseInternal/EConsent.tsx index 19a1c8d73a6..b8beac89eab 100644 --- a/web-client/src/views/StartCaseInternal/EConsent.tsx +++ b/web-client/src/views/StartCaseInternal/EConsent.tsx @@ -1,21 +1,29 @@ import { FormGroup } from '../../ustc-ui/FormGroup/FormGroup'; +import { props as cerebralProps } from 'cerebral'; import { connect } from '@web-client/presenter/shared.cerebral'; -import { props } from 'cerebral'; import { sequences } from '@web-client/presenter/app.cerebral'; import { state } from '@web-client/presenter/app.cerebral'; import React from 'react'; +const props = cerebralProps as unknown as { + bind: string; + contactType: string; + onBlur: () => void; +}; + export const EConsent = connect( { bind: props.bind, contactType: props.contactType, data: state[props.bind], + onBlur: props.onBlur, updateFormValueAndSecondaryContactInfoSequence: sequences.updateFormValueAndSecondaryContactInfoSequence, }, function EConsent({ contactType, data, + onBlur, updateFormValueAndSecondaryContactInfoSequence, }) { return ( @@ -26,6 +34,7 @@ export const EConsent = connect( id={`electronic-service-consent-${contactType}`} name={`${contactType}.hasConsentedToEService`} type="checkbox" + onBlur={onBlur} onChange={e => { updateFormValueAndSecondaryContactInfoSequence({ key: e.target.name, From 175329d5a4376be79606719952dcb42d30af0f34 Mon Sep 17 00:00:00 2001 From: Andy Kuny Date: Thu, 31 Oct 2024 10:13:18 -0400 Subject: [PATCH 17/17] 10466: remove validation logic for paper petiton email due to business reasons --- shared/src/business/entities/contacts/Contact.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/shared/src/business/entities/contacts/Contact.ts b/shared/src/business/entities/contacts/Contact.ts index 213be2d6fe0..4cb47262a8d 100644 --- a/shared/src/business/entities/contacts/Contact.ts +++ b/shared/src/business/entities/contacts/Contact.ts @@ -109,16 +109,10 @@ export class Contact extends JoiValidationEntity { name: JoiValidationConstants.STRING.max(100) .required() .messages({ '*': 'Enter name' }), - paperPetitionEmail: joi - .when('hasConsentedToEService', { - is: true, - otherwise: JoiValidationConstants.EMAIL.optional(), - then: JoiValidationConstants.EMAIL.required(), - }) - .messages({ - 'any.required': 'Enter a valid email address', - 'string.email': 'Enter email address in format: yourname@example.com', - }), + paperPetitionEmail: JoiValidationConstants.EMAIL.optional() + .allow(null) + .description('Email provided by the petitioner on their petition form') + .messages({ '*': 'Enter email address in format: yourname@example.com' }), phone: JoiValidationConstants.STRING.max(100) .when('contactType', { is: CONTACT_TYPES.secondary,