1
0
mirror of synced 2024-11-25 14:56:03 +03:00
vue-formulario/test/unit/validation/validator.test.js
2020-10-26 20:54:43 +03:00

224 lines
7.2 KiB
JavaScript

import {
createValidator,
enlarge,
parseModifier,
processSingleArrayConstraint,
processSingleStringConstraint,
validate,
} from '@/validation/validator.ts'
const isNumberAndInRangeRule = ({ value }, from, to) => !isNaN(value) && value >= from && value <= to
const isNumberAndInRangeMessage = ({ value }, from, to) => {
return isNaN(value) ? 'Value is NaN' : `Value not in range [${from}, ${to}]`
}
describe('createValidator', () => {
it ('Creates correct validator', async () => {
const context = { value: 'abc', formValues: {}, name: 'field' }
const validate = createValidator(
isNumberAndInRangeRule,
'rule',
[1, 2],
isNumberAndInRangeMessage,
)
await expect(validate(context)).toBeInstanceOf(Promise)
expect(await validate(context)).toEqual({
rule: 'rule',
args: [1, 2],
context,
message: 'Value is NaN',
})
expect(await validate({ ...context, value: 0 })).toEqual({
rule: 'rule',
args: [1, 2],
context: { ...context, value: 0 },
message: 'Value not in range [1, 2]',
})
expect(await validate({ ...context, value: 1.5 })).toBeNull()
})
})
describe('enlarge', () => {
it ('Merges non-bail validator groups', () => {
expect(enlarge([
{ validators: [], bail: false },
{ validators: [], bail: false },
{ validators: [], bail: false },
])).toEqual([
{ validators: [], bail: false },
])
})
it ('Merges non-bail validator groups, bail groups stayed unmerged', () => {
expect(enlarge([
{ validators: [], bail: false },
{ validators: [], bail: false },
{ validators: [], bail: false },
{ validators: [], bail: true },
{ validators: [], bail: true },
{ validators: [], bail: false },
{ validators: [], bail: false },
])).toEqual([
{ validators: [], bail: false },
{ validators: [], bail: true },
{ validators: [], bail: true },
{ validators: [], bail: false },
])
})
})
describe('parseModifier', () => {
it ('Extracts modifier if present', () => {
expect(parseModifier('^required')).toEqual(['required', '^'])
expect(parseModifier('required')).toEqual(['required', null])
expect(parseModifier('bail')).toEqual(['bail', null])
expect(parseModifier('^min_length')).toEqual(['minLength', '^'])
expect(parseModifier('min_length')).toEqual(['minLength', null])
})
})
describe('processSingleArrayConstraint', () => {
const rules = { isNumberAndInRange: isNumberAndInRangeRule }
const messages = { isNumberAndInRange: isNumberAndInRangeMessage }
it ('Creates validator context if constraint is valid and rule exists', () => {
expect(processSingleArrayConstraint(['isNumberAndInRange', 1, 2], rules, messages)).toEqual([
expect.any(Function),
'isNumberAndInRange',
null,
])
expect(processSingleArrayConstraint(['^is_number_and_in_range', 1, 2], rules, messages)).toEqual([
expect.any(Function),
'isNumberAndInRange',
'^',
])
})
it ('Creates validator context if constraint is validator', () => {
const validate = createValidator(
isNumberAndInRangeRule,
null,
[],
isNumberAndInRangeMessage,
)
expect(processSingleArrayConstraint([validate], rules, messages)).toEqual([
expect.any(Function),
null,
null,
])
})
it ('Throws error if constraint is valid and rule not exists', () => {
expect(() => processSingleArrayConstraint(
['^rule_that_not_exists'],
{ rule: isNumberAndInRangeRule },
{ rule: isNumberAndInRangeMessage },
)).toThrow('[Formulario] Can\'t create validator for constraint: [\"^rule_that_not_exists\"]')
})
it ('Throws error if constraint is not valid', () => {
expect(() => processSingleArrayConstraint(
[null],
{ rule: isNumberAndInRangeRule },
{ rule: isNumberAndInRangeMessage },
)).toThrow('[Formulario]: For array constraint first element must be rule name or Validator function')
})
})
describe('processSingleStringConstraint', () => {
const rules = { isNumberAndInRange: isNumberAndInRangeRule }
const messages = { isNumberAndInRange: isNumberAndInRangeMessage }
it ('Creates validator context if constraint is valid and rule exists', () => {
expect(processSingleStringConstraint('isNumberAndInRange:1,2', rules, messages)).toEqual([
expect.any(Function),
'isNumberAndInRange',
null,
])
expect(processSingleStringConstraint('^is_number_and_in_range:1,2', rules, messages)).toEqual([
expect.any(Function),
'isNumberAndInRange',
'^',
])
})
it ('Throws error if constraint is valid and rule not exists', () => {
expect(() => processSingleStringConstraint(
'^rule_that_not_exists',
{ rule: isNumberAndInRangeRule },
{ rule: isNumberAndInRangeMessage },
)).toThrow('[Formulario] Can\'t create validator for constraint: ^rule_that_not_exists')
})
})
describe('validate', () => {
const isNumber = createValidator(
({ value }) => String(value) !== '' && !isNaN(value),
'number',
[],
() => 'Value is NaN'
)
const isRequired = createValidator(
({ value }) => value !== undefined && String(value) !== '',
'required',
[],
() => 'Value is required'
)
const context = { value: '', formValues: {}, name: 'field' }
it('Applies all rules if no bail', async () => {
expect(await validate([
[isRequired, 'required', null],
[isNumber, 'number', null],
], context)).toEqual([{
rule: 'required',
args: [],
context,
message: 'Value is required',
}, {
rule: 'number',
args: [],
context,
message: 'Value is NaN',
}])
})
it('Applies only first rule (bail)', async () => {
expect(await validate([
[() => {}, 'bail', null],
[isRequired, 'required', '^'],
[isNumber, 'number', null],
], context)).toEqual([{
rule: 'required',
args: [],
context,
message: 'Value is required',
}])
})
it('Applies only first rule (bail modifier)', async () => {
expect(await validate([
[isRequired, 'required', '^'],
[isNumber, 'number', null],
], context)).toEqual([{
rule: 'required',
args: [],
context,
message: 'Value is required',
}])
})
it('No violations on valid context', async () => {
expect(await validate([
[isRequired, 'required', '^'],
[isNumber, 'number', null],
], { ...context, value: 0 })).toEqual([])
})
})