@coxy/react-validator 1.3.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.eslintignore +1 -1
  2. package/.eslintrc.js +25 -8
  3. package/babel.config.js +3 -0
  4. package/dist/context.d.ts +5 -0
  5. package/dist/context.js +5 -0
  6. package/dist/index.d.ts +5 -0
  7. package/dist/index.js +13 -0
  8. package/dist/rules.d.ts +37 -0
  9. package/dist/rules.js +43 -0
  10. package/dist/use-validator.d.ts +3 -0
  11. package/dist/use-validator.js +22 -0
  12. package/dist/validator-field.d.ts +25 -0
  13. package/dist/validator-field.jsx +34 -0
  14. package/dist/validator-wrapper.d.ts +17 -0
  15. package/dist/validator-wrapper.jsx +43 -0
  16. package/dist/validator.d.ts +28 -0
  17. package/dist/validator.js +72 -0
  18. package/example/example.jsx +29 -26
  19. package/example/index.html +2 -0
  20. package/example/webpack.config.js +15 -7
  21. package/jest.config.ts +10 -0
  22. package/package.json +34 -27
  23. package/src/context.test.ts +7 -0
  24. package/src/context.ts +6 -0
  25. package/src/index.test.ts +7 -0
  26. package/src/index.ts +5 -0
  27. package/src/jest.d.ts +1 -0
  28. package/src/rules.test.ts +127 -0
  29. package/src/{rules.js → rules.ts} +26 -15
  30. package/src/use-validator.test.tsx +58 -0
  31. package/src/use-validator.ts +10 -0
  32. package/src/validator-field.test.tsx +161 -0
  33. package/src/validator-field.tsx +71 -0
  34. package/src/validator-wrapper.test.tsx +138 -0
  35. package/src/validator-wrapper.tsx +58 -0
  36. package/src/validator.test.tsx +30 -0
  37. package/src/validator.ts +105 -0
  38. package/tsconfig.build.json +12 -0
  39. package/tsconfig.json +39 -0
  40. package/.babelrc.js +0 -14
  41. package/build/index.js +0 -1
  42. package/jest.config.js +0 -5
  43. package/src/context.js +0 -3
  44. package/src/context.test.js +0 -13
  45. package/src/index.js +0 -13
  46. package/src/index.test.js +0 -13
  47. package/src/rules.test.js +0 -134
  48. package/src/use-validator.js +0 -8
  49. package/src/use-validator.test.js +0 -56
  50. package/src/validator-field.jsx +0 -72
  51. package/src/validator-field.test.js +0 -190
  52. package/src/validator-wrapper.jsx +0 -63
  53. package/src/validator-wrapper.test.js +0 -177
  54. package/src/validator.js +0 -82
  55. package/src/validator.test.js +0 -40
  56. package/webpack.config.js +0 -32
