diff --git a/lib/createForm.js b/lib/createForm.js index acd2fba..2f15d6a 100644 --- a/lib/createForm.js +++ b/lib/createForm.js @@ -40,11 +40,7 @@ export const createForm = config => { return allTouched && noErrors; }); - function handleChange(event) { - const { name: field, value } = event.target; - - updateTouched(field, true); - + function validateField(field, value) { if (validationSchema) { isValidating.set(true); return util @@ -53,7 +49,6 @@ export const createForm = config => { .then(() => util.update(errors, field, "")) .catch(err => util.update(errors, field, err.message)) .finally(() => { - updateField(field, value); isValidating.set(false); }); } @@ -64,12 +59,19 @@ export const createForm = config => { .then(() => validateFn({ [field]: value })) .then(errs => util.update(errors, field, errs[field])) .finally(() => { - updateField(field, value); isValidating.set(false); - }) + }); } - updateField(field, value); + return Promise.resolve(); + } + + function handleChange(event) { + const { name: field, value } = event.target; + + updateTouched(field, true); + + return validateField(field, value).finally(() => updateField(field, value)); } function handleSubmit(ev) { @@ -151,6 +153,7 @@ export const createForm = config => { handleReset, updateField, updateTouched, + validateField, state: derived( [form, errors, touched, isValid, isValidating, isSubmitting], ([$form, $errors, $touched, $isValid, $isValidating, $isSubmitting]) => ({ diff --git a/test/lib.spec.js b/test/lib.spec.js index fae46d6..72bf5d4 100644 --- a/test/lib.spec.js +++ b/test/lib.spec.js @@ -173,6 +173,61 @@ describe("createForm", () => { }); }); + const validationAssert = ( + action, + { error: errorArgs, success: successArgs } + ) => { + const getTest = () => { + describe("runs field validation", () => { + it("and set errors for invalid value", done => { + instance[action] + .apply(null, errorArgs) + .then(() => subscribeOnce(instance.errors)) + .then(errors => + expect(errors.email).toBe("this must be a valid email") + ) + .then(done); + }); + it("and not set errors for valid value", done => { + instance[action] + .apply(null, successArgs) + .then(() => subscribeOnce(instance.errors)) + .then(errors => expect(errors.email).toBe("")) + .then(done); + }); + }); + }; + describe("when validateSchema is provided", () => { + let instance = getInstance(); + getTest(); + }); + + describe("when validateFn is provided", () => { + const instance = createForm({ + initialValues: { + email: "" + }, + validate: values => { + let errs = {}; + if (values.email === "invalid.email") { + errs.email = "this must be a valid email"; + } + return errs; + }, + onSubmit: values => console.log(values) + }); + + getTest(); + }); + }; + + describe("validateField", () => { + validationAssert("validateField", { + error: ["email", "invalid.email"], + success: ["email", "test@example.org"] + }); + }); + describe("handleChange", () => { it("updates the form when connected to change handler of input", done => { subscribeOnce(instance.form).then(form => @@ -192,47 +247,23 @@ describe("createForm", () => { .then(done); }); - it("runs field validation when validateSchema is provided", done => { - const invalid = "invalid.email"; - const event = { - target: { - name: "email", - value: invalid - } - }; - instance - .handleChange(event) - .then(() => subscribeOnce(instance.errors)) - .then(errors => expect(errors.email).toBe("this must be a valid email")) - .then(done); - }); - - it("runs field validation when validateFn is provided", done => { - const invalid = "invalid.email"; - const event = { - target: { - name: "email", - value: invalid - } - }; - const instance = createForm({ - initialValues: { - email: "", - }, - validate: values => { - let errs = {}; - if (values.email === "invalid.email") { - errs.email = "this email is invalid"; - } - return errs; - }, - onSubmit: (values) => console.log(values) - }); - instance - .handleChange(event) - .then(() => subscribeOnce(instance.errors)) - .then(errors => expect(errors.email).toBe("this email is invalid")) - .then(done); + const eventInvalid = { + target: { + name: "email", + value: "invalid.email" + } + }; + + const eventValid = { + target: { + name: "email", + value: "test@example.org" + } + }; + + validationAssert("handleChange", { + error: [eventInvalid], + success: [eventValid] }); });