UNPKG

powerform

Version:
568 lines (567 loc) 19.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.equals = void 0; const index_1 = require("./index"); function equals(fieldName) { return (val, ctx) => { if (ctx !== undefined) { if (val != ctx.all[fieldName]) { return `Must be equal to "${fieldName}"`; } return undefined; } return undefined; }; } exports.equals = equals; function capitalize(val) { if (val === "") return val; return val.replace(/(?:^|\s)\S/g, (s) => s.toUpperCase()); } function signupForm() { return new index_1.Form({ username: (0, index_1.str)(), name: (0, index_1.str)().onInput(capitalize), password: (0, index_1.str)(), confirmPassword: (0, index_1.str)(equals("password")), }); } describe("field.constructor()", () => { it("sets the decoder and validators", () => { function isApple(val) { if (val !== "apple") return "Expected an apple"; return undefined; } const fruitField = (0, index_1.str)(isApple); fruitField.setAndValidate("banana"); expect(fruitField.error).toEqual("Expected an apple"); expect(fruitField.value).toEqual("banana"); }); }); describe("field.setValue", () => { it("sets current value", () => { const value = "apple"; const field = (0, index_1.str)(); field.setValue(value); expect(field.value).toEqual(value); }); it("calls onInput and sets value returned by it", () => { const field = (0, index_1.str)().onInput(capitalize); field.setValue("red apple"); expect(field.value).toEqual("Red Apple"); }); it("calls onChange callback if exists", () => { const spy = jest.fn(); const fruit = (0, index_1.str)().onChange(spy); const value = "apple"; fruit.setValue(value); expect(spy.mock.calls[0][0]).toEqual(value); }); it("won't call onChange if value has not changed", () => { const spy = jest.fn(); const fruit = (0, index_1.str)().onChange(spy); const value = "apple"; fruit.setValue(value); expect(spy.mock.calls.length).toEqual(1); fruit.setValue(value); expect(spy.mock.calls.length).toEqual(1); }); it("won't call onChange callback if 'skipTrigger' is true", () => { const spy = jest.fn(); const fruit = (0, index_1.str)().onChange(spy); const value = "apple"; fruit.setValue(value, true); expect(spy.mock.calls.length).toEqual(0); }); }); describe("field.getValue()", () => { it("returns current value", () => { const value = "apple"; const fruit = (0, index_1.str)(); fruit.setValue(value); expect(fruit.value).toEqual(value); }); }); describe("field.validate()", () => { it("returns true on positive validation", () => { const { fields } = new index_1.Form({ fruit: (0, index_1.str)(), }); fields.fruit.setValue("apple"); expect(fields.fruit.validate()).toEqual(true); }); it("returns false on negative validation", () => { const { fields } = new index_1.Form({ fruit: (0, index_1.str)(), }); fields.fruit.setValue(1); expect(fields.fruit.validate()).toEqual(false); }); it("sets error", () => { const { fields } = new index_1.Form({ fruit: (0, index_1.str)(), }); fields.fruit.setValue(1); fields.fruit.validate(); expect(fields.fruit.error).toEqual("Expected a string, got 1"); }); it("can validate in relation to other form fields if exists", () => { const { fields } = new index_1.Form({ password: (0, index_1.str)(), confirmPassword: (0, index_1.str)(equals("password")), }); fields.password.setValue("apple"); fields.confirmPassword.setValue("banana"); fields.confirmPassword.validate(); expect(fields.confirmPassword.error).toEqual(`Must be equal to "password"`); }); }); describe("field.isValid()", () => { const schema = { fruit: (0, index_1.str)() }; it("returns true on positive validation", () => { const { fields } = new index_1.Form(schema); fields.fruit.setValue("apple"); expect(fields.fruit.isValid()).toEqual(true); }); it("returns false on negative validation", () => { const { fields } = new index_1.Form(schema); fields.fruit.setValue(1); expect(fields.fruit.isValid()).toEqual(false); }); it("wont set error", () => { const { fields } = new index_1.Form(schema); fields.fruit.setValue(1); expect(fields.fruit.isValid()).toEqual(false); expect(fields.fruit.error).toEqual(""); }); }); describe("field.setError()", () => { it("sets error", () => { const schema = { fruit: (0, index_1.str)() }; const { fields } = new index_1.Form(schema); const errMsg = "Nice error !!!"; fields.fruit.setError(errMsg); expect(fields.fruit.error).toEqual(errMsg); }); it("calls onError callback if exists", () => { const spy = jest.fn(); const schema = { fruit: (0, index_1.str)().onError(spy), }; const { fields } = new index_1.Form(schema); const errMsg = "Nice error !!!"; fields.fruit.setError(errMsg); expect(spy.mock.calls.length).toEqual(1); }); it("wont call onError callback if 'skipError' is true", () => { const spy = jest.fn(); const schema = { fruit: (0, index_1.str)().onError(spy), }; const { fields } = new index_1.Form(schema); const errMsg = "Nice error !!!"; fields.fruit.setError(errMsg, true); expect(spy.mock.calls.length).toEqual(0); }); }); describe("field.getError()", () => { it("returns error", () => { const { fields } = new index_1.Form({ fruit: (0, index_1.str)() }); const errMsg = "Nice error !!!"; fields.fruit.setError(errMsg); expect(fields.fruit.error).toEqual(errMsg); }); }); describe("field.isDirty()", () => { it("returns true for dirty field", () => { const { fields } = new index_1.Form({ fruit: (0, index_1.str)() }); fields.fruit.setValue("apple"); expect(fields.fruit.isDirty()).toEqual(true); }); it("returns false for non dirty field", () => { const { fields } = new index_1.Form({ fruit: (0, index_1.str)() }); expect(fields.fruit.isDirty()).toEqual(false); }); }); describe("field.makePristine()", () => { it("sets previousValue and initialValue to currentValue", () => { const { fields } = new index_1.Form({ fruit: (0, index_1.str)() }); fields.fruit.setValue("apple"); expect(fields.fruit.isDirty()).toEqual(true); fields.fruit.makePristine(); expect(fields.fruit.isDirty()).toEqual(false); }); it("empties error", () => { const { fields } = new index_1.Form({ fruit: (0, index_1.str)() }); fields.fruit.validate(); expect(fields.fruit.error).toEqual("This field is required"); fields.fruit.makePristine(); expect(fields.fruit.error).toEqual(""); }); }); describe("field.reset()", () => { it("sets currentValue and previousValue to initialValue", () => { const { fields } = new index_1.Form({ fruit: (0, index_1.str)() }).initValue({ fruit: "apple" }); fields.fruit.setValue("banana"); expect(fields.fruit.value).toEqual("banana"); fields.fruit.reset(); expect(fields.fruit.value).toEqual("apple"); }); it("calls onChange callback", () => { const spy = jest.fn(); const { fields } = new index_1.Form({ fruit: (0, index_1.str)().onChange(spy), }); fields.fruit.setValue("banana"); expect(fields.fruit.value).toEqual("banana"); fields.fruit.reset(); expect(spy.mock.calls[1][0]).toEqual(""); }); it("empties error", () => { const { fields } = new index_1.Form({ fruit: (0, index_1.str)() }); fields.fruit.validate(); expect(fields.fruit.error).toEqual("This field is required"); fields.fruit.reset(); expect(fields.fruit.error).toEqual(""); }); }); describe("field.setAndValidate()", () => { it("sets and validates field", () => { const { fields } = new index_1.Form({ fruit: (0, index_1.str)() }); const error = fields.fruit.setAndValidate(""); expect(error).toEqual("This field is required"); }); }); describe("powerform", () => { it("returns form instance", () => { const form = signupForm(); expect(form instanceof index_1.Form).toEqual(true); }); it("attaches self to each field", () => { const form = signupForm(); const { fields } = form; expect(fields.username.form).toBe(form); expect(fields.password.form).toBe(form); expect(fields.confirmPassword.form).toBe(form); }); it("attaches field name to each field", () => { const form = signupForm(); const { fields } = form; expect(fields.username.fieldName).toEqual("username"); expect(fields.password.fieldName).toEqual("password"); expect(fields.confirmPassword.fieldName).toEqual("confirmPassword"); }); }); describe("form.validate", () => { it("returns true if all the fields are valid", () => { const form = signupForm(); const data = { username: "ausername", name: "a name", password: "apassword", confirmPassword: "apassword", }; form.setValue(data); expect(form.validate()).toEqual(true); }); it("returns false if any of the field is invalid", () => { const form = signupForm(); const data = { username: "ausername", name: "a name", password: "apassword", confirmPassword: "", }; form.setValue(data); expect(form.validate()).toEqual(false); }); it("sets error", () => { const form = signupForm(); form.validate(); expect(form.error).toEqual({ confirmPassword: "This field is required", name: "This field is required", password: "This field is required", username: "This field is required", }); }); it("calls onError callback", () => { const spy = jest.fn(); const form = signupForm().onError(spy); form.validate(); expect(spy.mock.calls.length).toEqual(1); }); it("respects config.stopOnError", () => { const schema = { username: (0, index_1.str)(), name: (0, index_1.str)(), password: (0, index_1.str)(), }; const config = { stopOnError: true }; const form = new index_1.Form(schema, config); const { fields } = form; fields.username.setValue("a username"); expect(form.validate()).toEqual(false); expect(fields.username.error).toEqual(""); expect(fields.name.error).toEqual("This field is required"); expect(fields.password.error).toEqual(""); }); }); describe("form.isValid", () => { it("returns true if all the fields are valid", () => { const form = signupForm(); const data = { username: "ausername", name: "a name", password: "apassword", confirmPassword: "apassword", }; form.setValue(data); expect(form.isValid()).toEqual(true); }); it("returns false if any of the field is invalid", () => { const form = signupForm(); const data = { username: "ausername", name: "a name", password: "apassword", confirmPassword: "", }; form.setValue(data); expect(form.isValid()).toEqual(false); }); it("won't set error", () => { const form = signupForm(); form.isValid(); expect(form.error).toEqual({ confirmPassword: "", name: "", password: "", username: "", }); }); it("won't call onError callback", () => { const spy = jest.fn(); const form = signupForm().onError(spy); form.isValid(); expect(spy.mock.calls.length).toEqual(0); }); }); describe("form.setData", () => { it("sets data of each field", () => { const form = new index_1.Form({ price: (0, index_1.num)() }); const data = { price: 1 }; form.setValue(data); expect(form.fields.price.value).toEqual(data.price); }); it("wont trigger update event from fields", () => { const spy = jest.fn(); const form = signupForm().onChange(spy); const data = { username: "ausername", name: "A Name", password: "apassword", confirmPassword: "apassword", }; form.setValue(data); expect(spy.mock.calls.length).toEqual(1); expect(spy.mock.calls[0][0]).toEqual(data); }); }); describe("form.getUpdates", () => { it("returns key value pair of updated fields and their value", () => { const form = signupForm(); form.fields.username.setValue("ausername"); form.fields.password.setValue("apassword"); const expected = { username: "ausername", password: "apassword", }; expect(form.getUpdates()).toEqual(expected); }); }); describe("form.setError", () => { it("sets error on each field", () => { const form = signupForm(); const errors = { name: "", username: "a error", password: "a error", confirmPassword: "", }; form.setError(errors); expect(form.fields.username.error).toEqual(errors.username); expect(form.fields.password.error).toEqual(errors.password); }); it("calls onError callback only once", () => { const spy = jest.fn(); const form = signupForm().onError(spy); const errors = { name: "", username: "a error", password: "a error", confirmPassword: "", }; form.setError(errors); expect(spy.mock.calls.length).toEqual(1); expect(spy.mock.calls[0]).toEqual([errors]); }); }); describe("form.getError", () => { it("returns errors from every fields", () => { const form = signupForm(); form.fields.username.setError("a error"); form.fields.password.setError("a error"); const expected = { username: "a error", name: "", password: "a error", confirmPassword: "", }; expect(form.error).toEqual(expected); }); }); describe("form.isDirty", () => { it("returns true if any field's data has changed", () => { const form = signupForm(); form.fields.username.setValue("ausername"); expect(form.isDirty()).toEqual(true); }); it("returns false if non of the field's data has changed", () => { const form = signupForm(); expect(form.isDirty()).toEqual(false); }); }); describe("form.makePristine", () => { it("makes all the fields prestine", () => { const form = signupForm(); const data = { name: "", username: "ausername", password: "apassword", confirmPassword: "password confirmation", }; form.setValue(data); expect(form.isDirty()).toEqual(true); form.makePristine(); expect(form.isDirty()).toEqual(false); }); it("empties all the error fields and calls onError callback only once", () => { const spy = jest.fn(); const form = signupForm().onError(spy); form.setValue({ name: "", password: "", username: "ausername", confirmPassword: "", }); form.validate(); // first call expect(form.isDirty()).toEqual(true); expect(form.error).toEqual({ confirmPassword: "This field is required", name: "This field is required", password: "This field is required", username: "", }); form.makePristine(); // second call expect(form.isDirty()).toEqual(false); expect(form.error).toEqual({ confirmPassword: "", name: "", password: "", username: "", }); expect(spy.mock.calls.length).toEqual(2); }); }); describe("form.reset", () => { it("resets all the fields and calls onChange callback only once", () => { const spy = jest.fn(); const form = signupForm().onChange(spy); const data = { username: "ausername", name: "a name", password: "apassword", confirmPassword: "password confirmation", }; form.setValue(data); // first trigger form.reset(); // second trigger const expected = { username: "", name: "", password: "", confirmPassword: "", }; expect(form.raw).toEqual(expected); expect(spy.mock.calls.length).toEqual(2); }); it("resets all the errors and calls onError callback only once", () => { const spy = jest.fn(); const form = signupForm().onError(spy); form.validate(); // 1st trigger form.reset(); // 2nd triggter const expected = { username: "", name: "", password: "", confirmPassword: "", }; expect(form.error).toEqual(expected); expect(spy.mock.calls.length).toEqual(2); }); }); describe("form.triggerOnChange", () => { it("calls callback with value", () => { const spy = jest.fn(); const form = signupForm().onChange(spy); const data = { username: "ausername", password: "", name: "", confirmPassword: "", }; form.setValue(data); form.triggerOnChange(); expect(spy.mock.calls.length).toEqual(2); expect(spy.mock.calls[1]).toEqual([data]); }); it("won't call onChange callback if 'getNotified' is false", () => { const spy = jest.fn(); const form = signupForm().onChange(spy); form.setValue({ username: "ausername", password: "", name: "", confirmPassword: "", }); form.toggleGetNotified(); form.triggerOnChange(); expect(spy.mock.calls.length).toEqual(1); }); }); describe("form.triggerOnError", () => { it("calls callback with value and form instance", () => { const spy = jest.fn(); const form = signupForm().onError(spy); const errors = { username: "an error", name: "", password: "", confirmPassword: "", }; form.setError(errors); form.triggerOnError(); expect(spy.mock.calls.length).toEqual(2); expect(spy.mock.calls[1]).toEqual([errors]); }); it("won't call onError callback if 'getNotified' is false", () => { const spy = jest.fn(); const form = signupForm().onError(spy); form.validate(); form.toggleGetNotified(); form.triggerOnError(); expect(spy.mock.calls.length).toEqual(1); }); });