From b8881d0559b9fa1865abb75bc7db9810f03ad738 Mon Sep 17 00:00:00 2001 From: Robert Kuykendall Date: Sat, 15 Feb 2020 17:37:43 -0500 Subject: [PATCH] Improve test coverage (#378) * Improve test coverage * Add expectIsValid utility * Cover all validators * Fix typing on Validation spec * 100% * Work on linting and typing * Fix sort * Revert dist --- .eslintrc | 12 +- API.md | 2 +- __test_utils__/TestInput.tsx | 2 +- __test_utils__/expectIsValid.tsx | 30 +++++ __test_utils__/getInput.ts | 10 ++ __tests__/Element-spec.tsx | 62 +++++---- __tests__/Formsy-spec.tsx | 161 ++++++++++++++++++++---- __tests__/Rules-equals-spec.tsx | 44 ++----- __tests__/Rules-equalsField-spec.tsx | 49 ++++++++ __tests__/Rules-isAlpha-spec.tsx | 48 ++----- __tests__/Rules-isAlphanumeric-spec.tsx | 53 ++------ __tests__/Rules-isEmail-spec.tsx | 52 ++------ __tests__/Rules-isEmptyString-spec.tsx | 48 ++----- __tests__/Rules-isExisty-spec.tsx | 48 ++----- __tests__/Rules-isFalse-spec.tsx | 41 ++++++ __tests__/Rules-isFloat-spec.tsx | 64 ++-------- __tests__/Rules-isInt-spec.tsx | 64 ++-------- __tests__/Rules-isLength-spec.tsx | 84 +++---------- __tests__/Rules-isNumeric-spec.tsx | 64 ++-------- __tests__/Rules-isSpecialWords-spec.tsx | 39 ++++++ __tests__/Rules-isTrue-spec.tsx | 41 ++++++ __tests__/Rules-isUndefined-spec.tsx | 33 +++++ __tests__/Rules-isUrl-spec.tsx | 48 ++----- __tests__/Rules-isWords-spec.tsx | 54 ++------ __tests__/Rules-maxLength-spec.tsx | 52 ++------ __tests__/Rules-minLength-spec.tsx | 72 +++-------- __tests__/Utils-spec.tsx | 121 ++++++++++++++---- __tests__/Validation-spec.tsx | 158 ++++++++++++----------- package.json | 2 +- rollup.config.js | 21 ++-- src/Wrapper.ts | 57 +++++---- src/index.ts | 8 +- src/interfaces.ts | 1 - src/validationRules.ts | 6 +- 34 files changed, 807 insertions(+), 844 deletions(-) create mode 100644 __test_utils__/expectIsValid.tsx create mode 100644 __test_utils__/getInput.ts create mode 100644 __tests__/Rules-equalsField-spec.tsx create mode 100644 __tests__/Rules-isFalse-spec.tsx create mode 100644 __tests__/Rules-isSpecialWords-spec.tsx create mode 100644 __tests__/Rules-isTrue-spec.tsx create mode 100644 __tests__/Rules-isUndefined-spec.tsx diff --git a/.eslintrc b/.eslintrc index a214e0a0..86954f48 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,4 +1,9 @@ { + "ignorePatterns": [ + "dist/", + "node_modules/", + "coverage/" + ], "extends": [ "airbnb", "eslint:recommended", @@ -17,9 +22,14 @@ "@typescript-eslint/explicit-function-return-type": 0, "@typescript-eslint/no-explicit-any": 0, "import/extensions": 0, - "import/no-extraneous-dependencies": ["error", {"devDependencies": ["setupTests.ts", "**/*spec.tsx"]}], + "import/no-extraneous-dependencies": [ + "error", { + "devDependencies": ["rollup.config.js", "setupTests.ts", "__tests__/*", "__test_utils__/*"] + } + ], "prettier/prettier": ["error", { "singleQuote": true }], "react/forbid-prop-types": 0, + "react/jsx-filename-extension": 0, "react/static-property-placement": 0 }, "settings": { diff --git a/API.md b/API.md index 92c2d464..a1cdf827 100644 --- a/API.md +++ b/API.md @@ -778,7 +778,7 @@ Returns true if the value is not undefined or null ``` -Returns true if the value is the undefined +Returns true if the value is undefined **isEmptyString** diff --git a/__test_utils__/TestInput.tsx b/__test_utils__/TestInput.tsx index e5e29065..45e40c84 100644 --- a/__test_utils__/TestInput.tsx +++ b/__test_utils__/TestInput.tsx @@ -12,7 +12,7 @@ class TestInput extends React.Component { }; render() { - return ; + return ; } } diff --git a/__test_utils__/expectIsValid.tsx b/__test_utils__/expectIsValid.tsx new file mode 100644 index 00000000..96faa206 --- /dev/null +++ b/__test_utils__/expectIsValid.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { mount } from 'enzyme'; + +import Formsy from '../src'; +import { InputFactory } from './TestInput'; +import { getInputInstance } from './getInput'; + +const TestInput = InputFactory({ + render() { + return ; + }, +}); + +function ValidationForm(props: { validations: string; value?: any }) { + const { validations, value } = props; + + return ( + + + + ); +} + +export function expectIsValid(testForm: React.ComponentElement) { + const form = mount(testForm); + const inputComponent = form.find(TestInput); + return expect(getInputInstance(inputComponent).isValid()); +} + +export default ValidationForm; diff --git a/__test_utils__/getInput.ts b/__test_utils__/getInput.ts new file mode 100644 index 00000000..c0edf059 --- /dev/null +++ b/__test_utils__/getInput.ts @@ -0,0 +1,10 @@ +import { WrapperInstanceMethods } from '../src/Wrapper'; +import Formsy from '../src'; + +export function getInputInstance(inputComponent) { + return inputComponent.instance() as WrapperInstanceMethods; +} + +export function getFormInstance(formComponent) { + return formComponent.instance() as Formsy; +} diff --git a/__tests__/Element-spec.tsx b/__tests__/Element-spec.tsx index d0e08ee3..4543b583 100644 --- a/__tests__/Element-spec.tsx +++ b/__tests__/Element-spec.tsx @@ -25,14 +25,15 @@ describe('Element', () => { updateValue = event => { this.props.setValue(event.target.value, false); }; + render() { - return ; + return ; } }, ); const form = mount( - + , ); const inputComponent = form.find(Input); @@ -302,7 +303,7 @@ describe('Element', () => { ).toEqual(false); }); - it('should not override error messages with error messages passed by form if passed eror messages is an empty object', () => { + it('should not override error messages with error messages passed by form if passed error messages is an empty object', () => { class TestForm extends React.Component { render() { return ( @@ -326,6 +327,40 @@ describe('Element', () => { expect(inputComponent.instance().getErrorMessage()).toEqual('bar3'); }); + it('should handle multiple validation error messages passed from validators', () => { + function customValidationA() { + return 'error message one'; + } + + function customValidationB() { + return 'error message two'; + } + + function TestForm() { + return ( + + + + ); + } + + const form = mount(); + const inputComponent = form.find(TestInput); + + const formEl = form.find('form'); + formEl.simulate('submit'); + + expect(inputComponent.instance().getErrorMessage()).toEqual('error message one'); + expect(inputComponent.instance().getErrorMessages()).toEqual(['error message one', 'error message two']); + }); + it('should override all error messages with error messages passed by form', () => { class TestForm extends React.Component { render() { @@ -511,6 +546,7 @@ describe('Element', () => { } const form = mount(); + // TODO: Beef up this smoke test expect(true).toBe(true); const formEl = form.find('form'); @@ -533,6 +569,7 @@ describe('Element', () => { } const form = mount(); + // TODO: Beef up this smoke test expect(true).toBe(true); const formEl = form.find('form'); @@ -589,25 +626,6 @@ describe('Element', () => { expect(renderSpy.calledTwice).toEqual(true); }); - it('binds all necessary methods', () => { - const onInputRef = input => { - ['isValidValue', 'resetValue', 'setValidations', 'setValue'].forEach(fnName => { - const fn = input[fnName]; - try { - fn(); - } catch (e) { - throw new Error(`Method '${fnName}' isn't bound.`); - } - }); - }; - - mount( - - - , - ); - }); - it('unregisters on unmount', () => { const TestComponent = ({ hasInput }) => {hasInput ? : null}; diff --git a/__tests__/Formsy-spec.tsx b/__tests__/Formsy-spec.tsx index b7c8a1a2..7eed1167 100755 --- a/__tests__/Formsy-spec.tsx +++ b/__tests__/Formsy-spec.tsx @@ -1,3 +1,4 @@ +/* eslint-disable max-classes-per-file */ import { mount } from 'enzyme'; import * as React from 'react'; import DynamicInputForm from '../__test_utils__/DynamicInputForm'; @@ -9,6 +10,8 @@ import Formsy, { addValidationRule } from '../src'; describe('Setting up a form', () => { it('should expose the users DOM node through an innerRef prop', () => { class TestForm extends React.Component { + public inputRef: typeof TestInputHoc; + render() { return ( @@ -24,34 +27,36 @@ describe('Setting up a form', () => { } const form = mount(); - const input = form.instance().inputRef; + const input = (form.instance() as TestForm).inputRef; expect(input.props.name).toEqual('name'); }); it('should render a form into the document', () => { - const form = mount(); + const form = mount(); expect(form.find('form').name()).toEqual('form'); }); it('should set a class name if passed', () => { - const form = mount(); + const form = mount(); expect(form.find('form').hasClass('foo')).toBe(true); }); it('should allow for null/undefined children', () => { let model = null; - class TestForm extends React.Component { - render() { - return ( - (model = formModel)}> -

Test

- {null} - {undefined} - -
- ); - } + function TestForm() { + return ( + { + model = formModel; + }} + > +

Test

+ {null} + {undefined} + +
+ ); } const form = mount(); @@ -62,7 +67,14 @@ describe('Setting up a form', () => { it('should allow for inputs being added dynamically', () => { let model = null; - const form = mount( (model = formModel)} inputName="test" />); + const form = mount( + { + model = formModel; + }} + inputName="test" + />, + ); form.find('button').simulate('click'); form.update(); @@ -73,7 +85,14 @@ describe('Setting up a form', () => { it('should allow dynamically added inputs to update the form-model', () => { let model = null; - const form = mount( (model = formModel)} inputName="test" />); + const form = mount( + { + model = formModel; + }} + inputName="test" + />, + ); form.find('button').simulate('click'); form.update(); @@ -87,22 +106,29 @@ describe('Setting up a form', () => { it('should allow a dynamically updated input to update the form-model', () => { let model = null; - class TestForm extends React.Component { - public state = { - inputValue: this.props.inputValue, - }; + class TestForm extends React.Component<{ inputValue: any }, { inputValue: any }> { + constructor(props) { + super(props); + this.state = { inputValue: props.inputValue }; + } + + updateInputValue = () => this.setState({ inputValue: 'bar' }); render() { const { inputValue } = this.state; return ( - (model = formModel)}> + { + model = formModel; + }} + > - ); } - - updateInputValue = () => this.setState({ inputValue: 'bar' }); } const form = mount(); @@ -120,6 +146,34 @@ describe('Setting up a form', () => { }); }); +describe('mapModel', () => { + it('should honor mapModel transformations', () => { + const mapping = jest.fn(model => ({ + ...model, + testChange: true, + })); + const onSubmit = jest.fn(); + + function TestForm() { + return ( + + + + ); + } + + const form = mount(); + + form.simulate('submit'); + expect(mapping).toHaveBeenCalledWith({ 'parent.child': 'test' }); + expect(onSubmit).toHaveBeenCalledWith( + { 'parent.child': 'test', testChange: true }, + expect.any(Function), + expect.any(Function), + ); + }); +}); + describe('validations', () => { it('should run when the input changes', () => { const runRule = jest.fn(); @@ -276,7 +330,7 @@ describe('onChange', () => { class TestForm extends React.Component { render() { - return ; + return ; } } @@ -380,6 +434,7 @@ describe('Update a form', () => { it('should be possible to pass error state of elements by changing an errors attribute', () => { class TestForm extends React.Component { state = { validationErrors: { foo: 'bar' } }; + onChange = values => { this.setState(values.foo ? { validationErrors: {} } : { validationErrors: { foo: 'bar' } }); }; @@ -497,7 +552,7 @@ describe('value === false', () => { render() { return ( - + ); @@ -649,6 +704,27 @@ describe('.reset()', () => { }); expect(input.instance().getValue()).toEqual(''); }); + + it('should be able to reset the form using a button', () => { + function TestForm() { + return ( + + + + + ); + } + + const form = mount(); + const input = form.find(TestInput); + const formsyForm = form.find(Formsy); + + expect(input.instance().getValue()).toEqual('foo'); + input.simulate('change', { target: { value: 'foobar' } }); + expect(input.instance().getValue()).toEqual('foobar'); + formsyForm.simulate('reset'); + expect(input.instance().getValue()).toEqual('foo'); + }); }); describe('.isChanged()', () => { @@ -708,9 +784,11 @@ describe('form valid state', () => { onValidSubmit = (model, reset, updateInputsWithError) => { updateInputsWithError({ foo: 'bar' }, true); }; + onValid = () => { isValid = true; }; + onInvalid = () => { isValid = false; }; @@ -732,17 +810,45 @@ describe('form valid state', () => { expect(isValid).toEqual(false); }); + it('should throw an error when updateInputsWithError is called with a missing input', () => { + const mockConsoleError = jest.spyOn(console, 'error'); + mockConsoleError.mockImplementation(() => { + // do nothing + }); + + class TestForm extends React.Component { + onValidSubmit = (model, reset, updateInputsWithError) => { + updateInputsWithError({ bar: 'bar' }, true); + }; + + render() { + return ( + + + + ); + } + } + + const form = mount(); + expect(() => form.simulate('submit')).toThrow(); + mockConsoleError.mockRestore(); + }); + it('should be false when validationErrors is not empty', () => { let isValid = true; class TestForm extends React.Component { state = { validationErrors: {} }; + setValidationErrors = empty => { this.setState(!empty ? { validationErrors: { foo: 'bar' } } : { validationErrors: {} }); }; + onValid = () => { isValid = true; }; + onInvalid = () => { isValid = false; }; @@ -768,12 +874,15 @@ describe('form valid state', () => { let isValid = true; class TestForm extends React.Component { state = { validationErrors: {} }; + setValidationErrors = empty => { this.setState(!empty ? { validationErrors: { foo: 'bar' } } : { validationErrors: {} }); }; + onValid = () => { isValid = true; }; + onInvalid = () => { isValid = false; }; diff --git a/__tests__/Rules-equals-spec.tsx b/__tests__/Rules-equals-spec.tsx index 37eef610..37fde553 100644 --- a/__tests__/Rules-equals-spec.tsx +++ b/__tests__/Rules-equals-spec.tsx @@ -1,59 +1,29 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render: function() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('equals', () => { it('should pass when the value is equal', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail when the value is not equal', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with an empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); }); diff --git a/__tests__/Rules-equalsField-spec.tsx b/__tests__/Rules-equalsField-spec.tsx new file mode 100644 index 00000000..2300d4d5 --- /dev/null +++ b/__tests__/Rules-equalsField-spec.tsx @@ -0,0 +1,49 @@ +import React from 'react'; + +import Formsy from '../src'; +import TestInput from '../__test_utils__/TestInput'; +import { mount } from 'enzyme'; + +function ValidationForm(props: { validations: string; value?: any; other?: any }) { + const { validations, value, other } = props; + + return ( + + + + + ); +} + +export function expectIsValid(testForm: React.ComponentElement) { + const form = mount(testForm); + const inputComponent = form.find(TestInput).first(); + return expect(inputComponent.instance().isValid()); +} + +describe('equalsField', () => { + it('should pass when the value is equal', () => { + expectIsValid().toEqual(true); + }); + + it('should fail when the value is not equal', () => { + expectIsValid().toEqual(false); + }); + + it('should pass with an empty string', () => { + expectIsValid().toEqual(true); + }); + + it('should pass with an undefined', () => { + expectIsValid().toEqual(true); + }); + + it('should pass with a null', () => { + expectIsValid().toEqual(true); + }); + + it('should work with a number', () => { + expectIsValid().toEqual(true); + expectIsValid().toEqual(false); + }); +}); diff --git a/__tests__/Rules-isAlpha-spec.tsx b/__tests__/Rules-isAlpha-spec.tsx index 2ba6b2fb..663da8f1 100644 --- a/__tests__/Rules-isAlpha-spec.tsx +++ b/__tests__/Rules-isAlpha-spec.tsx @@ -1,65 +1,33 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render: function() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('isAlpha', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a string is only latin letters', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a string with numbers', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with an undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); }); diff --git a/__tests__/Rules-isAlphanumeric-spec.tsx b/__tests__/Rules-isAlphanumeric-spec.tsx index f0731506..d81053ea 100644 --- a/__tests__/Rules-isAlphanumeric-spec.tsx +++ b/__tests__/Rules-isAlphanumeric-spec.tsx @@ -1,72 +1,37 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('isAlphanumeric', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a string is only latin letters', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a string with numbers', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a non alpha and number symbols', () => { - const value = '!@#$%^&*()'; - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); }); diff --git a/__tests__/Rules-isEmail-spec.tsx b/__tests__/Rules-isEmail-spec.tsx index 3c4d4412..a7d902e9 100644 --- a/__tests__/Rules-isEmail-spec.tsx +++ b/__tests__/Rules-isEmail-spec.tsx @@ -1,71 +1,37 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('isEmail', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with "foo"', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with "foo@foo.com"', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with new long domains', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); }); diff --git a/__tests__/Rules-isEmptyString-spec.tsx b/__tests__/Rules-isEmptyString-spec.tsx index 81e28a14..d82330e0 100644 --- a/__tests__/Rules-isEmptyString-spec.tsx +++ b/__tests__/Rules-isEmptyString-spec.tsx @@ -1,65 +1,33 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component<{ inputValue?: any }> { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('isEmptyString', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should fail with non-empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with an empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should fail with null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should fail with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should fail with a zero', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); }); diff --git a/__tests__/Rules-isExisty-spec.tsx b/__tests__/Rules-isExisty-spec.tsx index ae7f4e71..2debcb0f 100644 --- a/__tests__/Rules-isExisty-spec.tsx +++ b/__tests__/Rules-isExisty-spec.tsx @@ -1,65 +1,33 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('isExisty', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with a string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should fail with null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a zero', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); }); diff --git a/__tests__/Rules-isFalse-spec.tsx b/__tests__/Rules-isFalse-spec.tsx new file mode 100644 index 00000000..9c7f2d94 --- /dev/null +++ b/__tests__/Rules-isFalse-spec.tsx @@ -0,0 +1,41 @@ +import React from 'react'; + +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; + +describe('isFalse', () => { + it('should fail with a default value', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with boolean false', () => { + expectIsValid().toEqual(true); + }); + + it('should pass with boolean true', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with a string', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with an empty string', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with undefined', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with null', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with a number', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with a zero', () => { + expectIsValid().toEqual(false); + }); +}); diff --git a/__tests__/Rules-isFloat-spec.tsx b/__tests__/Rules-isFloat-spec.tsx index e029b972..df99cd8c 100644 --- a/__tests__/Rules-isFloat-spec.tsx +++ b/__tests__/Rules-isFloat-spec.tsx @@ -1,89 +1,49 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('isFloat', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with a number as string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail string with digits', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with an int', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a float', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a float in science notation', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a zero', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); }); diff --git a/__tests__/Rules-isInt-spec.tsx b/__tests__/Rules-isInt-spec.tsx index 6b2d7e2c..51948418 100644 --- a/__tests__/Rules-isInt-spec.tsx +++ b/__tests__/Rules-isInt-spec.tsx @@ -1,89 +1,49 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('isInt', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with a number as string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail string with digits', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with an int', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a float', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should fail with a float in science notation', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a zero', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); }); diff --git a/__tests__/Rules-isLength-spec.tsx b/__tests__/Rules-isLength-spec.tsx index 94c741be..9ea89e1e 100644 --- a/__tests__/Rules-isLength-spec.tsx +++ b/__tests__/Rules-isLength-spec.tsx @@ -1,121 +1,71 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('isLength:3', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a string too small', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should fail with a string too long', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with matching length', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); }); describe('isLength:0', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a string too small', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should fail with a string too long', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with matching length', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); }); diff --git a/__tests__/Rules-isNumeric-spec.tsx b/__tests__/Rules-isNumeric-spec.tsx index 34f49024..ddf0d004 100644 --- a/__tests__/Rules-isNumeric-spec.tsx +++ b/__tests__/Rules-isNumeric-spec.tsx @@ -1,89 +1,49 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('isNumeric', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with an unempty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with a number as string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a number as string with not digits', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with an int', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a float', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a float in science notation', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with an undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a zero', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); }); diff --git a/__tests__/Rules-isSpecialWords-spec.tsx b/__tests__/Rules-isSpecialWords-spec.tsx new file mode 100644 index 00000000..bc57fda6 --- /dev/null +++ b/__tests__/Rules-isSpecialWords-spec.tsx @@ -0,0 +1,39 @@ +import React from 'react'; + +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; + +describe('isSpecialWords', () => { + it('should pass with a default value', () => { + expectIsValid().toEqual(true); + }); + + it('should pass with a 1 word', () => { + expectIsValid().toEqual(true); + }); + + it('should pass with 2 words', () => { + expectIsValid().toEqual(true); + }); + + it('should pass with special charachters', () => { + expectIsValid().toEqual( + true, + ); + }); + + it('should fail with a string with numbers', () => { + expectIsValid().toEqual(false); + }); + + it('should pass with an undefined', () => { + expectIsValid().toEqual(true); + }); + + it('should pass with a null', () => { + expectIsValid().toEqual(true); + }); + + it('should fail with a number', () => { + expectIsValid().toEqual(false); + }); +}); diff --git a/__tests__/Rules-isTrue-spec.tsx b/__tests__/Rules-isTrue-spec.tsx new file mode 100644 index 00000000..1a04e14a --- /dev/null +++ b/__tests__/Rules-isTrue-spec.tsx @@ -0,0 +1,41 @@ +import React from 'react'; + +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; + +describe('isTrue', () => { + it('should fail with a default value', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with boolean false', () => { + expectIsValid().toEqual(false); + }); + + it('should pass with boolean true', () => { + expectIsValid().toEqual(true); + }); + + it('should fail with a string', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with an empty string', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with undefined', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with null', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with a number', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with a zero', () => { + expectIsValid().toEqual(false); + }); +}); diff --git a/__tests__/Rules-isUndefined-spec.tsx b/__tests__/Rules-isUndefined-spec.tsx new file mode 100644 index 00000000..c989ce4d --- /dev/null +++ b/__tests__/Rules-isUndefined-spec.tsx @@ -0,0 +1,33 @@ +import React from 'react'; + +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; + +describe('isUndefined', () => { + it('should pass with a default value', () => { + expectIsValid().toEqual(true); + }); + + it('should fail with a string', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with an empty string', () => { + expectIsValid().toEqual(false); + }); + + it('should pass with undefined', () => { + expectIsValid().toEqual(true); + }); + + it('should fail with null', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with a number', () => { + expectIsValid().toEqual(false); + }); + + it('should fail with a zero', () => { + expectIsValid().toEqual(false); + }); +}); diff --git a/__tests__/Rules-isUrl-spec.tsx b/__tests__/Rules-isUrl-spec.tsx index 6efd06c6..da3838bf 100644 --- a/__tests__/Rules-isUrl-spec.tsx +++ b/__tests__/Rules-isUrl-spec.tsx @@ -1,65 +1,33 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('isUrl', () => { it('should pass with default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with "foo"', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with "https://www.google.com/"', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with an empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); }); diff --git a/__tests__/Rules-isWords-spec.tsx b/__tests__/Rules-isWords-spec.tsx index 331a2a1c..7c3553b0 100644 --- a/__tests__/Rules-isWords-spec.tsx +++ b/__tests__/Rules-isWords-spec.tsx @@ -1,65 +1,37 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} - -describe('isWord', () => { +describe('isWords', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a 1 word', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with 2 words', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); + }); + + it('should fail with special charachters', () => { + expectIsValid().toEqual(false); }); it('should fail with a string with numbers', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with an undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); }); diff --git a/__tests__/Rules-maxLength-spec.tsx b/__tests__/Rules-maxLength-spec.tsx index 167d89b9..94bde0d4 100644 --- a/__tests__/Rules-maxLength-spec.tsx +++ b/__tests__/Rules-maxLength-spec.tsx @@ -1,71 +1,37 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('maxLength', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it("should pass when a string's length is smaller", () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it("should pass when a string's length is equal", () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it("should fail when a string's length is bigger", () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); }); diff --git a/__tests__/Rules-minLength-spec.tsx b/__tests__/Rules-minLength-spec.tsx index e900f5c3..8ea98014 100644 --- a/__tests__/Rules-minLength-spec.tsx +++ b/__tests__/Rules-minLength-spec.tsx @@ -1,103 +1,59 @@ import React from 'react'; -import { mount } from 'enzyme'; -import Formsy from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; - -const TestInput = InputFactory({ - render() { - return ; - }, -}); - -class TestForm extends React.Component { - render() { - return ( - - - - ); - } -} +import ValidationForm, { expectIsValid } from '../__test_utils__/expectIsValid'; describe('minLength:3', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it("should pass when a string's length is bigger", () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it("should fail when a string's length is smaller", () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); it('should pass with empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); }); describe('minLength:0', () => { it('should pass with a default value', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it("should pass when a string's length is bigger", () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with empty string', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with an undefined', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should pass with a null', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(true); + expectIsValid().toEqual(true); }); it('should fail with a number', () => { - const form = mount(); - const inputComponent = form.find(TestInput); - expect(inputComponent.instance().isValid()).toEqual(false); + expectIsValid().toEqual(false); }); }); diff --git a/__tests__/Utils-spec.tsx b/__tests__/Utils-spec.tsx index e1f165a5..e1820abd 100644 --- a/__tests__/Utils-spec.tsx +++ b/__tests__/Utils-spec.tsx @@ -1,31 +1,100 @@ import * as utils from '../src/utils'; +const VALUES = [ + undefined, + null, + '', + 0, + 100, + 'Hello', + 'Goodbye', + { foo: 'bar' }, + { foo: 'lounge' }, + [{ foo: ['bar'] }], + [{ foo: [] }], + ['a', 7], + ['a', 8], + ['a', 7, 7], + new Date(1000), + new Date(2000), + () => 2 + 2, + () => 2 + 3, + utils.noop, +]; + +function getReadable(value, index) { + return `${typeof value} at ${index}`; +} + describe('Utils', () => { - it('should check equality of objects and arrays', () => { - const objA = { foo: 'bar' }; - const objB = { foo: 'bar' }; - const objC = [{ foo: ['bar'] }]; - const objD = [{ foo: ['bar'] }]; - const objE = undefined; - const objF = undefined; - const objG = null; - const objH = null; - - expect(utils.isSame(objA, objB)).toBe(true); - expect(utils.isSame(objC, objD)).toBe(true); - expect(utils.isSame(objA, objD)).toBe(false); - - expect(utils.isSame(objE, objF)).toBe(true); - expect(utils.isSame(objA, objF)).toBe(false); - expect(utils.isSame(objE, objA)).toBe(false); - - expect(utils.isSame(objG, objH)).toBe(true); - expect(utils.isSame(objA, objH)).toBe(false); - expect(utils.isSame(objC, objH)).toBe(false); - expect(utils.isSame(objG, objA)).toBe(false); - - expect(utils.isSame(utils.noop, utils.noop)).toBe(true); - expect(utils.isSame(objA, utils.noop)).toBe(false); - expect(utils.isSame(utils.noop, objA)).toBe(false); + // For every value in values, run isSame(a, b) with every other value in the array. + // Expect isSame to return true only if you are at the same point in the array. + VALUES.forEach((a, idxa) => { + VALUES.forEach((b, idxb) => { + const isSame = idxa === idxb; + + it(`isSame: ${getReadable(a, idxa)} ${isSame ? '==' : '!='} ${getReadable(b, idxb)}`, () => { + expect(utils.isSame(a, b)).toBe(isSame); + }); + }); + }); + + it('runRules', () => { + expect(utils.runRules('', {}, {}, {})).toEqual({ errors: [], failed: [], success: [] }); + + expect(() => utils.runRules('', {}, { rule: utils.noop }, { rule: utils.noop })).toThrow( + 'Formsy does not allow you to override default validations: rule', + ); + + expect(() => utils.runRules('', {}, { rule: true }, {})).toThrow('Formsy does not have the validation rule: rule'); + + expect(utils.runRules('', {}, { rule: () => 'Error' }, {})).toEqual({ + errors: ['Error'], + failed: ['rule'], + success: [], + }); + + // TODO: This fails but should pass + // expect(utils.runRules('', {}, { rule: () => true }, {})).toEqual({ errors: [], failed: [], success: ['rule'] }); + + expect(utils.runRules('', {}, { rule: () => false }, {})).toEqual({ errors: [], failed: ['rule'], success: [] }); + expect(utils.runRules('', {}, { rule: true }, { rule: () => false })).toEqual({ + errors: [], + failed: ['rule'], + success: [], + }); + expect(utils.runRules('', {}, { rule: true }, { rule: () => true })).toEqual({ + errors: [], + failed: [], + success: ['rule'], + }); + expect(utils.runRules('', {}, { rule: false }, { rule: () => false })).toEqual({ + errors: [], + failed: ['rule'], + success: [], + }); + + expect(utils.runRules('', {}, { rule: true }, { rule: (_cv, _v, validationsVal) => validationsVal })).toEqual({ + errors: [], + failed: [], + success: ['rule'], + }); + expect(utils.runRules('', {}, { rule: false }, { rule: (_cv, _v, validationsVal) => validationsVal })).toEqual({ + errors: [], + failed: ['rule'], + success: [], + }); + expect(utils.runRules('', {}, { rule: true }, { rule: (_cv, _v, validationsVal) => 'Error' })).toEqual({ + errors: ['Error'], + failed: ['rule'], + success: [], + }); + + // TODO: What does this even mean? + expect(utils.runRules('', {}, { rule: true }, { rule: true })).toEqual({ + errors: [], + failed: [], + success: ['rule'], + }); }); }); diff --git a/__tests__/Validation-spec.tsx b/__tests__/Validation-spec.tsx index b131d953..356b45a0 100644 --- a/__tests__/Validation-spec.tsx +++ b/__tests__/Validation-spec.tsx @@ -3,21 +3,25 @@ import sinon from 'sinon'; import { mount } from 'enzyme'; import Formsy, { withFormsy } from '../src'; -import { InputFactory } from '../__test_utils__/TestInput'; import immediate from '../__test_utils__/immediate'; +import { InputFactory } from '../__test_utils__/TestInput'; +import { PassDownProps } from '../src/Wrapper'; +import { getFormInstance, getInputInstance } from '../__test_utils__/getInput'; -class MyTest extends React.Component { - static defaultProps = { type: 'text' }; +class MyTest extends React.Component<{ type?: string } & PassDownProps> { + public static defaultProps = { type: 'text' }; handleChange = event => { - this.props.setValue(event.target.value); + const { setValue } = this.props; + setValue(event.target.value); }; render() { - return ; + const { type, value } = this.props; + return ; } } -const FormsyTest = withFormsy(MyTest); +const FormsyTest = withFormsy<{ type?: string }, string>(MyTest); describe('Validation', () => { it('should reset only changed form element when external error is passed', () => { @@ -31,34 +35,14 @@ describe('Validation', () => { const input = form.find('input').at(0); const inputComponents = form.find(FormsyTest); - form.instance().submit(); - expect( - inputComponents - .at(0) - .instance() - .isValid(), - ).toEqual(false); - expect( - inputComponents - .at(1) - .instance() - .isValid(), - ).toEqual(false); + getFormInstance(form).submit(); + expect(getInputInstance(inputComponents.at(0)).isValid()).toEqual(false); + expect(getInputInstance(inputComponents.at(1)).isValid()).toEqual(false); input.simulate('change', { target: { value: 'bar' } }); immediate(() => { - expect( - inputComponents - .at(0) - .instance() - .isValid(), - ).toEqual(true); - expect( - inputComponents - .at(1) - .instance() - .isValid(), - ).toEqual(false); + expect(getInputInstance(inputComponents.at(0)).isValid()).toEqual(true); + expect(getInputInstance(inputComponents).isValid()).toEqual(false); }); }); @@ -72,13 +56,13 @@ describe('Validation', () => { const input = form.find('input'); const inputComponent = form.find(FormsyTest); - form.instance().submit(); - expect(inputComponent.instance().isValid()).toEqual(false); + getFormInstance(form).submit(); + expect(getInputInstance(inputComponent).isValid()).toEqual(false); input.simulate('change', { target: { value: 'bar' } }); immediate(() => { - expect(inputComponent.getValue()).toEqual('bar'); - expect(inputComponent.instance().isValid()).toEqual(false); + expect(getInputInstance(inputComponent).getValue()).toEqual('bar'); + expect(getInputInstance(inputComponent).isValid()).toEqual(false); }); }); @@ -141,14 +125,12 @@ describe('Validation', () => { }); it('should provide invalidate callback on onValidSubmit', () => { - class TestForm extends React.Component { - render() { - return ( - invalidate({ foo: 'bar' })}> - - - ); - } + function TestForm() { + return ( + invalidate({ foo: 'bar' })}> + + + ); } const form = mount(); @@ -156,60 +138,94 @@ describe('Validation', () => { const formEl = form.find('form'); const input = form.find(FormsyTest); formEl.simulate('submit'); - expect(input.instance().isValid()).toEqual(false); + expect(getInputInstance(input).isValid()).toEqual(false); }); it('should provide invalidate callback on onInvalidSubmit', () => { - class TestForm extends React.Component { - render() { - return ( - invalidate({ foo: 'bar' })}> - - - ); - } + function TestForm() { + return ( + invalidate({ foo: 'bar' })}> + + + ); } const form = mount(); const formEl = form.find('form'); const input = form.find(FormsyTest); formEl.simulate('submit'); - expect(input.instance().getErrorMessage()).toEqual('bar'); + expect(getInputInstance(input).getErrorMessage()).toEqual('bar'); }); it('should not invalidate inputs on external errors with preventExternalInvalidation prop', () => { - class TestForm extends React.Component { - render() { - return ( - invalidate({ foo: 'bar' })}> - - - ); - } + function TestForm() { + return ( + invalidate({ foo: 'bar' })}> + + + ); } const form = mount(); const formEl = form.find('form'); const input = form.find(FormsyTest); formEl.simulate('submit'); - expect(input.instance().isValid()).toEqual(true); + expect(getInputInstance(input).isValid()).toEqual(true); }); it('should invalidate inputs on external errors without preventExternalInvalidation prop', () => { - class TestForm extends React.Component { - render() { - return ( - invalidate({ foo: 'bar' })}> - - - ); - } + function TestForm() { + return ( + invalidate({ foo: 'bar' })}> + + + ); } const form = mount(); const formEl = form.find('form'); const input = form.find(FormsyTest); formEl.simulate('submit'); - expect(input.instance().isValid()).toEqual(false); + expect(getInputInstance(input).isValid()).toEqual(false); + }); + + it('should throw errors on invalid validation string', () => { + const mockConsoleError = jest.spyOn(console, 'error'); + mockConsoleError.mockImplementation(() => { + // do nothing + }); + + function TestForm() { + return ( + invalidate({ foo: 'bar' })}> + + + ); + } + + expect(() => mount()).toThrow( + 'Formsy does not support multiple args on string validations. Use object format of validations instead.', + ); + + mockConsoleError.mockRestore(); + }); + + it('should throw errors on missing input name', () => { + const mockConsoleError = jest.spyOn(console, 'error'); + mockConsoleError.mockImplementation(() => { + // do nothing + }); + + function TestForm() { + return ( + invalidate({ foo: 'bar' })}> + + + ); + } + + expect(() => mount()).toThrow('Form Input requires a name property when used'); + + mockConsoleError.mockRestore(); }); }); diff --git a/package.json b/package.json index 6b93c59e..5046196b 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "changelog": "auto-changelog", "deploy": "np", "format": "prettier --write \"**/*.{js,jsx,ts,tsx,md}\"", - "lint": "eslint src/**/*", + "lint": "eslint .", "preversion": "npm run lint", "test": "jest", "version": "npm run build && git add dist && npm run changelog && git add CHANGELOG.md" diff --git a/rollup.config.js b/rollup.config.js index 8e423aee..4a630a56 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -6,16 +6,17 @@ import peerDepsExternal from 'rollup-plugin-peer-deps-external'; import pkg from './package.json'; -const name = 'formsy-react', - input = 'src/index.ts', - extensions = ['.js', '.ts'], - babelConfig = { - ...babelrc({ addExternalHelpersPlugin: false }), - exclude: 'node_modules/**', - extensions, - }, - common = { exports: 'named', sourcemap: true }, - plugins = [peerDepsExternal(), resolve({ extensions }), babel(babelConfig), commonjs()]; +const name = 'formsy-react'; +const input = 'src/index.ts'; +const extensions = ['.js', '.ts']; +const babelConfig = { + ...babelrc({ addExternalHelpersPlugin: false }), + exclude: 'node_modules/**', + extensions, +}; +const common = { exports: 'named', sourcemap: true }; +const plugins = [peerDepsExternal(), resolve({ extensions }), babel(babelConfig), commonjs()]; + export default [ // browser-friendly UMD build { diff --git a/src/Wrapper.ts b/src/Wrapper.ts index 41b8af77..29b6b2c9 100644 --- a/src/Wrapper.ts +++ b/src/Wrapper.ts @@ -2,20 +2,16 @@ import React from 'react'; import PropTypes from 'prop-types'; import * as utils from './utils'; -import { RequiredValidation, Validations, WrappedComponentClass } from './interfaces'; import FormsyContext from './FormsyContext'; +import { ComponentWithStaticAttributes, RequiredValidation, Validations, WrappedComponentClass } from './interfaces'; /* eslint-disable react/default-props-match-prop-types */ const convertValidationsToObject = (validations: false | Validations): Validations => { if (typeof validations === 'string') { return validations.split(/,(?![^{[]*[}\]])/g).reduce((validationsAccumulator, validation) => { - let args = validation.split(':'); - const validateMethod = args.shift(); - - if (typeof validateMethod !== 'string') { - throw new Error('Formsy encountered unexpected problem parsing validation string'); - } + let args: string[] = validation.split(':'); + const validateMethod: string = args.shift(); args = args.map(arg => { try { @@ -82,29 +78,31 @@ export interface InjectedProps { isValid: boolean; isValidValue: (value: V) => boolean; ref?: any; - resetValue: any; - setValidations: any; + resetValue: () => void; + setValidations: (validations: Validations, required: RequiredValidation) => void; setValue: (value: V) => void; showError: boolean; showRequired: boolean; } +export interface WrapperInstanceMethods { + isValid: () => boolean; + getValue: () => any; + getErrorMessage: () => any; +} + export type PassDownProps = WrapperProps & InjectedProps; export { propTypes }; function getDisplayName(component: WrappedComponentClass) { - return ( - (component as { displayName?: string }).displayName || - component.name || - (typeof component === 'string' ? component : 'Component') - ); + return component.displayName || component.name || (utils.isString(component) ? component : 'Component'); } export default function( WrappedComponent: React.ComponentType>, ): React.ComponentType, keyof InjectedProps>> { - return class extends React.Component, WrapperState> { + return class extends React.Component, WrapperState> implements WrapperInstanceMethods { // eslint-disable-next-line react/sort-comp public static contextType = FormsyContext; @@ -124,7 +122,7 @@ export default function( validationError: '', validationErrors: {}, validations: null, - value: (WrappedComponent as any).defaultValue, + value: (WrappedComponent as ComponentWithStaticAttributes).defaultValue, }; public constructor(props) { @@ -205,9 +203,9 @@ export default function( }; // eslint-disable-next-line react/destructuring-assignment - public getValue = () => this.state.value; + public getValue = (): V => this.state.value; - public setValidations = (validations: Validations, required: RequiredValidation) => { + public setValidations = (validations: Validations, required: RequiredValidation): void => { // Add validations to the store itself as the props object can not be modified this.validations = convertValidationsToObject(validations) || {}; this.requiredValidations = @@ -216,8 +214,9 @@ export default function( // By default, we validate after the value has been set. // A user can override this and pass a second parameter of `false` to skip validation. - public setValue = (value: any, validate = true) => { + public setValue = (value: V, validate = true): void => { const { validate: validateForm } = this.context; + if (!validate) { this.setState({ value, @@ -245,22 +244,22 @@ export default function( }; // eslint-disable-next-line react/destructuring-assignment - public isFormDisabled = () => this.context.isFormDisabled; + public isFormDisabled = (): boolean => this.context.isFormDisabled; // eslint-disable-next-line react/destructuring-assignment - public isFormSubmitted = () => this.state.formSubmitted; + public isFormSubmitted = (): boolean => this.state.formSubmitted; // eslint-disable-next-line react/destructuring-assignment - public isPristine = () => this.state.isPristine; + public isPristine = (): boolean => this.state.isPristine; // eslint-disable-next-line react/destructuring-assignment - public isRequired = () => !!this.props.required; + public isRequired = (): boolean => !!this.props.required; // eslint-disable-next-line react/destructuring-assignment - public isValid = () => this.state.isValid; + public isValid = (): boolean => this.state.isValid; // eslint-disable-next-line react/destructuring-assignment - public isValidValue = value => this.context.isValidValue(this, value); + public isValidValue = (value: V) => this.context.isValidValue(this, value); public resetValue = () => { const { pristineValue } = this.state; @@ -277,14 +276,14 @@ export default function( ); }; - public showError = () => !this.showRequired() && !this.isValid(); + public showError = (): boolean => !this.showRequired() && !this.isValid(); // eslint-disable-next-line react/destructuring-assignment - public showRequired = () => this.state.isRequired; + public showRequired = (): boolean => this.state.isRequired; public render() { const { innerRef } = this.props; - const propsForElement: PassDownProps = { + const propsForElement: T & PassDownProps = { ...this.props, errorMessage: this.getErrorMessage(), errorMessages: this.getErrorMessages(), @@ -307,7 +306,7 @@ export default function( propsForElement.ref = innerRef; } - return React.createElement(WrappedComponent, propsForElement as any); + return React.createElement(WrappedComponent, propsForElement); } }; } diff --git a/src/index.ts b/src/index.ts index f8c7fa42..7c5d85e7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -256,7 +256,7 @@ class Formsy extends React.Component { // eslint-disable-next-line react/destructuring-assignment public isFormDisabled = () => this.props.disabled; - public mapModel = (model: IModel) => { + public mapModel = (model: IModel): IModel => { const { mapping } = this.props; if (mapping) { @@ -282,7 +282,7 @@ class Formsy extends React.Component { this.resetModel(data); }; - public resetInternal = event => { + private resetInternal = event => { const { onReset } = this.props; event.preventDefault(); @@ -347,6 +347,8 @@ class Formsy extends React.Component { .filter((x, pos, arr) => arr.indexOf(x) === pos); // remove duplicates } + // This line is not reachable + // istanbul ignore next return undefined; })(), }; @@ -378,7 +380,7 @@ class Formsy extends React.Component { public isChanged = () => !utils.isSame(this.getPristineValues(), this.getCurrentValues()); // Update model, submit to url prop and send the model - public submit = event => { + public submit = (event?: any) => { const { onSubmit, onValidSubmit, onInvalidSubmit } = this.props; const { isValid } = this.state; diff --git a/src/interfaces.ts b/src/interfaces.ts index 0fef2a89..256cdbc9 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -23,7 +23,6 @@ export interface ValidationsStructure { export type RequiredValidation = boolean | Validations; export interface ComponentWithStaticAttributes extends ComponentClass { - string?: any; defaultValue?: any; } diff --git a/src/validationRules.ts b/src/validationRules.ts index 3bcc678a..c95b4f82 100644 --- a/src/validationRules.ts +++ b/src/validationRules.ts @@ -1,10 +1,10 @@ import { ValidationFunction, Values } from './interfaces'; import { + isNumber, isString, - isValueStringEmpty, isTypeUndefined, isValueNullOrUndefined, - isNumber, + isValueStringEmpty, isValueUndefined, } from './utils'; @@ -81,7 +81,7 @@ const validations: Validations = { return validations.matchRegexp(values, value, /^[A-Z\s]+$/i); }, isSpecialWords(values: Values, value: V) { - return validations.matchRegexp(values, value, /^[A-Z\s\u00C0-\u017F]+$/i); + return validations.matchRegexp(values, value, /^[\sA-ZÀ-ÖØ-öø-ÿ]+$/i); }, isLength(_values: Values, value: string, length: number) { return !isExisty(value) || isEmpty(value) || value.length === length;