Test function
/**
* @param value test value
* @param field current field that is being tested
* @param path full path to the field that is being tested
* @param objUnderTest whole object that is being passed to the validate function
*/
export type Test<T extends TestResult> = (
value: any,
field: string,
path: string,
objUnderTest: any
) => T
Function to test the values coming from the object under validation.
const { validate, validation } = require('validar')
//object to validate
const testObj = {
profile: {
name: 'Mike',
},
}
const stringLengthTest = (value, field, path, objectUnderTest) => {
// value -> 'Mike'
// field -> 'name'
// path -> 'profile.name'
// objectUnderTest -> reference to the testObj
return typeof value === 'string' && value.length > 5
}
//assemble the validation object
const validationObject = {
profile: {
name: validation(stringLengthTest),
},
}
const result = validate(validationObject, testObj)
function parameters:
value
: value to testfield
: name of the field that is under the testpath
: a path to the field under test. If the field is deeply nested full path could be something likeperson.profile.email
objUnderTest
: reference to the object that is currently being tested. Here you can access all other properties of the object (so in case you have acity
field that you are currently testing, you can also look at thecountry
field to determine if thecity
is valid).
Any function that accepts value
as the first parameter and returns boolean
or expected object can be used.
Async test function
Test function can be asynchronous, you just need to return a promise
that will eventually be resolved to the boolean
or object that conforms to the expected object that can be returned from the function.
const stringLengthTest = (value, field, path, objectUnderTest) => {
return new Promise((resolve, reject) => {
// resolve later - maybe query the DB...
resolve(typeof value === 'string' && value.length > 5)
})
}
Do not reject
the promise if the test is negative (e.g length is less than 5) just resolve the promise with the value of false
Using reject()
will bubble up and will have to be handled with the validator function validateAsync().catch()
When using asynchronous tests you should use validateAsync()
function
const { validate, validation } = require('validar')
//object to validate
const testObj = {
profile: {
name: 'Mike',
},
}
const stringLengthTest = (value, field, path, objectUnderTest) => {
// value -> 'Mike'
// field -> 'name'
// path -> 'profile.name'
// objectUnderTest -> reference to the testObj
return new Promise((resolve, reject) => {
// resolve later - maybe query the DB...
resolve(typeof value === 'string' && value.length > 5)
})
}
//assemble the validation object
const validationObject = {
profile: {
name: validation(stringLengthTest),
},
}
const result = validateAsync(testObj, validationObject)
.then(result => {
console.log(result)
})
.catch(error => {
//something went wrong during the validation, a promise has timed out
// or some async test rejected the promise
})
Return values
export type TestResult = boolean | TestPayload | Promise<boolean | TestPayload>
/**
* Object that is optionally returned from the test function.
*
* @param valid true if test is successful
* @param payload custom object with arbitrary data
*/
export interface TestPayload {
readonly valid: boolean
readonly payload?: any
}
Test function can return few different values
boolean
:true
if the test is successful.- Special object
TestPayload
with the following properties.valid
:boolean
->true
if test is successful.payload
: an object that can have any arbitrary data added, and that object will be passed to thetest message
function in case that the test is unsuccessful (function returnsfalse
orpromise
resolves tofalse
)
const stringLengthTest = (value, field, path, objectUnderTest) => {
const r = typeof value === 'string' && value.length > 5
return {
valid: r,
payload: {
whatever: 'whatever',
},
}
}
Async example:
const stringLengthTest = (value, field, path, objectUnderTest) => {
return new Promise((resolve, reject) => {
const r = typeof value === 'string' && value.length > 5
resolve({
valid: r,
payload: {
propA: 'propA',
propB: 'propB',
},
})
})
}
Then if the test is a failure message
function will be called with the result of the test and the payload.
// message function will only be called if the test is a failure
const message = (value,field,path,objUnderTest,payload)=>{
//value -> test value
// payload -> {
// propA:'propA',
// propB:'propB'
// }
return 'Custom failure message'
}
}