diff --git a/web/html/src/components/input/InputBase.test.tsx b/web/html/src/components/input/InputBase.test.tsx index a87b49f5a20..bfb7706719e 100644 --- a/web/html/src/components/input/InputBase.test.tsx +++ b/web/html/src/components/input/InputBase.test.tsx @@ -4,7 +4,7 @@ import { render, screen } from "utils/test-utils"; import { Form } from "./form/Form"; import { InputBase } from "./InputBase"; -import { Validate } from "./validate"; +import { Validation } from "./validation/validation"; describe("InputBase", () => { // Use these to test model changes in tests @@ -41,7 +41,7 @@ describe("InputBase", () => { }; renderWithForm( - + {({ setValue }) => { if (isFirstFire) { // Realistically this should be with a user interaction, but we manually fire it off to see if it propagates @@ -64,7 +64,7 @@ describe("InputBase", () => { }; renderWithForm( - + {({ setValue }) => { if (isFirstFire) { setValue("username", "fo"); @@ -87,7 +87,7 @@ describe("InputBase", () => { }; renderWithForm( - + {({ setValue }) => { if (isFirstFire) { setValue("firstname", "John"); diff --git a/web/html/src/components/input/InputBase.tsx b/web/html/src/components/input/InputBase.tsx index ef46b51e28a..bba9188e9fd 100644 --- a/web/html/src/components/input/InputBase.tsx +++ b/web/html/src/components/input/InputBase.tsx @@ -6,7 +6,7 @@ import _isNil from "lodash/isNil"; import { FormContext } from "./form/Form"; import { FormGroup } from "./FormGroup"; import { Label } from "./Label"; -import { ValidationResult, Validator } from "./validate"; +import { ValidationResult, Validator } from "./validation/validation"; export type InputBaseProps = { /** name of the field to map in the form model. diff --git a/web/html/src/components/input/form-multi-input/multiple-fields.stories.tsx b/web/html/src/components/input/form-multi-input/multiple-fields.stories.tsx index 19c01f8e489..14a156fec67 100644 --- a/web/html/src/components/input/form-multi-input/multiple-fields.stories.tsx +++ b/web/html/src/components/input/form-multi-input/multiple-fields.stories.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { SubmitButton } from "components/buttons"; -import { Form, Text, Validate } from "components/input"; +import { Form, Text, Validation } from "components/input"; import { FormMultiInput } from "./FormMultiInput"; @@ -47,7 +47,7 @@ export default () => { required labelClass="col-md-3" divClass="col-md-6" - validate={[Validate.minLength(2)]} + validate={[Validation.minLength(2)]} /> { required labelClass="col-md-3" divClass="col-md-6" - validate={[Validate.minLength(2)]} + validate={[Validation.minLength(2)]} /> )} diff --git a/web/html/src/components/input/form-multi-input/single-field.stories.tsx b/web/html/src/components/input/form-multi-input/single-field.stories.tsx index 49cccb9218e..ac937b15b05 100644 --- a/web/html/src/components/input/form-multi-input/single-field.stories.tsx +++ b/web/html/src/components/input/form-multi-input/single-field.stories.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { SubmitButton } from "components/buttons"; -import { Form, FormMultiInput, Text, Validate } from "components/input"; +import { Form, FormMultiInput, Text, Validation } from "components/input"; export default () => { const [model, setModel] = useState({ user0_login: "jdoe" }); @@ -43,7 +43,7 @@ export default () => { required labelClass="col-md-3" divClass="col-md-6" - validate={Validate.minLength(2)} + validate={Validation.minLength(2)} /> )} diff --git a/web/html/src/components/input/form-multi-input/table-fields.stories.tsx b/web/html/src/components/input/form-multi-input/table-fields.stories.tsx index 985660a15ed..c0f76926b1b 100644 --- a/web/html/src/components/input/form-multi-input/table-fields.stories.tsx +++ b/web/html/src/components/input/form-multi-input/table-fields.stories.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { SubmitButton } from "components/buttons"; -import { Form, FormMultiInput, Text, Validate } from "components/input"; +import { Form, FormMultiInput, Text, Validation } from "components/input"; export default () => { const [model, setModel] = useState({ user0_firstname: "John", user0_lastname: "Doe", user0_age: 42 }); @@ -53,7 +53,7 @@ export default () => { name={`user${index}_firstname`} required divClass="col-md-12" - validate={Validate.minLength(2)} + validate={Validation.minLength(2)} className="col-md-4" /> { required divClass="col-md-12" className="col-md-4" - validate={Validate.minLength(2)} + validate={Validation.minLength(2)} /> diff --git a/web/html/src/components/input/form/Form.stories.tsx b/web/html/src/components/input/form/Form.stories.tsx index 74e0689d65e..fa35730eecc 100644 --- a/web/html/src/components/input/form/Form.stories.tsx +++ b/web/html/src/components/input/form/Form.stories.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { SubmitButton } from "components/buttons"; -import { Form, Text, Validate } from "components/input"; +import { Form, Text, Validation } from "components/input"; export default () => { const [model, setModel] = useState({ @@ -22,7 +22,7 @@ export default () => { required labelClass="col-md-3" divClass="col-md-6" - validate={Validate.minLength(2)} + validate={Validation.minLength(2)} /> diff --git a/web/html/src/components/input/index.ts b/web/html/src/components/input/index.ts index 36566c7c458..0101b61ab6f 100644 --- a/web/html/src/components/input/index.ts +++ b/web/html/src/components/input/index.ts @@ -9,4 +9,4 @@ export * from "./radio/Radio"; export * from "./range/Range"; export * from "./select/Select"; export * from "./text/Text"; -export * from "./validate"; +export * from "./validation/validation"; diff --git a/web/html/src/components/input/password/Password.stories.tsx b/web/html/src/components/input/password/Password.stories.tsx index 004f9fdba46..ed57d599295 100644 --- a/web/html/src/components/input/password/Password.stories.tsx +++ b/web/html/src/components/input/password/Password.stories.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { SubmitButton } from "components/buttons"; -import { Form, Password, Validate } from "components/input"; +import { Form, Password, Validation } from "components/input"; export default () => { const [model, setModel] = useState({ @@ -22,7 +22,7 @@ export default () => { required labelClass="col-md-3" divClass="col-md-6" - validate={Validate.minLength(4)} + validate={Validation.minLength(4)} /> diff --git a/web/html/src/components/input/text/Text.stories.tsx b/web/html/src/components/input/text/Text.stories.tsx index 8a73e47529d..c5eaeae31bc 100644 --- a/web/html/src/components/input/text/Text.stories.tsx +++ b/web/html/src/components/input/text/Text.stories.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { SubmitButton } from "components/buttons"; -import { Form, Text, Validate } from "components/input"; +import { Form, Text, Validation } from "components/input"; export default () => { const [model, setModel] = useState({ @@ -22,10 +22,10 @@ export default () => { required labelClass="col-md-3" divClass="col-md-6" - validate={Validate.minLength(2)} + validate={Validation.minLength(2)} />

(Last name has no label.)

- + ); diff --git a/web/html/src/components/input/validation/helpers.stories.tsx b/web/html/src/components/input/validation/helpers.stories.tsx index 40224d9469f..3415a19c041 100644 --- a/web/html/src/components/input/validation/helpers.stories.tsx +++ b/web/html/src/components/input/validation/helpers.stories.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; -import { Form, Text, Validate } from "components/input"; +import { Form, Text, Validation } from "components/input"; export default () => { const [model, setModel] = useState({ foo: "Foo", bar: "3", tea: "Hi" }); @@ -8,9 +8,9 @@ export default () => { return (

There are numerous validation helpers:

- - - + + + ); }; diff --git a/web/html/src/components/input/validation/validation.test.ts b/web/html/src/components/input/validation/validation.test.ts new file mode 100644 index 00000000000..c0d5c28374d --- /dev/null +++ b/web/html/src/components/input/validation/validation.test.ts @@ -0,0 +1,76 @@ +import { Validation } from "./validation"; + +const errorMessage = "error message"; + +describe("validation", () => { + test("minLength string", () => { + const validator = Validation.minLength(3, errorMessage); + + expect(validator("foo")).toEqual(undefined); + expect(validator("fo")).toEqual(errorMessage); + }); + + test("minLength object", () => { + const validator = Validation.minLength(3, errorMessage); + + expect( + validator({ + foo: "foo", + bar: "bar", + tea: "tea", + }) + ).toEqual(undefined); + + expect( + validator({ + foo: "foo", + bar: "ba", + tea: "tea", + }) + ).toEqual(errorMessage); + }); + + test("maxLength string", () => { + const validator = Validation.maxLength(3, errorMessage); + + expect(validator("foo")).toEqual(undefined); + expect(validator("fooo")).toEqual(errorMessage); + }); + + test("maxLength object", () => { + const validator = Validation.maxLength(3, errorMessage); + + expect( + validator({ + foo: "foo", + bar: "bar", + tea: "tea", + }) + ).toEqual(undefined); + + expect( + validator({ + foo: "foo", + bar: "barr", + tea: "tea", + }) + ).toEqual(errorMessage); + }); + + test("isInt", () => { + const validator = Validation.isInt(); + + // If you want the value to be required, set the `required` flag instead + expect(validator("")).toEqual(true); + expect(validator("0")).toEqual(true); + expect(validator("42")).toEqual(true); + expect(validator("42.")).toEqual(false); + expect(validator("4.2")).toEqual(false); + expect(validator("0x1")).toEqual(false); + expect(validator("foo")).toEqual(false); + }); + + test("matches", () => { + // TODO: Implement + }); +}); diff --git a/web/html/src/components/input/validate.ts b/web/html/src/components/input/validation/validation.ts similarity index 98% rename from web/html/src/components/input/validate.ts rename to web/html/src/components/input/validation/validation.ts index 490d017d012..01cb9017c66 100644 --- a/web/html/src/components/input/validate.ts +++ b/web/html/src/components/input/validation/validation.ts @@ -59,7 +59,7 @@ const isInt = } }; -export const Validate = { +export const Validation = { matches, minLength, maxLength,