@@ -0,0 +1,58 @@
1
+ /* eslint react/sort-comp: [0], camelcase: [0] */
2
+ import { Component, ReactNode, RefObject } from 'react'
3
+
4
+ import { Context } from './context'
5
+ import { Validator } from './validator'
6
+
7
+ interface ComponentProps {
8
+ children?: ReactNode
9
+ stopAtFirstError?: boolean
10
+ ref?: RefObject<any>
11
+ }
12
+
13
+ export class ValidatorWrapper extends Component<ComponentProps> {
14
+ fields = [];
15
+
16
+ constructor (props, ctx) {
17
+ super(props, ctx)
18
+ this.registerField = this.registerField.bind(this)
19
+ this.unregisterField = this.unregisterField.bind(this)
20
+ }
21
+
22
+ componentWillUnmount () {
23
+ this.fields = []
24
+ }
25
+
26
+ registerField (field) {
27
+ if (field && !this.fields.includes(field)) {
28
+ this.fields.push(field)
29
+ }
30
+ }
31
+
32
+ unregisterField (field) {
33
+ const index = this.fields.indexOf(field)
34
+ if (index > -1) this.fields.splice(index, 1)
35
+ }
36
+
37
+ getField (id) {
38
+ return this.fields.find((field) => field.props.id === id) || null
39
+ }
40
+
41
+ validate () {
42
+ const validator = new Validator({ stopAtFirstError: this.props.stopAtFirstError })
43
+ this.fields.forEach((comp) => {
44
+ validator.addField(comp.props)
45
+ })
46
+ return validator.validate()
47
+ }
48
+
49
+ render () {
50
+ return (
51
+ <Context.Provider
52
+ value={{ registerField: this.registerField, unregisterField: this.unregisterField }}
53
+ >
54
+ {this.props.children}
55
+ </Context.Provider>
56
+ )
57
+ }
58
+ }
@@ -0,0 +1,30 @@
1
+ import { rules } from './rules'
2
+ import { Validator } from './validator'
3
+
4
+ it('check normal create validator', () => {
5
+ const validator = new Validator()
6
+ expect(typeof validator).toBe('object')
7
+ expect(typeof validator.validate).toBe('function')
8
+ })
9
+
10
+ it('check normal add and remove fields', () => {
11
+ const validator = new Validator({ stopAtFirstError: true })
12
+ const fieldPassword = validator.addField({
13
+ rules: rules.password,
14
+ value: '',
15
+ id: 'for-remove'
16
+ })
17
+
18
+ expect(typeof fieldPassword).toBe('object')
19
+
20
+ const fieldSearchPassword = validator.getField('for-remove')
21
+
22
+ expect(typeof fieldSearchPassword).toBe('object')
23
+ expect(typeof fieldSearchPassword.validate).toBe('function')
24
+ expect(fieldPassword.id === fieldSearchPassword.id).toBe(true)
25
+
26
+ let newFieldSearchPassword = validator.getField('for-remove')
27
+ validator.removeField(newFieldSearchPassword)
28
+ newFieldSearchPassword = validator.getField('for-remove')
29
+ expect(newFieldSearchPassword === null).toBe(true)
30
+ })
@@ -0,0 +1,105 @@
1
+ import { Validity, Value } from './validator-field'
2
+ import { ValidatorRules } from './rules'
3
+
4
+ export interface FieldParams {
5
+ value: Value
6
+ rules: ValidatorRules,
7
+ required?: boolean
8
+ id?: string | number
9
+ }
10
+
11
+ export class Field {
12
+ private rules: ValidatorRules;
13
+ private required: boolean;
14
+ private value: Value;
15
+ public id: string | number;
16
+ constructor ({
17
+ rules,
18
+ required,
19
+ value,
20
+ id
21
+ }: FieldParams) {
22
+ this.rules = rules
23
+ this.required = required
24
+ this.value = value
25
+ this.id = id
26
+ }
27
+
28
+ validate (): Validity {
29
+ let isValid = true
30
+ let message = ''
31
+ const {
32
+ rules,
33
+ value,
34
+ required,
35
+ id
36
+ } = this
37
+
38
+ const isEmptyValue = !value && parseFloat(value) !== 0
39
+
40
+ if (!rules.length || (isEmptyValue && required === false)) {
41
+ return { isValid, message, id }
42
+ }
43
+ rules.forEach((instance) => {
44
+ if (isValid) {
45
+ isValid = instance.rule(value)
46
+ if (!isValid) {
47
+ if (typeof instance.message === 'function') {
48
+ message = instance.message(value)
49
+ } else {
50
+ message = instance.message
51
+ }
52
+ }
53
+ }
54
+ })
55
+ return { isValid, message, id }
56
+ }
57
+ }
58
+
59
+ export interface ValidatorParams {
60
+ stopAtFirstError: boolean
61
+ }
62
+
63
+ export class Validator {
64
+ private fields: Field[];
65
+ private params: ValidatorParams;
66
+
67
+ constructor (params?: ValidatorParams) {
68
+ this.params = params || null
69
+ this.fields = []
70
+ }
71
+
72
+ addField (params: FieldParams): Field {
73
+ const field = new Field(params)
74
+ this.fields.push(field)
75
+ return field
76
+ }
77
+
78
+ removeField (field: Field): void {
79
+ const index = this.fields.indexOf(field)
80
+ if (index > -1) this.fields.splice(index, 1)
81
+ }
82
+
83
+ getField (id: Field['id']): Field {
84
+ return this.fields.find((field) => field.id === id) || null
85
+ }
86
+
87
+ validate (): Validity {
88
+ let prevResult
89
+ const statuses = this.fields.map((field) => {
90
+ if (this.params?.stopAtFirstError && prevResult && prevResult.isValid === false) {
91
+ return null
92
+ }
93
+ prevResult = field.validate()
94
+ return prevResult
95
+ })
96
+
97
+ const errors = statuses.filter((inst) => inst && inst.isValid === false)
98
+
99
+ if (errors.length) {
100
+ const { isValid, message } = errors[0]
101
+ return { isValid, message, errors }
102
+ }
103
+ return { isValid: true, message: '' }
104
+ }
105
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": [
4
+ "src/**/*"
5
+ ],
6
+ "exclude": [
7
+ "node_modules",
8
+ "dist",
9
+ "src/**/*.test.tsx",
10
+ "src/**/*.test.ts"
11
+ ]
12
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "compilerOptions": {
3
+ "esModuleInterop": true,
4
+ "declaration": true,
5
+ "module": "CommonJS",
6
+ "removeComments": true,
7
+ "emitDecoratorMetadata": true,
8
+ "experimentalDecorators": true,
9
+ "target": "es2017",
10
+ "sourceMap": false,
11
+ "composite": true,
12
+ "incremental": true,
13
+ "noUnusedLocals": true,
14
+ "noUnusedParameters": false,
15
+ "resolveJsonModule": true,
16
+ "outDir": "./dist",
17
+ "rootDir": "src",
18
+ "baseUrl": "./src",
19
+ "lib": [
20
+ "dom",
21
+ "dom.iterable",
22
+ "esnext"
23
+ ],
24
+ "allowJs": true,
25
+ "skipLibCheck": true,
26
+ "strict": false,
27
+ "isolatedModules": true,
28
+ "moduleResolution": "node",
29
+ "jsx": "preserve"
30
+ },
31
+ "include": [
32
+ "src",
33
+ "src/**/*"
34
+ ],
35
+ "exclude": [
36
+ "node_modules",
37
+ "dist"
38
+ ]
39
+ }
package/.babelrc.js DELETED
@@ -1,14 +0,0 @@
1
- module.exports = {
2
- "presets": [
3
- "@babel/preset-env",
4
- "@babel/preset-react"
5
- ],
6
- "plugins": [
7
- "@babel/proposal-class-properties"
8
- ],
9
- "env": {
10
- "production": {
11
- "plugins": ["transform-react-remove-prop-types"]
12
- }
13
- }
14
- }
package/build/index.js DELETED
@@ -1 +0,0 @@
1
- (()=>{"use strict";var e={n:t=>{var r=t&&t.__esModule?()=>t.default:()=>t;return e.d(r,{a:r}),r},d:(t,r)=>{for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{Validator:()=>f,ValidatorField:()=>R,default:()=>B,rules:()=>C,useValidator:()=>x});const r=require("react");var n=e.n(r);const i=require("prop-types");var o=e.n(i);const u=n().createContext("@coxy/Validator");function l(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function s(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function a(e,t,r){return t&&s(e.prototype,t),r&&s(e,r),e}var c=function(){function e(t){var r=t.rules,n=t.required,i=t.value,o=t.id;l(this,e),this.rules=r,this.required=n,this.value=i,this.id=o}return a(e,[{key:"validate",value:function(){var e=!0,t="",r=this.rules,n=this.value,i=this.required,o=this.id,u=!n&&0!==parseFloat(n);return!r.length||u&&!1===i||r.forEach((function(r){e&&((e=r.rule(n))||"function"==typeof(t=r.message)&&(t=t(n)))})),{isValid:e,message:t,id:o}}}]),e}(),f=function(){function e(t){l(this,e),this.params=t||{},this.fields=[]}return a(e,[{key:"addField",value:function(e){var t=new c(e);return this.fields.push(t),t}},{key:"removeField",value:function(e){var t=this.fields.indexOf(e);t>-1&&this.fields.splice(t,1)}},{key:"getField",value:function(e){return this.fields.find((function(t){return t.id===e}))||null}},{key:"validate",value:function(){var e,t=this,r=this.fields.map((function(r){return t.params.stopAtFirstError&&e&&!1===e.isValid?null:e=r.validate()})).filter((function(e){return e&&!1===e.isValid}));if(r.length){var n=r[0];return{isValid:n.isValid,message:n.message,errors:r}}return{isValid:!0,message:""}}}]),e}();function p(e){return(p="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function d(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function y(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function h(e,t){return(h=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function v(e,t){return!t||"object"!==p(t)&&"function"!=typeof t?b(e):t}function b(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function m(e){return(m=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function g(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var O=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&h(e,t)}(s,e);var t,r,i,o,l=(i=s,o=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}(),function(){var e,t=m(i);if(o){var r=m(this).constructor;e=Reflect.construct(t,arguments,r)}else e=t.apply(this,arguments);return v(this,e)});function s(){var e;d(this,s);for(var t=arguments.length,r=new Array(t),n=0;n<t;n++)r[n]=arguments[n];return g(b(e=l.call.apply(l,[this].concat(r))),"fields",[]),e.registerField=e.registerField.bind(b(e)),e.unregisterField=e.unregisterField.bind(b(e)),e}return t=s,(r=[{key:"componentWillUnmount",value:function(){this.fields=[]}},{key:"registerField",value:function(e){e&&!this.fields.includes(e)&&this.fields.push(e)}},{key:"unregisterField",value:function(e){var t=this.fields.indexOf(e);t>-1&&this.fields.splice(t,1)}},{key:"getField",value:function(e){return this.fields.find((function(t){return t.props.id===e}))||null}},{key:"validate",value:function(){var e=new f({stopAtFirstError:this.props.stopAtFirstError});return this.fields.forEach((function(t){e.addField(t.props)})),e.validate()}},{key:"render",value:function(){return n().createElement(u.Provider,{value:{registerField:this.registerField,unregisterField:this.unregisterField}},this.props.children)}}])&&y(t.prototype,r),s}(r.Component);O.propTypes={children:o().node.isRequired,stopAtFirstError:o().bool},O.defaultProps={stopAtFirstError:!1};const w=O;function F(e){return(F="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function j(){return(j=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}function P(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function S(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function E(e,t){return(E=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function _(e,t){return!t||"object"!==F(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function k(e){return(k=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}var q=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&E(e,t)}(u,e);var t,r,n,i,o=(n=u,i=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}(),function(){var e,t=k(n);if(i){var r=k(this).constructor;e=Reflect.construct(t,arguments,r)}else e=t.apply(this,arguments);return _(this,e)});function u(){return P(this,u),o.apply(this,arguments)}return t=u,(r=[{key:"componentWillUnmount",value:function(){this.props.unregisterField(this)}},{key:"componentDidMount",value:function(){this.props.registerField(this)}},{key:"validate",value:function(){return new c({rules:this.props.rules,required:this.props.required,value:this.props.value,id:this.props.id}).validate()}},{key:"render",value:function(){var e=this.props,t=e.children,r=e.value,n=this.validate();return"function"==typeof t?t(n,r):t}}])&&S(t.prototype,r),u}(r.Component);function R(e){return n().createElement(u.Consumer,null,(function(t){return n().createElement(q,j({},e,{registerField:t.registerField,unregisterField:t.unregisterField}))}))}q.propTypes={registerField:o().func.isRequired,unregisterField:o().func.isRequired,children:o().oneOfType([o().node,o().func]),rules:o().arrayOf(o().shape({message:o().oneOfType([o().string,o().func]),rule:o().func})),id:o().string,required:o().bool,value:o().any},q.defaultProps={rules:[],children:null,required:!0,value:void 0,id:""};var V=["isValid"];function T(e,t){if(null==e)return{};var r,n,i=function(e,t){if(null==e)return{};var r,n,i={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}function x(e,t){var r=new f;r.addField({value:e,rules:t});var n=r.validate();return[n.isValid,T(n,V)]}var A=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;const C={notEmpty:[{rule:function(e){return""!==e&&e.length>0},message:"Value is required"}],bool:[{rule:function(e){return!!e},message:"Value is required"}],password:[{rule:function(e){return e.length>0},message:"Password field cannot be empty"},{rule:function(e){return e.length>5},message:"Password field can not be less than 6 characters"}],email:[{rule:function(e){return!!e&&""!==e&&0!==e.length},message:"Email is required"},{rule:function(e){return A.test(String(e).toLowerCase())},message:"Email is invalid"}],min:function(e){return[{rule:function(t){return parseFloat(t)>e},message:"The value must be greater than ".concat(e)}]},max:function(e){return[{rule:function(t){return parseFloat(t)<e},message:"The value must be smaller ".concat(e)}]},length:function(e,t){return[{rule:function(t){return String(t).length>=e},message:"No less than ".concat(e," symbols")},{rule:function(e){return void 0===t||String(e).length<=t},message:"No more than ".concat(t," symbols")}]}},B=w;module.exports=t})();
package/jest.config.js DELETED
@@ -1,5 +0,0 @@
1
- module.exports = {
2
- collectCoverage: true,
3
- coverageDirectory: './coverage/',
4
- displayName: '@coxy',
5
- };
package/src/context.js DELETED
@@ -1,3 +0,0 @@
1
- import React from 'react';
2
-
3
- export default React.createContext('@coxy/Validator');
@@ -1,13 +0,0 @@
1
- /**
2
- * @jest-environment jsdom
3
- */
4
-
5
- /* eslint-env jest */
6
-
7
- import context from './context';
8
-
9
- it('renders with or without a name', () => {
10
- expect(typeof context).toBe('object');
11
- expect(typeof context.Consumer).toBe('object');
12
- expect(typeof context.Provider).toBe('object');
13
- });
package/src/index.js DELETED
@@ -1,13 +0,0 @@
1
- import ValidatorWrapper from './validator-wrapper';
2
- import ValidatorField from './validator-field';
3
- import useValidator from './use-validator';
4
- import Validator from './validator';
5
- import rules from './rules';
6
-
7
- export default ValidatorWrapper;
8
- export {
9
- ValidatorField,
10
- useValidator,
11
- Validator,
12
- rules,
13
- };
package/src/index.test.js DELETED
@@ -1,13 +0,0 @@
1
- /**
2
- * @jest-environment jsdom
3
- */
4
-
5
- /* eslint-env jest */
6
-
7
- import ValidatorWrapper, { ValidatorField, rules } from './index';
8
-
9
- it('renders with or without a name', () => {
10
- expect(typeof ValidatorWrapper).toBe('function');
11
- expect(typeof ValidatorField).toBe('function');
12
- expect(typeof rules).toBe('object');
13
- });
package/src/rules.test.js DELETED
@@ -1,134 +0,0 @@
1
- /**
2
- * @jest-environment jsdom
3
- */
4
-
5
- /* eslint-env jest */
6
-
7
- import rules from './rules';
8
-
9
- it('check rule email', () => {
10
- expect(rules.email.length).toBe(2);
11
-
12
- let result = null;
13
- // email.length > 0
14
- result = rules.email[0].rule('test');
15
- expect(result).toBe(true);
16
-
17
- // email check regexp
18
- result = rules.email[1].rule('test');
19
- expect(result).toBe(false);
20
-
21
- // email check regexp
22
- result = rules.email[1].rule('test@gmail.com');
23
- expect(result).toBe(true);
24
- });
25
-
26
- it('check rule password', () => {
27
- expect(rules.password.length).toBe(2);
28
-
29
- let result = null;
30
- // password.length > 0
31
- result = rules.password[0].rule('test');
32
- expect(result).toBe(true);
33
-
34
- // password.length > 5
35
- result = rules.password[1].rule('test');
36
- expect(result).toBe(false);
37
- });
38
-
39
- it('check rule bool', () => {
40
- expect(rules.bool.length).toBe(1);
41
-
42
- let result = null;
43
- result = rules.bool[0].rule(true);
44
- expect(result).toBe(true);
45
- });
46
-
47
- it('check rule notEmpty', () => {
48
- expect(rules.notEmpty.length).toBe(1);
49
-
50
- let result = null;
51
- result = rules.notEmpty[0].rule('');
52
- expect(result).toBe(false);
53
-
54
- result = rules.notEmpty[0].rule('test');
55
- expect(result).toBe(true);
56
- });
57
-
58
- it('check rule min', () => {
59
- expect(rules.min(1).length).toBe(1);
60
- expect(typeof rules.min).toBe('function');
61
-
62
- let result = null;
63
- result = rules.min(10)[0].rule('');
64
- expect(result).toBe(false);
65
-
66
- result = rules.min(9)[0].rule('testtesttest');
67
- expect(result).toBe(false);
68
-
69
- result = rules.min(9)[0].rule('11');
70
- expect(result).toBe(true);
71
-
72
- result = rules.min(9)[0].rule(10);
73
- expect(result).toBe(true);
74
-
75
- result = rules.min(9)[0].rule('8');
76
- expect(result).toBe(false);
77
-
78
- result = rules.min(9)[0].rule(7);
79
- expect(result).toBe(false);
80
-
81
- result = rules.min(-1)[0].rule('');
82
- expect(result).toBe(false);
83
- });
84
-
85
- it('check rule max', () => {
86
- let result = null;
87
- result = rules.max(10)[0].rule('');
88
- expect(result).toBe(false);
89
-
90
- result = rules.max(9)[0].rule('testtesttest');
91
- expect(result).toBe(false);
92
-
93
- result = rules.max(9)[0].rule('11');
94
- expect(result).toBe(false);
95
-
96
- result = rules.max(9)[0].rule(10);
97
- expect(result).toBe(false);
98
-
99
- result = rules.max(9)[0].rule('5');
100
- expect(result).toBe(true);
101
-
102
- result = rules.max(9)[0].rule(5);
103
- expect(result).toBe(true);
104
-
105
- result = rules.max(-1)[0].rule('');
106
- expect(result).toBe(false);
107
- });
108
-
109
- it('check rule length', () => {
110
- let result = null;
111
- result = rules.length(1)[0].rule('');
112
- expect(result).toBe(false);
113
-
114
- result = rules.length(1)[0].rule('1');
115
- expect(result).toBe(true);
116
-
117
- result = rules.length(1, 10)[0].rule('testtesttest');
118
- expect(result).toBe(true);
119
-
120
- result = rules.length(1, 10)[1].rule('testtesttest');
121
- expect(result).toBe(false);
122
-
123
- result = rules.length(1, 10)[0].rule('lol');
124
- expect(result).toBe(true);
125
-
126
- result = rules.length(1, 10)[1].rule('lol');
127
- expect(result).toBe(true);
128
-
129
- result = rules.length(1)[1].rule('test undefined 2 param');
130
- expect(result).toBe(true);
131
-
132
- result = rules.length(10)[0].rule('tes');
133
- expect(result).toBe(false);
134
- });
@@ -1,8 +0,0 @@
1
- import Validator from './validator';
2
-
3
- export default function useValidate(value, rules) {
4
- const validator = new Validator();
5
- validator.addField({ value, rules });
6
- const { isValid, ...validateObject } = validator.validate();
7
- return [isValid, validateObject];
8
- }
@@ -1,56 +0,0 @@
1
- /**
2
- * @jest-environment jsdom
3
- */
4
-
5
- /* eslint-env jest */
6
- /* eslint react/jsx-filename-extension: [0] */
7
-
8
- import React from 'react';
9
- import { render, unmountComponentAtNode } from 'react-dom';
10
- import { act } from 'react-dom/test-utils';
11
-
12
- import rules from './rules';
13
- import useValidate from './use-validator';
14
-
15
- let container = null;
16
- beforeEach(() => {
17
- container = document.createElement('div');
18
- document.body.appendChild(container);
19
- });
20
-
21
- afterEach(() => {
22
- unmountComponentAtNode(container);
23
- container.remove();
24
- container = null;
25
- });
26
-
27
- jest.useFakeTimers();
28
-
29
- it('check state change and hide field', () => {
30
- function Comp() {
31
- const [value, setValue] = React.useState(false);
32
- const [isValid] = useValidate(value, rules.bool);
33
- console.log(isValid);
34
-
35
- React.useEffect(() => {
36
- setTimeout(() => {
37
- act(() => {
38
- setValue(true);
39
- });
40
- }, 100);
41
- }, []);
42
-
43
- return (
44
- <div>{isValid ? 'true' : 'false'}</div>
45
- );
46
- }
47
- act(() => {
48
- render(<Comp />, container);
49
- });
50
-
51
- expect(container.textContent).toBe('false');
52
-
53
- jest.runAllTimers();
54
-
55
- expect(container.textContent).toBe('true');
56
- });
@@ -1,72 +0,0 @@
1
- /* eslint react/jsx-props-no-spreading: [0], react/sort-comp: [0], camelcase: [0] */
2
- import React, { Component } from 'react';
3
- import PropTypes from 'prop-types';
4
- import Context from './context';
5
- import { Field } from './validator';
6
-
7
- class ValidationFieldWrapper extends Component {
8
- componentWillUnmount() {
9
- this.props.unregisterField(this);
10
- }
11
-
12
- componentDidMount() {
13
- this.props.registerField(this);
14
- }
15
-
16
- validate() {
17
- const field = new Field({
18
- rules: this.props.rules,
19
- required: this.props.required,
20
- value: this.props.value,
21
- id: this.props.id,
22
- });
23
- return field.validate();
24
- }
25
-
26
- render() {
27
- const { children, value } = this.props;
28
- const validity = this.validate();
29
- return (typeof children === 'function' ? children(validity, value) : children);
30
- }
31
- }
32
-
33
- export default function ValidationField(props) {
34
- return (
35
- <Context.Consumer>
36
- {(data) => (
37
- <ValidationFieldWrapper
38
- {...props}
39
- registerField={data.registerField}
40
- unregisterField={data.unregisterField}
41
- />
42
- )}
43
- </Context.Consumer>
44
- );
45
- }
46
-
47
- ValidationFieldWrapper.propTypes = {
48
- // from context
49
- registerField: PropTypes.func.isRequired,
50
- unregisterField: PropTypes.func.isRequired,
51
-
52
- children: PropTypes.oneOfType([
53
- PropTypes.node,
54
- PropTypes.func,
55
- ]),
56
- rules: PropTypes.arrayOf(PropTypes.shape({
57
- message: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
58
- rule: PropTypes.func,
59
- })),
60
-
61
- id: PropTypes.string,
62
- required: PropTypes.bool,
63
- value: PropTypes.any, // eslint-disable-line
64
- };
65
-
66
- ValidationFieldWrapper.defaultProps = {
67
- rules: [],
68
- children: null,
69
- required: true,
70
- value: undefined,
71
- id: '',
72
- };