Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

10466 design debt #5369

Draft
wants to merge 20 commits into
base: staging
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7c8c237
10466: start making email validation messages uniform
akuny Sep 9, 2024
9b9f809
10466: continue unifying email validation messages
akuny Sep 10, 2024
91ff1ca
10466: update test case
akuny Sep 10, 2024
0c2bb00
10466: adjust NewPetitionerUser test case so that mock data is prepar…
akuny Sep 10, 2024
81dbe05
10466: update Contact entity test case
akuny Sep 10, 2024
c463f65
10466: continue updating validation rules for email addresses
akuny Sep 12, 2024
fe37362
Update NewPractitioner entity
akuny Sep 12, 2024
814f04e
Merge remote-tracking branch 'USTC/staging' into 10466-design-debt
akuny Sep 12, 2024
ddd3435
10466: update unit test
akuny Sep 13, 2024
9a11c53
10466: merge staging
akuny Sep 13, 2024
7c7204a
10466: update test case description
akuny Sep 16, 2024
a73fc07
10466: Clear alerts, errors, and stop showing validation when directi…
akuny Sep 20, 2024
9eb6692
Merge remote-tracking branch 'USTC/staging' into 10466-design-debt
akuny Sep 24, 2024
f3a79f0
10466-design-debt: add live validation to ChangeLoginAndServiceEmail …
akuny Sep 24, 2024
7974b9d
10466: add test for new computed
akuny Sep 24, 2024
6bd433d
10466: update interactor test
akuny Sep 24, 2024
d6b4494
Merge remote-tracking branch 'USTC/staging' into 10466-design-debt
akuny Sep 25, 2024
3a485da
10466: add live email validation to petitioner add/update form
akuny Sep 25, 2024
77ad9d4
10466: reduce duplication by using EmailForm entity and related compu…
akuny Sep 25, 2024
f5957c3
10466: update use case test
akuny Sep 25, 2024
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
17 changes: 17 additions & 0 deletions shared/src/business/entities/ChangePasswordForm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [email protected]',
});
});
});

describe('Password Requirements', () => {
Expand Down
3 changes: 2 additions & 1 deletion shared/src/business/entities/ChangePasswordForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [email protected]',
'string.max': 'Email address must contain fewer than 100 characters',
})
.description('Email of user'),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,89 +1,89 @@
import { UpdateUserEmail } from './UpdateUserEmail';
import { EmailForm } from './EmailForm';

