1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-20 11:24:07 +00:00

[PM-32161] Remove all emails when email list field is cleared and send is saved (#18959)

* add new validation criteria to prevent authType.Email with an empty emails field

* simplify validation logic
This commit is contained in:
John Harrington
2026-02-18 14:59:34 -07:00
committed by GitHub
parent bca2ebaca9
commit 263ec94124
5 changed files with 83 additions and 2 deletions

View File

@@ -127,4 +127,57 @@ describe("SendDetailsComponent", () => {
expect(emailsControl?.validator).toBeNull();
expect(passwordControl?.validator).toBeNull();
});
it("should show validation error when emails are cleared while authType is Email", () => {
// Set authType to Email with valid emails
component.sendDetailsForm.patchValue({
authType: AuthType.Email,
emails: "test@example.com",
});
expect(component.sendDetailsForm.get("emails")?.valid).toBe(true);
// Clear emails - should trigger validation error
component.sendDetailsForm.patchValue({ emails: "" });
expect(component.sendDetailsForm.get("emails")?.valid).toBe(false);
expect(component.sendDetailsForm.get("emails")?.hasError("emailsRequiredForEmailAuth")).toBe(
true,
);
});
it("should clear validation error when authType is changed from Email after clearing emails", () => {
// Set authType to Email and then clear emails
component.sendDetailsForm.patchValue({
authType: AuthType.Email,
emails: "test@example.com",
});
component.sendDetailsForm.patchValue({ emails: "" });
expect(component.sendDetailsForm.get("emails")?.valid).toBe(false);
// Change authType to None - emails field should become valid (no longer required)
component.sendDetailsForm.patchValue({ authType: AuthType.None });
expect(component.sendDetailsForm.get("emails")?.valid).toBe(true);
});
it("should force user to change authType by blocking form submission when emails are cleared", () => {
// Set up a send with email verification
component.sendDetailsForm.patchValue({
name: "Test Send",
authType: AuthType.Email,
emails: "user@example.com",
});
expect(component.sendDetailsForm.valid).toBe(true);
// User clears emails field
component.sendDetailsForm.patchValue({ emails: "" });
// Form should now be invalid, preventing save
expect(component.sendDetailsForm.valid).toBe(false);
expect(component.sendDetailsForm.get("emails")?.hasError("emailsRequiredForEmailAuth")).toBe(
true,
);
// User must change authType to continue
component.sendDetailsForm.patchValue({ authType: AuthType.None });
expect(component.sendDetailsForm.valid).toBe(true);
});
});

View File

@@ -224,7 +224,10 @@ export class SendDetailsComponent implements OnInit {
} else if (type === AuthType.Email) {
passwordControl.setValue(null);
passwordControl.clearValidators();
emailsControl.setValidators([Validators.required, this.emailListValidator()]);
emailsControl.setValidators([
this.emailsRequiredForEmailAuthValidator(),
this.emailListValidator(),
]);
} else {
emailsControl.setValue(null);
emailsControl.clearValidators();
@@ -317,6 +320,23 @@ export class SendDetailsComponent implements OnInit {
};
}
emailsRequiredForEmailAuthValidator(): ValidatorFn {
return (control: FormControl): ValidationErrors | null => {
const authType = this.sendDetailsForm?.get("authType")?.value;
const emails = control.value;
if (authType === AuthType.Email && (!emails || emails.trim() === "")) {
return {
emailsRequiredForEmailAuth: {
message: this.i18nService.t("emailsRequiredChangeAccessType"),
},
};
}
return null;
};
}
generatePassword = async () => {
const on$ = new BehaviorSubject<GenerateRequest>({ source: "send", type: Type.password });
const account$ = this.accountService.activeAccount$.pipe(