mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 22:33:35 +00:00
[SM-628] Add trim validator to SM dialogs (#4993)
* Add trim validator to SM dialogs * Swap to creating a generic component * Swap to BitValidators.trimValidator * Fix storybook * update validator to auto trim whitespace * update storybook copy * fix copy * update trim validator to run on submit * add validator to project name in secret dialog; update secret name validation to on submit --------- Co-authored-by: William Martin <contact@willmartian.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import { InputModule } from "../input/input.module";
|
||||
import { I18nMockService } from "../utils/i18n-mock.service";
|
||||
|
||||
import { forbiddenCharacters } from "./bit-validators/forbidden-characters.validator";
|
||||
import { trimValidator } from "./bit-validators/trim.validator";
|
||||
import { BitFormFieldComponent } from "./form-field.component";
|
||||
import { FormFieldModule } from "./form-field.module";
|
||||
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
return new I18nMockService({
|
||||
inputForbiddenCharacters: (chars) =>
|
||||
`The following characters are not allowed: ${chars}`,
|
||||
inputTrimValidator: "Input must not contain only whitespace.",
|
||||
});
|
||||
},
|
||||
},
|
||||
@@ -56,3 +58,20 @@ export const ForbiddenCharacters: StoryObj<BitFormFieldComponent> = {
|
||||
template,
|
||||
}),
|
||||
};
|
||||
|
||||
export const TrimValidator: StoryObj<BitFormFieldComponent> = {
|
||||
render: (args: BitFormFieldComponent) => ({
|
||||
props: {
|
||||
formObj: new FormBuilder().group({
|
||||
name: [
|
||||
"",
|
||||
{
|
||||
updateOn: "submit",
|
||||
validators: [trimValidator],
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
template,
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { forbiddenCharacters } from "./forbidden-characters.validator";
|
||||
export { trimValidator } from "./trim.validator";
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { FormControl } from "@angular/forms";
|
||||
|
||||
import { trimValidator as validate } from "./trim.validator";
|
||||
|
||||
describe("trimValidator", () => {
|
||||
it("should not error when input is null", () => {
|
||||
const input = createControl(null);
|
||||
const errors = validate(input);
|
||||
|
||||
expect(errors).toBe(null);
|
||||
});
|
||||
|
||||
it("should not error when input is an empty string", () => {
|
||||
const input = createControl("");
|
||||
const errors = validate(input);
|
||||
|
||||
expect(errors).toBe(null);
|
||||
});
|
||||
|
||||
it("should not error when input has no whitespace", () => {
|
||||
const input = createControl("test value");
|
||||
const errors = validate(input);
|
||||
|
||||
expect(errors).toBe(null);
|
||||
});
|
||||
|
||||
it("should remove beginning whitespace", () => {
|
||||
const input = createControl(" test value");
|
||||
const errors = validate(input);
|
||||
|
||||
expect(errors).toBe(null);
|
||||
expect(input.value).toBe("test value");
|
||||
});
|
||||
|
||||
it("should remove trailing whitespace", () => {
|
||||
const input = createControl("test value ");
|
||||
const errors = validate(input);
|
||||
|
||||
expect(errors).toBe(null);
|
||||
expect(input.value).toBe("test value");
|
||||
});
|
||||
|
||||
it("should remove beginning and trailing whitespace", () => {
|
||||
const input = createControl(" test value ");
|
||||
const errors = validate(input);
|
||||
|
||||
expect(errors).toBe(null);
|
||||
expect(input.value).toBe("test value");
|
||||
});
|
||||
|
||||
it("should error when input is just whitespace", () => {
|
||||
const input = createControl(" ");
|
||||
const errors = validate(input);
|
||||
|
||||
expect(errors).toEqual({ trim: { message: "input is only whitespace" } });
|
||||
});
|
||||
});
|
||||
|
||||
function createControl(input: string) {
|
||||
return new FormControl(input);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { AbstractControl, FormControl, ValidatorFn } from "@angular/forms";
|
||||
|
||||
/**
|
||||
* Automatically trims FormControl value. Errors if value only contains whitespace.
|
||||
*
|
||||
* Should be used with `updateOn: "submit"`
|
||||
*/
|
||||
export const trimValidator: ValidatorFn = (control: AbstractControl<string>) => {
|
||||
if (!(control instanceof FormControl)) {
|
||||
throw new Error("trimValidator only supports validating FormControls");
|
||||
}
|
||||
const value = control.value;
|
||||
if (value === null || value === undefined || value === "") {
|
||||
return null;
|
||||
}
|
||||
if (!value.trim().length) {
|
||||
return {
|
||||
trim: {
|
||||
message: "input is only whitespace",
|
||||
},
|
||||
};
|
||||
}
|
||||
if (value !== value.trim()) {
|
||||
control.setValue(value.trim());
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -38,6 +38,8 @@ export class BitErrorComponent {
|
||||
return this.i18nService.t("inputForbiddenCharacters", this.error[1]?.characters.join(", "));
|
||||
case "multipleEmails":
|
||||
return this.i18nService.t("multipleInputEmails");
|
||||
case "trim":
|
||||
return this.i18nService.t("inputTrimValidator");
|
||||
default:
|
||||
// Attempt to show a custom error message.
|
||||
if (this.error[1]?.message) {
|
||||
|
||||
Reference in New Issue
Block a user