describe('UpdateUserEmail', () => {
describe('UpdateUserEmailForm', () => {
describe('validation', () => {
it('should fail validation when email is not provided', () => {
const updateUserEmailEntity = new UpdateUserEmail({
const updateUserEmailFormEntity = new EmailForm({
confirmEmail: '[email protected]',
email: undefined as any,
});

expect(updateUserEmailEntity.isValid()).toBeFalsy();
expect(updateUserEmailEntity.getFormattedValidationErrors()).toEqual({
expect(updateUserEmailFormEntity.isValid()).toBeFalsy();
expect(updateUserEmailFormEntity.getFormattedValidationErrors()).toEqual({
confirmEmail: 'Email addresses do not match',
email: 'Enter a valid email address',
});
});

it('should fail validation when confirmEmail is not provided', () => {
const updateUserEmailEntity = new UpdateUserEmail({
const updateUserEmailFormEntity = new EmailForm({
confirmEmail: undefined as any,
email: '[email protected]',
});

expect(updateUserEmailEntity.isValid()).toBeFalsy();
expect(updateUserEmailEntity.getFormattedValidationErrors()).toEqual({
expect(updateUserEmailFormEntity.isValid()).toBeFalsy();
expect(updateUserEmailFormEntity.getFormattedValidationErrors()).toEqual({
confirmEmail: 'Enter a valid email address',
});
});

it('should fail validation when confirmEmail does not match email', () => {
const updateUserEmailEntity = new UpdateUserEmail({
const updateUserEmailFormEntity = new EmailForm({
confirmEmail: '[email protected]',
email: '[email protected]',
});

expect(updateUserEmailEntity.isValid()).toBeFalsy();
expect(updateUserEmailEntity.getFormattedValidationErrors()).toEqual({
expect(updateUserEmailFormEntity.isValid()).toBeFalsy();
expect(updateUserEmailFormEntity.getFormattedValidationErrors()).toEqual({
confirmEmail: 'Email addresses do not match',
});
});

it('should fail validation when email and confirmEmail are not provided', () => {
const updateUserEmailEntity = new UpdateUserEmail({
const updateUserEmailFormEntity = new EmailForm({
confirmEmail: undefined as any,
email: undefined as any,
});

expect(updateUserEmailEntity.isValid()).toBeFalsy();
expect(updateUserEmailEntity.getFormattedValidationErrors()).toEqual({
expect(updateUserEmailFormEntity.isValid()).toBeFalsy();
expect(updateUserEmailFormEntity.getFormattedValidationErrors()).toEqual({
confirmEmail: 'Enter a valid email address',
email: 'Enter a valid email address',
});
});

it('should fail validation when email is NOT a valid email address and confirmEmail is valid', () => {
const updateUserEmailEntity = new UpdateUserEmail({
const updateUserEmailFormEntity = new EmailForm({
confirmEmail: '[email protected]',
email: 'testexample.com',
});

expect(updateUserEmailEntity.isValid()).toBeFalsy();
expect(updateUserEmailEntity.getFormattedValidationErrors()).toEqual({
expect(updateUserEmailFormEntity.isValid()).toBeFalsy();
expect(updateUserEmailFormEntity.getFormattedValidationErrors()).toEqual({
confirmEmail: 'Email addresses do not match',
email: 'Enter a valid email address',
email: 'Enter email address in format: [email protected]',
});
});

it('should fail validation when confirmEmail is NOT a valid email address and email is valid', () => {
const updateUserEmailEntity = new UpdateUserEmail({
const updateUserEmailFormEntity = new EmailForm({
confirmEmail: 'testexample.com',
email: '[email protected]',
});

expect(updateUserEmailEntity.isValid()).toBeFalsy();
expect(updateUserEmailEntity.getFormattedValidationErrors()).toEqual({
confirmEmail: 'Enter a valid email address',
expect(updateUserEmailFormEntity.isValid()).toBeFalsy();
expect(updateUserEmailFormEntity.getFormattedValidationErrors()).toEqual({
confirmEmail: 'Enter email address in format: [email protected]',
});
});

it('should pass validation when email and confirmEmail are provided and match', () => {
const updateUserEmailEntity = new UpdateUserEmail({
const updateUserEmailFormEntity = new EmailForm({
confirmEmail: '[email protected]',
email: '[email protected]',
});

expect(updateUserEmailEntity.isValid()).toBeTruthy();
expect(updateUserEmailFormEntity.isValid()).toBeTruthy();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import { JoiValidationConstants } from './JoiValidationConstants';
import { JoiValidationEntity } from '@shared/business/entities/JoiValidationEntity';
import joi from 'joi';

export class UpdateUserEmail extends JoiValidationEntity {
export class EmailForm extends JoiValidationEntity {
public confirmEmail: string;
public email: string;

constructor(rawUpdateUserEmail: { email: string; confirmEmail: string }) {
super('UpdateUserEmail');
constructor(rawEmail: { email: string; confirmEmail: string }) {
super('EmailForm');

this.email = rawUpdateUserEmail.email;
this.confirmEmail = rawUpdateUserEmail.confirmEmail;
this.email = rawEmail.email;
this.confirmEmail = rawEmail.confirmEmail;
}

static VALIDATION_RULES = {
Expand All @@ -19,16 +19,17 @@ 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: [email protected]',
}),
email: JoiValidationConstants.EMAIL.required().messages({
'*': 'Enter a valid email address',
'any.required': 'Enter a valid email address',
'string.email': 'Enter email address in format: [email protected]',
}),
};

getValidationRules() {
return UpdateUserEmail.VALIDATION_RULES;
return EmailForm.VALIDATION_RULES;
}
}

export type RawUpdateUserEmail = ExcludeMethods<UpdateUserEmail>;
export type RawEmailForm = ExcludeMethods<EmailForm>;
29 changes: 27 additions & 2 deletions shared/src/business/entities/NewPetitionerUser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,42 @@ 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 formEntity = new NewPetitionerUser({
...validEntity,
email: 'hello',
email: undefined,
});

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',
});

expect(formEntity.isValid()).toBeFalsy();
expect(formEntity.getValidationErrors()).toEqual({
email: 'Enter email address in format: [email protected]',
});
});

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',
});
});
});

describe('Name', () => {
Expand Down
5 changes: 3 additions & 2 deletions shared/src/business/entities/NewPetitionerUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [email protected]',
'string.max': 'Email address must contain fewer than 100 characters',
})
.description('Email of user'),
entityName:
Expand Down
6 changes: 3 additions & 3 deletions shared/src/business/entities/NewPractitioner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('NewPractitioner', () => {

expect(user.isValid()).toBeFalsy();
expect(user.getFormattedValidationErrors()).toMatchObject({
email: 'Enter email address',
email: 'Enter a valid email address',
});
});

Expand Down Expand Up @@ -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: [email protected]',
});
});

Expand All @@ -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: [email protected]',
});
});

Expand Down
5 changes: 3 additions & 2 deletions shared/src/business/entities/NewPractitioner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [email protected]',
}),
email: JoiValidationConstants.EMAIL.required().messages({
'*': 'Enter email address',
'any.required': 'Enter a valid email address',
'string.email': 'Enter email address in format: [email protected]',
}),
firstName: JoiValidationConstants.STRING.max(100)
.required()
Expand Down
6 changes: 3 additions & 3 deletions shared/src/business/entities/Practitioner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [email protected]',
});
});

Expand All @@ -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: [email protected]',
});
});

Expand Down Expand Up @@ -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: [email protected]',
});
});
});
Expand Down
7 changes: 5 additions & 2 deletions shared/src/business/entities/Practitioner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [email protected]',
}),
entityName: JoiValidationConstants.STRING.valid('Practitioner').required(),
firmName: JoiValidationConstants.STRING.max(100)
Expand Down Expand Up @@ -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: [email protected]',
}),
};

getValidationRules() {
Expand Down
2 changes: 1 addition & 1 deletion shared/src/business/entities/contacts/Contact.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('Contact', () => {
);

expect(contact.getFormattedValidationErrors()!.email).toEqual(
'"email" is required',
'Enter a valid email address',
);
});

Expand Down
8 changes: 7 additions & 1 deletion shared/src/business/entities/contacts/Contact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [email protected]',
'string.empty': 'Enter a valid email address',
}),
hasConsentedToEService: joi
.boolean()
Expand All @@ -108,7 +112,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: [email protected]' }),
.messages({
'string.email': 'Enter email address in format: [email protected]',
}),
phone: JoiValidationConstants.STRING.max(100)
.when('contactType', {
is: CONTACT_TYPES.secondary,
Expand Down
11 changes: 8 additions & 3 deletions shared/src/business/entities/contacts/Petitioner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ export class Petitioner 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: [email protected]',
}),
hasConsentedToEService: joi
.boolean()
Expand All @@ -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: [email protected]',
}),
sealedAndUnavailable: joi.boolean().optional(),
serviceIndicator: JoiValidationConstants.STRING.valid(
...Object.values(SERVICE_INDICATOR_TYPES),
Expand Down
Loading
Loading