diff --git a/.gitignore b/.gitignore
index 40b878d..ec26ac4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,4 @@
-node_modules/
\ No newline at end of file
+node_modules/
+yarn.lock
+package-lock.json
+.vscode
\ No newline at end of file
diff --git a/README.md b/README.md
index 9c2cb0f..3553ffa 100644
--- a/README.md
+++ b/README.md
@@ -72,30 +72,37 @@ Usage
## Custom validations
-Open `src/config.js` and add:
-```
-export const validations = {
- ...
- nameOfValidation: {
- message: (params, value, values) => `The value is ${value} and the param is ${params[0]} and the form values is ${JSON.stringify(values)}`,
- handle: ({ value, params }) => {
- // value is field value | params is array of validation params: "nameOfValidation:param1:param2 ...."
- return true // true if is valid | false if is invalid
- }
- }
+Inside `
` tag, import `Config` as module before import `index.js` and add:
+```html
+ ....
+
+
+ ...
```
Use your validation on html:
```
-
-
+
```
## Custom field types
-- First: Create a class that implements the template and store `formitem` public variable of form element to receive event handlers
+- First: Create a class that implements the template and store `formitem` as public variable of form element to receive event handlers
- Second: Create a method to trigger error message on the template
-````
+```js
export class FormCurrency {
constructor({ el, shadow, internals }) {
this.label = el.getAttribute('label')
@@ -113,24 +120,25 @@ export class FormCurrency {
`
// REQUIRED
- this.formitem = shadow.querySelector('input');
+ this.formitem = shadow.querySelector('input');
}
setError(error) { // false or `string of errors separatelly of `
- console.log('Do anything with form error', error)
+ console.log('Do anything with error message', error)
}
}
-````
-Next, open `src/config.js`, import your class and add on inputs list your new input type:
```
-import { FormCurrency } from 'path/of/file/FormCurrency.js'
-...
-export const inputs = {
+Next, import `Config` store and import your class. register your new input type:
+```html
+
+
...
- currency: {
- source: FormCurrency
- }
```
Use your new input on html:
diff --git a/index.html b/index.html
index e2b7b5e..f33d2e2 100644
--- a/index.html
+++ b/index.html
@@ -4,9 +4,19 @@
- replit
+ Web Components Forms
+
-
+
@@ -37,13 +47,13 @@
Custom label slot
-
+
-
+
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..7df02cc
--- /dev/null
+++ b/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "wc-forms",
+ "version": "1.0.0",
+ "author": "Ulisses Mantovani",
+ "description": "Is a modular, 100% vanilla js, form inputs group, based on [Vue FormKit](https://formkit.com/getting-started/what-is-formkit) library.",
+ "repository": "https://github.com/minasvisual/wc-forms.git",
+ "license": "ISC",
+ "main": "src/index.js",
+ "type": "module",
+ "scripts": {
+ "test": "vitest"
+ },
+ "keywords": [],
+ "devDependencies": {
+ "vitest": "^2.1.3"
+ },
+ "dependencies": {}
+}
diff --git a/src/config.js b/src/config.js
index a4f262b..1c5e982 100644
--- a/src/config.js
+++ b/src/config.js
@@ -2,97 +2,153 @@ import { FormText } from './inputs/forminput.js'
import { FormSelect } from './inputs/formselect.js'
import { FormTextarea, } from './inputs/formtext.js'
import { FormChecksBox, FormChecksRadio } from './inputs/formchecks.js'
-import { splitValues, dateRegex, emailRegex } from './helpers.js'
-import { FormCurrency } from './inputs/custominput.js'
+import { splitValues, get, dateRegex, emailRegex, isValidNumber } from './helpers.js'
+/**
+ * Validations object
+ * @namespace validations
+ * @prop {Object} required - required validation
+ * @prop {Object} email - email validation
+ * @prop {Object} isdate - check if is a date
+ * @prop {Object} isafter - check if is after a date
+ * @prop {Object} isbefore - check if is before a date
+ * @prop {Object} isnumber - check if is a number
+ * @prop {Object} minlen - check if is greater than a min length
+ * @prop {Object} maxlen - check if is lesser than a max length
+ * @prop {Object} confirm - check if is equal to other field
+ * @prop {Object} in - check if is a value in an array
+ *
+ * @example
+ * {
+ * required: {
+ * message: () => 'This field is required',
+ * handle: ({ value, params }) => {
+ * return ![null, undefined, NaN, ''].includes(value)
+ * }
+ * },
+ * email: {
+ * message: () => 'This should be an valid email',
+ * handle: ({ value, params }) => {
+ * return emailRegex.test(value)
+ * }
+ * }
+ * }
+ */
export const validations = {
+
required: {
message: () => 'This field is required',
- handle: ({ value, params }) => {
- return value && value.length > 0
+ /**
+ * @function handle
+ * @description Check if the value is not empty (not null, undefined, NaN, or empty string)
+ * @param {Object} - object with the value to check and the parameters of the validation
+ * @param {any} value - the value to check
+ * @param {string[]} params - the parameters of the validation
+ * @returns {boolean} - true if the value is not empty, false otherwise
+ */
+ handle: ({ value }) => {
+ return ![null, undefined, NaN, ''].includes(value)
}
},
email: {
- message: () => 'This should be an valid email',
- handle: ({ value, params }) => {
+ message: () => 'This should be an valid email',
+ handle: ({ value }) => {
return value && typeof value === 'string' && emailRegex.test(value)
}
},
minlen: {
- message: (params, value, values) => `This field must be at least ${params[0]} characters`,
+ message: (params) => `This field must be at least ${get(params, '[0]', 1)} characters`,
handle: ({ value, params }) => {
+ if(!get(params, '[0]')) throw new Error('Parameter 1 not found')
return value && (value.length >= parseInt(params[0] || 1))
}
},
maxlen: {
- message: (params, value, values) => `This field must be maximum ${params[0]} characters`,
- handle: ({ value, params }) => {
- return value && (value.length <= parseInt(params[0] || 255))
+ message: (params, value, values) => `This field must be maximum ${get(params, '[0]', 255)} characters`,
+ handle: ({ value, params }) => {
+ return value && ( value.length <= parseInt(get(params, '[0]', '255')) )
}
},
confirm: {
- message: (params, value, values) => `This field must be equal to ${params[0]} field`,
- handle: ({ value, params, values }) => {
- return value && params[0] && (value === values[params[0]])
+ message: (params) => `This field must be equal to ${get(params, '[0]')} field`,
+ handle: ({ value, params = [], values }) => {
+ if(!get(params, '[0]')) throw new Error('Parameter to match not found')
+ return value && get(params, '[0]') && (value === values[get(params, '[0]')])
}
},
isdate: {
message: () => 'This field must be a valid date',
- handle: ({ value, params }) => {
+ handle: ({ value }) => {
return value && typeof value === 'string' && dateRegex.test(value)
}
},
isafter: {
- message: (params, value, values) => `This field must be after ${params[0]}`,
- handle: ({ value, params, values }) => {
+ message: (params = [], value, values) => `This field must be after ${get(params, '[0]')}`,
+ handle: ({ value, params = [], values }) => {
+ if(!get(params, '[0]')) throw new Error('Parameter 1 not found')
return value && typeof value === 'string' && dateRegex.test(value) && new Date(value) > new Date(params[0])
}
},
isbefore: {
- message: (params, value, values) => `This field must be before ${params[0]}`,
- handle: ({ value, params, values }) => {
+ message: (params = [], value, values) => `This field must be before ${get(params, '[0]')}`,
+ handle: ({ value, params = [], values }) => {
+ if(!get(params, '[0]')) throw new Error('Parameter 1 not found')
return value && typeof value === 'string' && dateRegex.test(value) && new Date(value) < new Date(params[0])
}
},
isnumber: {
message: () => 'This field must be a valid number',
handle: ({ value, params }) => {
- return value && typeof Number(value) === 'number'
+ console.log(value, Number.isNaN(value))
+ return value && typeof Number(value) === 'number' && !Number.isNaN(Number(value))
}
},
startwith: {
message: (params, value) => `This field must start with ${value}`,
handle: ({ value, params }) => {
- return value && value.startsWith(params[0])
+ if(!get(params, '[0]')) throw new Error('Parameter 1 not found')
+ return value && value.toLowerCase().startsWith(params[0].toLowerCase())
}
},
endswith: {
- message: (params, value) => `This field must ends with ${value}`,
+ message: (params = [], value) => `This field must ends with ${value}`,
handle: ({ value, params }) => {
- return value && value.endsWith(params[0])
+ return value && value.toLowerCase().endsWith(params[0].toLowerCase())
}
},
in: {
- message: (params, value) => `This field must contains ${params.join(',')}`,
+ message: (params = [], value) => `This field must contains ${params?.join(',')}`,
handle: ({ value, params }) => {
- return value && (splitValues(params).includes(value) || splitValues(value).includes(params))
+ if(params.length === 0) throw new Error('Parameters is required')
+ if(value && value.includes(','))
+ return splitValues(value).some(v => splitValues(params).includes(v))
+ else
+ return value && splitValues(params).includes(value)
}
},
notin: {
- message: (params, value) => `This field must not contains ${params.join(',')}`,
+ message: (params = [], value) => `This field must not contains ${params.join(',')}`,
handle: ({ value, params }) => {
- return value && !params.includes(value)
+ if(params.length === 0) throw new Error('Parameters is required')
+ if(value && value.includes(','))
+ return !splitValues(value).some(v => splitValues(params).includes(v))
+ else
+ return value && !splitValues(params).includes(value)
}
},
max: {
- message: (params, value) => `This field must be less than ${params[0]}`,
+ message: (params = [], value) => `This field must be less than ${get(params, '[0]')}`,
handle: ({ value, params }) => {
+ if( !get(params, '[0]') || !isValidNumber(value) ) throw new Error('Parameter 1 not found')
+ if( !isValidNumber(value) ) throw new Error('Value must be a number')
return value && Number(value) <= Number(params[0])
}
},
min: {
- message: (params, value) => `This field must be greater than ${params[0]}`,
+ message: (params = [], value) => `This field must be greater than ${get(params, '[0]')}`,
handle: ({ value, params }) => {
+ if( !get(params, '[0]') || !isValidNumber(value) ) throw new Error('Parameter 1 not found')
+ if( !isValidNumber(value) ) throw new Error('Value must be a number')
return value && Number(value) >= Number(params[0])
}
}
@@ -137,8 +193,24 @@ export const inputs = {
},
textarea: {
source: FormTextarea,
- },
- currency: {
- source: FormCurrency,
+ },
+}
+
+export const Config = {
+ basePath: '/src',
+ validations,
+ inputs,
+ registerValidation(name, rule) {
+ if(!name) throw new Error('Name is required')
+ if(!rule || typeof rule !== 'object') throw new Error('Rule is required as object')
+ if(!rule.message || typeof rule.message !== 'function') throw new Error('Rule message must be a function')
+ if(!rule.handle || typeof rule.handle !== 'function') throw new Error('Rule handle must be a function')
+ this.validations[name] = rule
+ },
+ registerInput(name, classObj) {
+ console.log(name, typeof classObj)
+ if(!name) throw new Error('Name is required')
+ if(!classObj || typeof classObj !== 'function') throw new Error('Rule is required as object')
+ this.inputs[name] = { source: classObj }
}
}
\ No newline at end of file
diff --git a/src/helpers.js b/src/helpers.js
index 09d17d5..8ebd59a 100644
--- a/src/helpers.js
+++ b/src/helpers.js
@@ -28,6 +28,21 @@ export function splitValues(value) {
if (value.includes(',')) return value.split(',')
}
-export const dateRegex = /^[1-2]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])(T([01]\d|2[0-3]):[0-5]\d)?$/;
+export function get (obj, path, defaultValue = undefined) {
+ const travel = regexp =>
+ String.prototype.split
+ .call(path, regexp)
+ .filter(Boolean)
+ .reduce((res, key) => (res !== null && res !== undefined ? res[key] : res), obj);
+ const result = travel(/[,[\]]+?/) || travel(/[,[\].]+?/);
+ return result === undefined || result === obj ? defaultValue : result;
+}
+
+
+export function isValidNumber(value) {
+ return typeof Number(value) === 'number' && !Number.isNaN(Number(value))
+}
+
+export const dateRegex = /^[1-2]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])(T([01]\d|2[0-3]):[0-5]\d(:[01]\d)?)?$/;
export const emailRegex = /^([a-z]){1,}([a-z0-9._-]){1,}([@]){1}([a-z]){2,}([.]){1}([a-z]){2,}([.]?){1}([a-z]?){2,}$/i;
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index 6124ba7..fafc516 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,6 +1,6 @@
import { renderAttributes, extractValidations } from './helpers.js'
import { Validate } from './validation.js'
-import { inputs } from './config.js'
+import { Config } from './config.js'
class FormComponent extends HTMLElement {
static formAssociated = true;
@@ -12,7 +12,8 @@ class FormComponent extends HTMLElement {
connectedCallback() {
this.itype = this.getAttribute('type')
- // todo: create adapters
+ // todo: create adapters
+ const inputs = Config.inputs
const InputSource = inputs[this.itype] ?? inputs.text
if (!InputSource) throw new Error(`Input type not found: ${this.itype}`)
this.instance = new InputSource.source({
@@ -24,7 +25,6 @@ class FormComponent extends HTMLElement {
this.shadowRoot.appendChild(this.addStyles())
this.formitem = this.instance.formitem
this.formitem.addEventListener('change', (e) => {
- console.log('check changed', e.target.value)
this.internals.setFormValue(this.formitem.value)
this.emitEvent('change', this.formitem.value)
this.validate()
@@ -32,6 +32,9 @@ class FormComponent extends HTMLElement {
if (this.instance?.onMounted)
this.instance?.onMounted()
+
+ if (this.instance?.onDestroy)
+ this.instance?.onDestroy()
}
disconnectedCallback() {
@@ -43,7 +46,9 @@ class FormComponent extends HTMLElement {
type: 'text/css',
})
style.appendChild(
- document.createTextNode(`@import "/src/style.css";`)
+ document.createTextNode(
+ `@import "${Config.basePath}/style.css";`
+ )
);
return style
}
diff --git a/src/validation.js b/src/validation.js
index ae69634..ddde2c3 100644
--- a/src/validation.js
+++ b/src/validation.js
@@ -1,4 +1,4 @@
-import { validations } from './config.js'
+import { Config } from './config.js'
export class Validate {
constructor(ruleString) {
this.rule = ''
@@ -24,6 +24,7 @@ export class Validate {
}
getSourceRule() {
+ let validations = Config.validations
if (!validations[this.rule])
throw new Error(`Rule not found: ${this.rule}`)
return validations[this.rule]
diff --git a/tests/helpers.test.js b/tests/helpers.test.js
new file mode 100644
index 0000000..db69a11
--- /dev/null
+++ b/tests/helpers.test.js
@@ -0,0 +1,14 @@
+
+import { test, expect, describe } from 'vitest'
+import { dateRegex } from '../src/helpers.js'
+
+describe('Helpers test - dateRegex', () => {
+ test('should return a dateRegex function', async () => {
+ const sut = dateRegex
+ expect(dateRegex.test('2024-01-01')).toBe(true)
+ expect(dateRegex.test('2024-01-01T12:00')).toBe(true)
+ expect(dateRegex.test('2024-01-01T12:00:00')).toBe(true)
+ expect(dateRegex.test('2024-01-01T12:00:00.000Z')).toBe(false)
+ })
+
+})
diff --git a/tests/validations.test.js b/tests/validations.test.js
new file mode 100644
index 0000000..6c88621
--- /dev/null
+++ b/tests/validations.test.js
@@ -0,0 +1,226 @@
+
+import { test, expect, describe } from 'vitest'
+import { Config } from '../src/config.js'
+
+describe('Config validations - Required', () => {
+ test('should return a validation function', async () => {
+ const sut = Config.validations.required.handle
+ const message = Config.validations.required.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: 'value' })).toBe(true)
+ expect(sut({ value: '' })).toBe(false)
+ expect(message({})).toBe('This field is required')
+ })
+
+})
+
+describe('Config validations - Email', () => {
+ test('should test validation email', async () => {
+ const sut = Config.validations.email.handle
+ const message = Config.validations.email.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: 'test@domain.com' })).toBe(true)
+ expect(sut({ value: 'test@subdomain.domain.com' })).toBe(true)
+ expect(sut({ value: 'test@domain.com.br' })).toBe(true)
+ expect(sut({ value: 'test@subdomain.subdomain.domain.com' })).toBe(false)
+ expect(sut({ value: 'test' })).toBe(false)
+ expect(message({})).toBe('This should be an valid email')
+ })
+
+})
+
+describe('Config validations - Min Length', () => {
+ test('should test max length validation', async () => {
+ const sut = Config.validations.minlen.handle
+ const message = Config.validations.minlen.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: '12345', params: ['5'] })).toBe(true)
+ expect(sut({ value: '12345', params: ['6'] })).toBe(false)
+ expect(message([])).toBe( `This field must be at least 1 characters`)
+ expect(message(['5'])).toBe( `This field must be at least 5 characters`)
+ })
+})
+
+describe('Config validations - Max Length', () => {
+ test('should test max length validation', async () => {
+ const sut = Config.validations.maxlen.handle
+ const message = Config.validations.maxlen.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: '12345', params: ['5'] })).toBe(true)
+ expect(sut({ value: '12345', params: ['4'] })).toBe(false)
+ expect(message([])).toBe( `This field must be maximum 255 characters`)
+ expect(message(['5'])).toBe( `This field must be maximum 5 characters`)
+ })
+})
+
+describe('Config validations - Confirm', () => {
+ test('should test confirm validation', async () => {
+ const sut = Config.validations.confirm.handle
+ const message = Config.validations.confirm.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: '123mudar', params: ['password2'], values: { password2: '123mudar' } })).toBe(true)
+ expect(sut({ value: '12345', params: ['4'], values: { password2: '123MUDAR'} })).toBe(false)
+ expect(message([])).toBe( `This field must be equal to undefined field`)
+ expect(message(['password2'])).toBe( `This field must be equal to password2 field`)
+ })
+})
+
+describe('Config validations - Is date', () => {
+ test('should test isdate validation', async () => {
+ const sut = Config.validations.isdate.handle
+ const message = Config.validations.isdate.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: '2024-01-01' })).toBe(true)
+ expect(sut({ value: '2024-01-01T12:00' })).toBe(true)
+ expect(sut({ value: '2024-01-01T12:00:00' })).toBe(true)
+ expect(sut({ value: '12345abc' })).toBe(false)
+ expect(sut({ value: 'abc' })).toBe(false)
+ expect(message({})).toBe('This field must be a valid date')
+ })
+
+})
+
+describe('Config validations - Is After', () => {
+ test('should test isafter validation', async () => {
+ const sut = Config.validations.isafter.handle
+ const message = Config.validations.isafter.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: '2020-01-01', params: ['2020-01-02'] })).toBe(false)
+ expect(sut({ value: '2020-01-02', params: ['2020-01-02'] })).toBe(false)
+ expect(sut({ value: '2020-01-03', params: ['2020-01-02'] })).toBe(true)
+ expect(message([])).toBe( `This field must be after undefined`)
+ expect(message(['2020-01-01'])).toBe( `This field must be after 2020-01-01`)
+ })
+})
+
+describe('Config validations - Is Before', () => {
+ test('should test isbefore validation', async () => {
+ const sut = Config.validations.isbefore.handle
+ const message = Config.validations.isbefore.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: '2020-01-01', params: ['2020-01-02'] })).toBe(true)
+ expect(sut({ value: '2020-01-02', params: ['2020-01-02'] })).toBe(false)
+ expect(message([])).toBe( `This field must be before undefined`)
+ expect(message(['2020-01-01'])).toBe( `This field must be before 2020-01-01`)
+ })
+})
+
+describe('Config validations - Is Number', () => {
+ test('should test isnumber validation', async () => {
+ const sut = Config.validations.isnumber.handle
+ const message = Config.validations.isnumber.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: '12345' })).toBe(true)
+ expect(sut({ value: '12345.12' })).toBe(true)
+ expect(sut({ value: '12345abc' })).toBe(false)
+ expect(sut({ value: 'abc' })).toBe(false)
+ expect(message({})).toBe('This field must be a valid number')
+ })
+
+})
+
+describe('Config validations - Starts With', () => {
+ test('should test startswith validation', async () => {
+ const sut = Config.validations.startwith.handle
+ const message = Config.validations.startwith.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: 'hello world', params: ['hello'] })).toBe(true)
+ expect(sut({ value: 'Hello world', params: ['hello'] })).toBe(true)
+ expect(sut({ value: 'world hello', params: ['hello'] })).toBe(false)
+ expect(message([])).toBe(`This field must start with undefined`)
+ expect(message([], 'hello')).toBe(`This field must start with hello`)
+ })
+})
+
+describe('Config validations - Ends With', () => {
+ test('should test endswith validation', async () => {
+ const sut = Config.validations.endswith.handle
+ const message = Config.validations.endswith.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: 'hello world', params: ['world'] })).toBe(true)
+ expect(sut({ value: 'Hello World', params: ['world'] })).toBe(true)
+ expect(sut({ value: 'world hello', params: ['world'] })).toBe(false)
+ expect(message([])).toBe(`This field must ends with undefined`)
+ expect(message([], 'hello')).toBe(`This field must ends with hello`)
+ })
+})
+
+describe('Config validations - IN', () => {
+ test('should test In validation', async () => {
+ const sut = Config.validations.in.handle
+ const message = Config.validations.in.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: 'apple', params: ['apple','banana','orange'] })).toBe(true)
+ expect(sut({ value: 'apple,banana', params: ['apple','banana','orange'] })).toBe(true)
+ expect(sut({ value: 'watermelon,apple', params: ['apple','banana','orange'] })).toBe(true)
+ expect(sut({ value: 'watermelon', params: ['apple','banana','orange'] })).toBe(false)
+ expect(sut({ value: 'watermelon,lemon', params: ['apple','banana','orange'] })).toBe(false)
+ expect(message([])).toBe(`This field must contains `)
+ expect(message(['hello'])).toBe(`This field must contains hello`)
+ expect(message(['lemon','watermelon'])).toBe(`This field must contains lemon,watermelon`)
+ })
+})
+
+describe('Config validations - NotIn', () => {
+ test('should test NotIn validation', async () => {
+ const sut = Config.validations.notin.handle
+ const message = Config.validations.notin.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: 'lemon', params: ['apple','banana','orange'] })).toBe(true)
+ expect(sut({ value: 'lemon,watermelon', params: ['apple','banana','orange'] })).toBe(true)
+ expect(sut({ value: 'apple', params: ['apple','banana','orange'] })).toBe(false)
+ expect(sut({ value: 'apple,orange', params: ['apple','banana','orange'] })).toBe(false)
+ expect(message([])).toBe(`This field must not contains `)
+ expect(message(['lemon','watermelon'])).toBe(`This field must not contains lemon,watermelon`)
+ })
+})
+
+describe('Config validations - Max and Min', () => {
+ test('should test max validation', async () => {
+ const sut = Config.validations.max.handle
+ const message = Config.validations.max.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: '5', params: ['10'] })).toBe(true)
+ expect(sut({ value: '15', params: ['10'] })).toBe(false)
+ expect(message([])).toBe('This field must be less than undefined')
+ expect(message(['10'])).toBe('This field must be less than 10')
+ })
+
+ test('should test min validation', async () => {
+ const sut = Config.validations.min.handle
+ const message = Config.validations.min.message
+ expect(typeof sut).toBe('function')
+ expect(sut({ value: '15', params: ['10'] })).toBe(true)
+ expect(sut({ value: '5', params: ['10'] })).toBe(false)
+ expect(message([])).toBe('This field must be greater than undefined')
+ expect(message(['10'])).toBe('This field must be greater than 10')
+ })
+})
+
+// describe('registerValidation test', () => {
+// it('should register new validation', () => {
+// const name = 'test'
+// const rule = {
+// message: (params, value, values) => `This field must quals ${value}`,
+// handle: ({ value, params }) => value == params[0]
+// }
+// Config.registerValidation(name, rule)
+// expect(Config.validations[name]).toEqual(rule)
+// })
+
+// it('should throw an error if no name is provided', () => {
+// expect(() => Config.registerValidation(undefined, {})).toThrowError('Name is required')
+// })
+
+// it('should throw an error if no rule is provided', () => {
+// expect(() => Config.registerValidation('name', undefined)).toThrowError('Rule is required as object')
+// })
+
+// it('should throw an error if rule message is not a function', () => {
+// expect(() => Config.registerValidation('name', { message: 'message' })).toThrowError('Rule message must be a function')
+// })
+
+// it('should throw an error if rule handle is not a function', () => {
+// expect(() => Config.registerValidation('name', { message: () => 'message', handle: 'handle' })).toThrowError('Rule handle must be a function')
+// })
+// })
\ No newline at end of file