diff --git a/packages/docs/src/validators.md b/packages/docs/src/validators.md index c273073b..9676c0eb 100644 --- a/packages/docs/src/validators.md +++ b/packages/docs/src/validators.md @@ -1,11 +1,7 @@ # Validators _Vuelidate 2_ does not bundle any validators, however it exposes them via a secondary package `@vuelidate/validators`. It consists of a set of -validators and helpers, that you can just require and use, but it doesn't end there. All of those are just simple predicates - functions of data -into `boolean`, which denotes if data is valid. You can easily write your own or use any function in this shape from any library you already have. - -This documentation presents every builtin validator with short description and presents an example custom validator implementation to help understand -them and writing your own as easy as possible. +validators and helpers, that you can just import and use. ## Using Builtin validators @@ -27,69 +23,194 @@ import { required, maxLength } from '@vuelidate/validators/dist/raw.esm' Requires non-empty data. Checks for empty arrays and strings containing only whitespaces. +```js +export default { + validations () { + return { + name: { required } + } + } +} +``` + ## requiredIf * **Arguments:** - * `{Ref | Any} prop` - the property to base the required on. + * `{Ref | Any | Function} prop` - the property, to base the `required` validator on. * **Usage:** - Requires non-empty data only if provided property or predicate is true. + Requires non-empty data, only if provided data property, ref, or a function resolve to `true`. + +```js +export default { + validations () { + return { + name: { + requiredIfFoo: requiredIf(this.foo), + requiredIfRef: requiredIf(someRef), + requiredIfFuction: requiredIf(someFunction), + requiredIfAsyncFuction: requiredIf(asyncFunction), + } + } + } +} +``` ## requiredUnless * **Arguments:** - * `{Ref | Any} prop` - the property to base the required on. + * `{Ref | Any | Function} prop` - the property, to base the `required` validator on. * **Usage:** - Requires non-empty data only if provided property or predicate is false. + Requires non-empty data, only if provided data property, ref, or a function resolve to `false`. + +```js +export default { + validations () { + return { + name: { + requiredIfFoo: requiredUnless(this.foo), + requiredIfRef: requiredUnless(someRef), + requiredIfFuction: requiredUnless(someFunction), + requiredIfAsyncFuction: requiredUnless(asyncFunction), + } + } + } +} +``` ## minLength * **Arguments:** * `{Ref | Number} min` +* **Works With:** + * `{Array | Object | String}` + * **Usage:** - Requires the input value to have a minimum specified length, inclusive. Works with arrays. + Requires the input value to have a minimum specified length, inclusive. Works with arrays, objects and strings. + +```js +export default { + validations () { + return { + name: { + minLength: minLength(this.foo), + minLengthRef: minLength(someRef), + minLengthValue: minLength(10), + } + } + } +} +``` ## maxLength * **Arguments:** * `{Ref | Number} max` +* **Works With:** + * `{Array | Object | String}` + * **Usage:** - Requires the input to have a maximum specified length, inclusive. Works with arrays. + Requires the input value to have a maximum specified length, inclusive. Works with arrays, objects and strings. + +```js +export default { + validations () { + return { + name: { + maxLength: maxLength(this.foo), + maxLengthRef: maxLength(someRef), + maxLengthValue: maxLength(10), + } + } + } +} +``` ## minValue * **Arguments:** * `{Ref | Number} min` +* **Works With:** + * `{Number | Date}` + * **Usage:** Requires entry to have a specified minimum numeric value or Date. +```js +export default { + validations () { + return { + name: { + minValue: minValue(this.foo), + minValueRef: minValue(someRef), + minValueValue: minValue(10), + } + } + } +} +``` + ## maxValue * **Arguments:** * `{Ref | Number} max` +* **Works With:** + * `{Number | Date}` + * **Usage:** Requires entry to have a specified maximum numeric value or Date. +```js +export default { + validations () { + return { + name: { + maxValue: maxValue(this.foo), + maxValueRef: maxValue(someRef), + maxValueValue: maxValue(10), + } + } + } +} +``` + ## between * **Arguments:** * `{Ref | Number} min` * `{Ref | Number} max` +* **Works With:** + * `{Number | Date}` + * **Usage:** - Checks if a number or Date is in specified bounds. Min and max are both inclusive + Checks if a number or Date is in specified bounds. `min` and `max` are both inclusive. + +```js +export default { + validations () { + return { + name: { + between: between(this.foo, this.bar), + betweenRef: between(someFooRef, someBarRef), + betweenValue: between(10, 15), + } + } + } +} +``` ## alpha @@ -107,7 +228,7 @@ import { required, maxLength } from '@vuelidate/validators/dist/raw.esm' * **Usage:** - Accepts only numerics. + Accepts only numerics. String numbers are also numeric. ## integer @@ -141,18 +262,43 @@ import { required, maxLength } from '@vuelidate/validators/dist/raw.esm' * **Usage:** - Accepts valid MAC addresses like *00:ff: - 11:22:33:44:55*. Don't forget to call it `macAddress()`, as it has optional parameter. You can specify your own separator instead of `':'`. Provide - empty separator `macAddress('')` to validate MAC addresses like 00ff1122334455*. + Accepts valid MAC addresses like **00:ff:11:22:33:44:55**. Don't forget to call it as a function `macAddress()`, as it has an optional parameter. + You can specify your own separator instead of `':'`. Provide empty separator `macAddress('')` to validate MAC addresses like **00ff1122334455**. + +```js +export default { + validations () { + return { + mac: { + macAddress: macAddress() + } + } + } +} +``` ## sameAs * **Arguments:** - * `{Any} equalTo` + * `{String | Number| Boolean | Ref} equalTo` * **Usage:** - Checks for equality with a given property. + Checks for equality with a given property. Accepts a ref, a direct reference to a data property, or a raw value. + +```js +export default { + validations () { + return { + confirmPassword: { + sameAsPassword: sameAs(this.password), + sameAsRef: sameAs(ref), + sameAsRaw: sameAs('foo') + } + } + } +} +``` ## url @@ -170,16 +316,41 @@ import { required, maxLength } from '@vuelidate/validators/dist/raw.esm' * **Usage:** - Passes when at least one of provided validators passes. + Passes when at least one of provided validators returns `true`. + +```js +export default { + validations () { + return { + agree: { + shouldBeChecked: or(validatorOne, validatorTwo, validatorThree) + } + } + } +} +``` ## and * **Arguments:** - * `{...(NormalizedValidator|Function)} validators` + * `{...(NormalizedValidator | Function | function(): Promise)} validators` * **Usage:** - Passes when all of provided validators passes. + Passes when all of provided validators return `true`. A validator can return a Promise. + +```js +export default { + validations () { + return { + agree: { + shouldBeChecked: and(validatorOne, validatorTwo, validatorThree) + } + } + } +} +``` + ## not @@ -188,15 +359,17 @@ import { required, maxLength } from '@vuelidate/validators/dist/raw.esm' * **Usage:** - Passes when provided validator would not pass, fails otherwise. Can be chained with other validators like `not(sameAs('field'))`. - -## withParams + Passes when provided validator would not pass, fails otherwise. Can be chained with other validators. -* **Arguments:** - * `{Ref | Object} params` - * `{Function | ValidatorObject} validator` - -* **Usage:** - - Not really a validator, but a validator modifier. Adds a `$params` object to the provided validator. Can be used on validation functions or even - entire nested field validation objects. Useful for creating your own custom validators. +```js +export default { + validations () { + return { + name: { + otherProperty: not(sameAs(this.email)), + asyncFunction: not(sameAs(asyncFunction)), + } + } + } +} +``` diff --git a/packages/validators/src/raw/__tests__/and.spec.js b/packages/validators/src/raw/__tests__/and.spec.js index 26f8e1a3..f90aba47 100644 --- a/packages/validators/src/raw/__tests__/and.spec.js +++ b/packages/validators/src/raw/__tests__/and.spec.js @@ -7,7 +7,9 @@ import { NormalizedF, NormalizedT, NormalizedValidatorResponseF, - NormalizedValidatorResponseT + NormalizedValidatorResponseT, + asyncF, + asyncT } from '../../../tests/fixtures' describe('and validator', () => { @@ -16,40 +18,52 @@ describe('and validator', () => { }) it('should not validate single false function', () => { - expect(and(F)()).toBe(false) + return expect(and(F)()).resolves.toBe(false) }) it('should validate single true function', () => { - expect(and(T)()).toBe(true) + return expect(and(T)()).resolves.toBe(true) }) it('should validate all true functions', () => { - expect(and(T, T, T)()).toBe(true) + return expect(and(T, T, T)()).resolves.toBe(true) + }) + + it('should validate all to true, when mixed function types', () => { + return expect(and(T, asyncT, T)()).resolves.toBe(true) }) it('should not validate some true functions', () => { - expect(and(T, F, T)()).toBe(false) + return expect(and(T, F, T)()).resolves.toBe(false) + }) + + it('should not validate some true functions, when mixed function types', () => { + expect(and(T, asyncF, T)()).resolves.toBe(false) + }) + + it('should not validate all false functions', async () => { + await expect(and(F, F, F)()).resolves.toBe(false) }) - it('should not validate all false functions', () => { - expect(and(F, F, F)()).toBe(false) + it('should not validate all false functions, when async', async () => { + await expect(and(asyncF, asyncF, asyncF)()).resolves.toBe(false) }) - it('should pass values and model to function', () => { + it('should pass values and model to function', async () => { const spy = jest.fn() - and(spy)(1, 2) + await and(spy)(1, 2) expect(spy).toHaveBeenCalledWith(1, 2) }) - it('should work with functions returning ValidatorResponse', () => { - expect(and(ValidatorResponseT, ValidatorResponseT, ValidatorResponseT)()).toBe(true) - expect(and(ValidatorResponseF, ValidatorResponseF, ValidatorResponseF)()).toBe(false) + it('should work with functions returning ValidatorResponse', async () => { + await expect(and(ValidatorResponseT, ValidatorResponseT, ValidatorResponseT)()).resolves.toBe(true) + await expect(and(ValidatorResponseF, ValidatorResponseF, ValidatorResponseF)()).resolves.toBe(false) }) - it('should work with Normalized Validators', () => { - expect(and(NormalizedT, NormalizedT)()).toBe(true) - expect(and(NormalizedF, NormalizedF)()).toBe(false) - expect(and(NormalizedValidatorResponseT, NormalizedValidatorResponseT)()).toBe(true) - expect(and(NormalizedValidatorResponseF, NormalizedValidatorResponseF)()).toBe(false) + it('should work with Normalized Validators', async () => { + await expect(and(NormalizedT, NormalizedT)()).resolves.toBe(true) + await expect(and(NormalizedF, NormalizedF)()).resolves.toBe(false) + await expect(and(NormalizedValidatorResponseT, NormalizedValidatorResponseT)()).resolves.toBe(true) + await expect(and(NormalizedValidatorResponseF, NormalizedValidatorResponseF)()).resolves.toBe(false) }) }) diff --git a/packages/validators/src/raw/__tests__/not.spec.js b/packages/validators/src/raw/__tests__/not.spec.js index a2ecf297..c854b6ed 100644 --- a/packages/validators/src/raw/__tests__/not.spec.js +++ b/packages/validators/src/raw/__tests__/not.spec.js @@ -7,24 +7,34 @@ import { NormalizedF, NormalizedT, NormalizedValidatorResponseF, - NormalizedValidatorResponseT + NormalizedValidatorResponseT, + asyncT, + asyncF } from '../../../tests/fixtures' describe('not validator', () => { it('should not validate with true function', () => { - expect(not(T)('test')).toBe(false) + return expect(not(T)('test')).resolves.toBe(false) }) it('should validate with true function on empty input', () => { - expect(not(T)('')).toBe(true) + return expect(not(T)('')).resolves.toBe(true) + }) + + it('should validate with async true function', () => { + return expect(not(asyncT)('')).resolves.toBe(true) }) it('should validate with false function', () => { - expect(not(F)('test')).toBe(true) + return expect(not(F)('test')).resolves.toBe(true) + }) + + it('should validate with async false function', () => { + return expect(not(asyncF)('test')).resolves.toBe(true) }) it('should validate with false function on empty input', () => { - expect(not(T)('')).toBe(true) + return expect(not(T)('')).resolves.toBe(true) }) it('should pass values or model to function', () => { @@ -33,16 +43,16 @@ describe('not validator', () => { expect(spy).toHaveBeenCalledWith(1, 2) }) - it('should work with functions returning ValidatorResponse', () => { - expect(not(ValidatorResponseT)('test')).toBe(false) - expect(not(ValidatorResponseT)('')).toBe(true) - expect(not(ValidatorResponseF)('test')).toBe(true) + it('should work with functions returning ValidatorResponse', async () => { + await expect(not(ValidatorResponseT)('test')).resolves.toBe(false) + await expect(not(ValidatorResponseT)('')).resolves.toBe(true) + await expect(not(ValidatorResponseF)('test')).resolves.toBe(true) }) - it('should work with Normalized Validators', () => { - expect(not(NormalizedT)('test')).toBe(false) - expect(not(NormalizedF)('')).toBe(true) - expect(not(NormalizedValidatorResponseT)('test')).toBe(false) - expect(not(NormalizedValidatorResponseF)('')).toBe(true) + it('should work with Normalized Validators', async () => { + await expect(not(NormalizedT)('test')).resolves.toBe(false) + await expect(not(NormalizedF)('')).resolves.toBe(true) + await expect(not(NormalizedValidatorResponseT)('test')).resolves.toBe(false) + await expect(not(NormalizedValidatorResponseF)('')).resolves.toBe(true) }) }) diff --git a/packages/validators/src/raw/__tests__/or.spec.js b/packages/validators/src/raw/__tests__/or.spec.js index 116cee51..980b384a 100644 --- a/packages/validators/src/raw/__tests__/or.spec.js +++ b/packages/validators/src/raw/__tests__/or.spec.js @@ -7,7 +7,9 @@ import { NormalizedValidatorResponseF, NormalizedValidatorResponseT, ValidatorResponseF, - ValidatorResponseT + ValidatorResponseT, + asyncF, + asyncT } from '../../../tests/fixtures' describe('or validator', () => { @@ -16,40 +18,48 @@ describe('or validator', () => { }) it('should not validate single false function', () => { - expect(or(F)()).toBe(false) + return expect(or(F)()).resolves.toBe(false) }) it('should validate single true function', () => { - expect(or(T)()).toBe(true) + return expect(or(T)()).resolves.toBe(true) }) it('should validate all true functions', () => { - expect(or(T, T, T)()).toBe(true) + return expect(or(T, T, T)()).resolves.toBe(true) + }) + + it('should validate all true functions, when mixed with async', () => { + return expect(or(T, asyncT, T)()).resolves.toBe(true) }) it('should validate some true functions', () => { - expect(or(T, F, T)()).toBe(true) + return expect(or(T, F, T)()).resolves.toBe(true) + }) + + it('should validate some true functions, when mixed with async', () => { + return expect(or(T, asyncF, T)()).resolves.toBe(true) }) it('should not validate all false functions', () => { - expect(or(F, F, F)()).toBe(false) + return expect(or(F, F, F)()).resolves.toBe(false) }) - it('should pass values or model to function', () => { + it('should pass values or model to function', async () => { const spy = jest.fn() - or(spy)(1, 2) + await or(spy)(1, 2) expect(spy).toHaveBeenCalledWith(1, 2) }) - it('should work with functions returning ValidatorResponse', () => { - expect(or(ValidatorResponseT, ValidatorResponseF, ValidatorResponseF)()).toBe(true) - expect(or(ValidatorResponseF, ValidatorResponseF, ValidatorResponseF)()).toBe(false) + it('should work with functions returning ValidatorResponse', async () => { + await expect(or(ValidatorResponseT, ValidatorResponseF, ValidatorResponseF)()).resolves.toBe(true) + await expect(or(ValidatorResponseF, ValidatorResponseF, ValidatorResponseF)()).resolves.toBe(false) }) - it('should work with Normalized Validators', () => { - expect(or(NormalizedT, NormalizedT)()).toBe(true) - expect(or(NormalizedF, NormalizedT)()).toBe(true) - expect(or(NormalizedValidatorResponseT, NormalizedValidatorResponseT)()).toBe(true) - expect(or(NormalizedValidatorResponseF, NormalizedValidatorResponseT)()).toBe(true) + it('should work with Normalized Validators', async () => { + await expect(or(NormalizedT, NormalizedT)()).resolves.toBe(true) + await expect(or(NormalizedF, NormalizedT)()).resolves.toBe(true) + await expect(or(NormalizedValidatorResponseT, NormalizedValidatorResponseT)()).resolves.toBe(true) + await expect(or(NormalizedValidatorResponseF, NormalizedValidatorResponseT)()).resolves.toBe(true) }) }) diff --git a/packages/validators/src/raw/__tests__/requiredIf.spec.js b/packages/validators/src/raw/__tests__/requiredIf.spec.js index ab35f7e2..6e5ad7c5 100644 --- a/packages/validators/src/raw/__tests__/requiredIf.spec.js +++ b/packages/validators/src/raw/__tests__/requiredIf.spec.js @@ -6,19 +6,19 @@ const promiseF = () => Promise.resolve(false) describe('requiredIf validator', () => { it('should not validate empty string when functional condition is met', () => { - expect(requiredIf(T)('')).toBe(false) + expect(requiredIf(T)('')).resolves.toBe(false) }) it('should validate empty string when functional condition not met', () => { - expect(requiredIf(F)('')).toBe(true) + expect(requiredIf(F)('')).resolves.toBe(true) }) it('should not validate empty string when simple boolean condition is met', () => { - expect(requiredIf('prop')('')).toBe(false) + expect(requiredIf('prop')('')).resolves.toBe(false) }) it('should validate empty string when simple boolean condition not met', () => { - expect(requiredIf('')('')).toBe(true) + expect(requiredIf('')('')).resolves.toBe(true) }) it('should return a promise when passed a promise condition', () => { @@ -37,8 +37,8 @@ describe('requiredIf validator', () => { it('should pass the value to the validation function', () => { const validator = jest.fn() - requiredIf(validator)('foo') + requiredIf(validator)('foo', 'bar') expect(validator).toHaveBeenCalledTimes(1) - expect(validator).toHaveBeenCalledWith('foo') + expect(validator).toHaveBeenCalledWith('foo', 'bar') }) }) diff --git a/packages/validators/src/raw/__tests__/requiredUnless.spec.js b/packages/validators/src/raw/__tests__/requiredUnless.spec.js index 17de04df..62209ad7 100644 --- a/packages/validators/src/raw/__tests__/requiredUnless.spec.js +++ b/packages/validators/src/raw/__tests__/requiredUnless.spec.js @@ -3,19 +3,19 @@ import { T, F } from '../../../tests/fixtures' describe('requiredUnless validator', () => { it('should not validate if prop is falsy', () => { - expect(requiredUnless(F)('')).toBe(false) - expect(requiredUnless(F)('truthy value')).toBe(true) + expect(requiredUnless(F)('')).resolves.toBe(false) + expect(requiredUnless(F)('truthy value')).resolves.toBe(true) }) it('should not validate when prop condition is truthy', () => { - expect(requiredUnless(T)('')).toBe(true) - expect(requiredUnless(T)('truthy value')).toBe(true) + expect(requiredUnless(T)('')).resolves.toBe(true) + expect(requiredUnless(T)('truthy value')).resolves.toBe(true) }) it('should pass the value to the validation function', () => { const validator = jest.fn() - requiredUnless(validator)('foo') + requiredUnless(validator)('foo', 'bar') expect(validator).toHaveBeenCalledTimes(1) - expect(validator).toHaveBeenCalledWith('foo') + expect(validator).toHaveBeenCalledWith('foo', 'bar') }) }) diff --git a/packages/validators/src/raw/and.js b/packages/validators/src/raw/and.js index 863e3070..3f415299 100644 --- a/packages/validators/src/raw/and.js +++ b/packages/validators/src/raw/and.js @@ -2,14 +2,14 @@ import { unwrapNormalizedValidator, unwrapValidatorResponse } from '../utils/com /** * Returns true when all validators are truthy - * @param {...(NormalizedValidator|Function)} validators + * @param {...(NormalizedValidator | Function | function(): Promise)} validators * @return {function(...[*]=): boolean} */ -export default function (...validators) { - return function (...args) { +export default function and (...validators) { + return function andInternal (...args) { return ( validators.length > 0 && - validators.reduce((valid, fn) => valid && unwrapValidatorResponse(unwrapNormalizedValidator(fn).apply(this, args)), true) + validators.reduce(async (valid, fn) => await valid && unwrapValidatorResponse(await unwrapNormalizedValidator(fn).apply(this, args)), Promise.resolve(true)) ) } } diff --git a/packages/validators/src/raw/between.js b/packages/validators/src/raw/between.js index c3616c3f..460acf65 100644 --- a/packages/validators/src/raw/between.js +++ b/packages/validators/src/raw/between.js @@ -1,4 +1,4 @@ -import { req } from '../common' +import { req } from './core' import { unwrap } from '../utils/common' /** diff --git a/packages/validators/src/raw/macAddress.js b/packages/validators/src/raw/macAddress.js index 683c766e..82484e09 100644 --- a/packages/validators/src/raw/macAddress.js +++ b/packages/validators/src/raw/macAddress.js @@ -1,4 +1,4 @@ -import { req } from '../common' +import { req } from './core' import { unwrap } from '../utils/common' /** diff --git a/packages/validators/src/raw/minValue.js b/packages/validators/src/raw/minValue.js index 2e63669d..f61b986b 100644 --- a/packages/validators/src/raw/minValue.js +++ b/packages/validators/src/raw/minValue.js @@ -1,4 +1,4 @@ -import { req } from '../common' +import { req } from './core' import { unwrap } from '../utils/common' /** diff --git a/packages/validators/src/raw/not.js b/packages/validators/src/raw/not.js index c6efbe58..5fa68db5 100644 --- a/packages/validators/src/raw/not.js +++ b/packages/validators/src/raw/not.js @@ -1,4 +1,4 @@ -import { req } from '../common' +import { req } from './core' import { unwrapNormalizedValidator, unwrapValidatorResponse } from '../utils/common' /** @@ -7,7 +7,7 @@ import { unwrapNormalizedValidator, unwrapValidatorResponse } from '../utils/com * @returns {function(*=, *=): boolean} */ export default function (validator) { - return function (value, vm) { - return !req(value) || !unwrapValidatorResponse(unwrapNormalizedValidator(validator).call(this, value, vm)) + return async function (value, vm) { + return !req(value) || !unwrapValidatorResponse(await unwrapNormalizedValidator(validator).call(this, value, vm)) } } diff --git a/packages/validators/src/raw/or.js b/packages/validators/src/raw/or.js index 61c53464..9a91919d 100644 --- a/packages/validators/src/raw/or.js +++ b/packages/validators/src/raw/or.js @@ -5,11 +5,11 @@ import { unwrapNormalizedValidator, unwrapValidatorResponse } from '../utils/com * @param {...(NormalizedValidator|Function)} validators * @return {function(...[*]=): boolean} */ -export default function (...validators) { - return function (...args) { +export default function or (...validators) { + return function orInternal (...args) { return ( validators.length > 0 && - validators.reduce((valid, fn) => valid || unwrapValidatorResponse(unwrapNormalizedValidator(fn).apply(this, args)), false) + validators.reduce(async (valid, fn) => await valid || unwrapValidatorResponse(await unwrapNormalizedValidator(fn).apply(this, args)), Promise.resolve(false)) ) } } diff --git a/packages/validators/src/raw/requiredIf.js b/packages/validators/src/raw/requiredIf.js index 4592f94c..fdae3cbc 100644 --- a/packages/validators/src/raw/requiredIf.js +++ b/packages/validators/src/raw/requiredIf.js @@ -1,23 +1,17 @@ -import { req } from '../common' -import { isPromise } from '../utils/common' +import { req } from './core' const validate = (prop, val) => prop ? req(val) : true /** * Returns required if the passed property is truthy - * @param {Boolean | String | function(any): (Boolean | Promise)} prop + * @param {Boolean | String | function(any): (Boolean | Promise)} propOrFunction * @return {function(*): (Boolean | Promise)} */ -export default function (prop) { - return (value) => { - if (typeof prop !== 'function') { - return validate(prop, value) - } - const result = prop(value) - if (isPromise(result)) { - return result.then((response) => { - return validate(response, value) - }) +export default function requiredIf (propOrFunction) { + return async function requiredIfInternal (value, parentVM) { + if (typeof propOrFunction !== 'function') { + return validate(propOrFunction, value) } + const result = await propOrFunction.call(this, value, parentVM) return validate(result, value) } } diff --git a/packages/validators/src/raw/requiredUnless.js b/packages/validators/src/raw/requiredUnless.js index f94eaae4..a7508aa3 100644 --- a/packages/validators/src/raw/requiredUnless.js +++ b/packages/validators/src/raw/requiredUnless.js @@ -1,23 +1,17 @@ -import { req } from '../common' -import { isPromise } from '../utils/common' +import { req } from './core' const validate = (prop, val) => !prop ? req(val) : true /** * Returns required if the passed property is falsy. - * @param {Boolean | String | function(any): (Boolean | Promise)} prop + * @param {Boolean | String | function(any): (Boolean | Promise)} propOrFunction * @return {function(*): (Boolean | Promise)} */ -export default function (prop) { - return (value) => { - if (typeof prop !== 'function') { - return validate(prop, value) - } - const result = prop(value) - if (isPromise(result)) { - return result.then((response) => { - return validate(response, value) - }) +export default function requiredUnless (propOrFunction) { + return async function requiredUnlessInternal (value, parentVM) { + if (typeof propOrFunction !== 'function') { + return validate(propOrFunction, value) } + const result = await propOrFunction.call(this, value, parentVM) return validate(result, value) } } diff --git a/packages/validators/tests/fixtures.js b/packages/validators/tests/fixtures.js index b6d7d53f..37ac7ee0 100644 --- a/packages/validators/tests/fixtures.js +++ b/packages/validators/tests/fixtures.js @@ -6,3 +6,5 @@ export const NormalizedT = { $validator: T } export const NormalizedF = { $validator: F } export const NormalizedValidatorResponseT = { $validator: ValidatorResponseT } export const NormalizedValidatorResponseF = { $validator: ValidatorResponseF } +export const asyncT = () => Promise.resolve(true) +export const asyncF = () => Promise.resolve(false)