Adds startsWith and endsWith validation rules (#9)
* adds language definitions for new rules * re-order rules file to order rule definitions alphabetically * adds support for endsWith validation rule and converts snake_case rules to camelCase function calls * adds support for startsWith field validation * better en.js definitions for new validations * adds tests for snakeCaseToCamelCase function
This commit is contained in:
parent
c7a3e1a015
commit
4bfe43719d
2
dist/formulate.esm.js
vendored
2
dist/formulate.esm.js
vendored
File diff suppressed because one or more lines are too long
4
dist/formulate.min.js
vendored
4
dist/formulate.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/formulate.umd.js
vendored
2
dist/formulate.umd.js
vendored
File diff suppressed because one or more lines are too long
@ -113,6 +113,20 @@ export default {
|
||||
return Promise.resolve(isEmail.test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value ends with one of the given Strings
|
||||
*/
|
||||
endsWith: function ({ value }, ...stack) {
|
||||
return Promise.resolve((() => {
|
||||
if (stack.length) {
|
||||
return stack.find(item => {
|
||||
return value.endsWith(item)
|
||||
}) !== undefined
|
||||
}
|
||||
return true
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is in an array (stack).
|
||||
*/
|
||||
@ -137,27 +151,6 @@ export default {
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the maximum value of a particular.
|
||||
*/
|
||||
max: function ({ value }, maximum = 10, force) {
|
||||
return Promise.resolve((() => {
|
||||
if (Array.isArray(value)) {
|
||||
maximum = !isNaN(maximum) ? Number(maximum) : maximum
|
||||
return value.length <= maximum
|
||||
}
|
||||
if ((!isNaN(value) && force !== 'length') || force === 'value') {
|
||||
value = !isNaN(value) ? Number(value) : value
|
||||
return value <= maximum
|
||||
}
|
||||
if (typeof value === 'string' || (force === 'length')) {
|
||||
value = !isNaN(value) ? value.toString() : value
|
||||
return value.length <= maximum
|
||||
}
|
||||
return false
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the file type is correct.
|
||||
*/
|
||||
@ -197,6 +190,27 @@ export default {
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the maximum value of a particular.
|
||||
*/
|
||||
max: function ({ value }, maximum = 10, force) {
|
||||
return Promise.resolve((() => {
|
||||
if (Array.isArray(value)) {
|
||||
maximum = !isNaN(maximum) ? Number(maximum) : maximum
|
||||
return value.length <= maximum
|
||||
}
|
||||
if ((!isNaN(value) && force !== 'length') || force === 'value') {
|
||||
value = !isNaN(value) ? Number(value) : value
|
||||
return value <= maximum
|
||||
}
|
||||
if (typeof value === 'string' || (force === 'length')) {
|
||||
value = !isNaN(value) ? value.toString() : value
|
||||
return value.length <= maximum
|
||||
}
|
||||
return false
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is not in stack.
|
||||
*/
|
||||
@ -240,6 +254,20 @@ export default {
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value starts with one of the given Strings
|
||||
*/
|
||||
startsWith: function ({ value }, ...stack) {
|
||||
return Promise.resolve((() => {
|
||||
if (stack.length) {
|
||||
return stack.find(item => {
|
||||
return value.startsWith(item)
|
||||
}) !== undefined
|
||||
}
|
||||
return true
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a string is a valid url
|
||||
*/
|
||||
|
@ -71,6 +71,19 @@ export function shallowEqualObjects (objA, objB) {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string, convert snake_case to camelCase
|
||||
* @param {String} string
|
||||
*/
|
||||
export function snakeCaseToCamelCase (string) {
|
||||
return string.replace(/([_][a-z])/ig, ($1) => {
|
||||
if (string.indexOf($1) !== 0 && string[string.indexOf($1) - 1] !== '_') {
|
||||
return $1.toUpperCase().replace('_', '')
|
||||
}
|
||||
return $1
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string, object, falsey, or array - return an array.
|
||||
* @param {mixed} item
|
||||
@ -138,7 +151,7 @@ function parseRule (rule, rules) {
|
||||
}
|
||||
if (typeof rule === 'string') {
|
||||
const segments = rule.split(':')
|
||||
const functionName = segments.shift()
|
||||
const functionName = snakeCaseToCamelCase(segments.shift())
|
||||
if (rules.hasOwnProperty(functionName)) {
|
||||
return [rules[functionName], segments.length ? segments.join(':').split(',') : []]
|
||||
} else {
|
||||
|
@ -89,6 +89,16 @@ export default {
|
||||
return `“${value}” is not a valid email address.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Ends with specified value
|
||||
*/
|
||||
endsWith: function ({ name, value }) {
|
||||
if (!value) {
|
||||
return `This field doesn’t end with a valid value.`
|
||||
}
|
||||
return `“${value}” doesn’t end with a valid value.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is an allowed value.
|
||||
*/
|
||||
@ -162,6 +172,16 @@ export default {
|
||||
return `${s(name)} is required.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts with specified value
|
||||
*/
|
||||
startsWith: function ({ name, value }) {
|
||||
if (!value) {
|
||||
return `This field doesn’t start with a valid value.`
|
||||
}
|
||||
return `“${value}” doesn’t start with a valid value.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is not a url.
|
||||
*/
|
||||
|
@ -1,35 +1,238 @@
|
||||
import rules from '@/libs/rules'
|
||||
import FileUpload from '../src/FileUpload'
|
||||
|
||||
|
||||
/**
|
||||
* Required rule
|
||||
* Accepted rule
|
||||
*/
|
||||
describe('required', () => {
|
||||
it('fails on empty string', async () => expect(await rules.required({ value: '' })).toBe(false))
|
||||
describe('accepted', () => {
|
||||
it('passes with true', async () => expect(await rules.accepted({ value: 'yes' })).toBe(true))
|
||||
|
||||
it('fails on empty array', async () => expect(await rules.required({ value: [] })).toBe(false))
|
||||
it('passes with on', async () => expect(await rules.accepted({ value: 'on' })).toBe(true))
|
||||
|
||||
it('fails on empty object', async () => expect(await rules.required({ value: {} })).toBe(false))
|
||||
it('passes with 1', async () => expect(await rules.accepted({ value: '1' })).toBe(true))
|
||||
|
||||
it('fails on null', async () => expect(await rules.required({ value: null })).toBe(false))
|
||||
it('passes with number 1', async () => expect(await rules.accepted({ value: 1 })).toBe(true))
|
||||
|
||||
it('passes with the number zero', async () => expect(await rules.required({ value: 0 })).toBe(true))
|
||||
it('passes with boolean true', async () => expect(await rules.accepted({ value: true })).toBe(true))
|
||||
|
||||
it('passes with the boolean false', async () => expect(await rules.required({ value: false })).toBe(true))
|
||||
it('fail with boolean false', async () => expect(await rules.accepted({ value: false })).toBe(false))
|
||||
|
||||
it('passes with a non empty array', async () => expect(await rules.required({ value: ['123'] })).toBe(true))
|
||||
|
||||
it('passes with a non empty object', async () => expect(await rules.required({ value: {a: 'b'} })).toBe(true))
|
||||
|
||||
it('passes with empty value if second argument is false', async () => expect(await rules.required({ value: '' }, false)).toBe(true))
|
||||
|
||||
it('passes with empty value if second argument is false string', async () => expect(await rules.required({ value: '' }, 'false')).toBe(true))
|
||||
|
||||
it('passes with FileUpload', async () => expect(await rules.required({ value: new FileUpload({ files: [{ name: 'j.png' }] }) })).toBe(true))
|
||||
|
||||
it('fails with empty FileUpload', async () => expect(await rules.required({ value: new FileUpload({ files: [] }) })).toBe(false))
|
||||
it('fail with "false"', async () => expect(await rules.accepted({ value: 'false' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if a date is after another date
|
||||
*/
|
||||
describe('after', () => {
|
||||
const today = new Date()
|
||||
const tomorrow = new Date()
|
||||
const yesterday = new Date()
|
||||
tomorrow.setDate(today.getDate() + 1)
|
||||
yesterday.setDate(today.getDate() - 1)
|
||||
|
||||
it('passes with tomorrow’s date object', async () => expect(await rules.after({ value: tomorrow })).toBe(true))
|
||||
|
||||
it('passes with future date', async () => expect(await rules.after({ value: 'January 15, 2999' })).toBe(true))
|
||||
|
||||
it('passes with long past date', async () => expect(await rules.after({ value: yesterday }, 'Jan 15, 2000')).toBe(true))
|
||||
|
||||
it('fails with yesterday’s date', async () => expect(await rules.after({ value: yesterday })).toBe(false))
|
||||
|
||||
it('fails with old date string', async () => expect(await rules.after({ value: 'January, 2000' })).toBe(false))
|
||||
|
||||
it('fails with invalid value', async () => expect(await rules.after({ value: '' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if a date is after another date
|
||||
*/
|
||||
describe('alpha', () => {
|
||||
it('passes with simple string', async () => expect(await rules.alpha({ value: 'abc' })).toBe(true))
|
||||
|
||||
it('passes with long string', async () => expect(await rules.alpha({ value: 'lkashdflaosuihdfaisudgflakjsdbflasidufg' })).toBe(true))
|
||||
|
||||
it('passes with single character', async () => expect(await rules.alpha({ value: 'z' })).toBe(true))
|
||||
|
||||
it('passes with accented character', async () => expect(await rules.alpha({ value: 'jüstin' })).toBe(true))
|
||||
|
||||
it('passes with lots of accented characters', async () => expect(await rules.alpha({ value: 'àáâäïíôöÆ' })).toBe(true))
|
||||
|
||||
it('passes with lots of accented characters if invalid set', async () => expect(await rules.alpha({ value: 'àáâäïíôöÆ' }, 'russian')).toBe(true))
|
||||
|
||||
it('fails with lots of accented characters if latin', async () => expect(await rules.alpha({ value: 'àáâäïíôöÆ' }, 'latin')).toBe(false))
|
||||
|
||||
it('fails with numbers', async () => expect(await rules.alpha({ value: 'justin83' })).toBe(false))
|
||||
|
||||
it('fails with symbols', async () => expect(await rules.alpha({ value: '-justin' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if a date alpha and numeric
|
||||
*/
|
||||
describe('alphanumeric', () => {
|
||||
it('passes with simple string', async () => expect(await rules.alphanumeric({ value: '567abc' })).toBe(true))
|
||||
|
||||
it('passes with long string', async () => expect(await rules.alphanumeric({ value: 'lkashdfla234osuihdfaisudgflakjsdbfla567sidufg' })).toBe(true))
|
||||
|
||||
it('passes with single character', async () => expect(await rules.alphanumeric({ value: 'z' })).toBe(true))
|
||||
|
||||
it('passes with accented character', async () => expect(await rules.alphanumeric({ value: 'jüst56in' })).toBe(true))
|
||||
|
||||
it('passes with lots of accented characters', async () => expect(await rules.alphanumeric({ value: 'àáâ7567567äïíôöÆ' })).toBe(true))
|
||||
|
||||
it('passes with lots of accented characters if invalid set', async () => expect(await rules.alphanumeric({ value: '123123àáâäï67íôöÆ' }, 'russian')).toBe(true))
|
||||
|
||||
it('fails with lots of accented characters if latin', async () => expect(await rules.alphanumeric({ value: 'àáâäï123123íôöÆ' }, 'latin')).toBe(false))
|
||||
|
||||
it('fails with decimals in', async () => expect(await rules.alphanumeric({ value: 'abcABC99.123' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if a date is after another date
|
||||
*/
|
||||
describe('before', () => {
|
||||
const today = new Date()
|
||||
const tomorrow = new Date()
|
||||
const yesterday = new Date()
|
||||
tomorrow.setDate(today.getDate() + 1)
|
||||
yesterday.setDate(today.getDate() - 1)
|
||||
|
||||
it('fails with tomorrow’s date object', async () => expect(await rules.before({ value: tomorrow })).toBe(false))
|
||||
|
||||
it('fails with future date', async () => expect(await rules.before({ value: 'January 15, 2999' })).toBe(false))
|
||||
|
||||
it('fails with long past date', async () => expect(await rules.before({ value: yesterday }, 'Jan 15, 2000')).toBe(false))
|
||||
|
||||
it('passes with yesterday’s date', async () => expect(await rules.before({ value: yesterday })).toBe(true))
|
||||
|
||||
it('passes with old date string', async () => expect(await rules.before({ value: 'January, 2000' })).toBe(true))
|
||||
|
||||
it('fails with invalid value', async () => expect(await rules.after({ value: '' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if between
|
||||
*/
|
||||
describe('between', () => {
|
||||
it('passes with simple number', async () => expect(await rules.between({ value: 5 }, 0, 10)).toBe(true))
|
||||
|
||||
it('passes with simple number string', async () => expect(await rules.between({ value: '5' }, '0', '10')).toBe(true))
|
||||
|
||||
it('passes with decimal number string', async () => expect(await rules.between({ value: '0.5' }, '0', '1')).toBe(true))
|
||||
|
||||
it('passes with string length', async () => expect(await rules.between({ value: 'abc' }, 2, 4)).toBe(true))
|
||||
|
||||
it('fails with string length too long', async () => expect(await rules.between({ value: 'abcdef' }, 2, 4)).toBe(false))
|
||||
|
||||
it('fails with string length too short', async () => expect(await rules.between({ value: 'abc' }, 3, 10)).toBe(false))
|
||||
|
||||
it('fails with number to small', async () => expect(await rules.between({ value: 0 }, 3, 10)).toBe(false))
|
||||
|
||||
it('fails with number to large', async () => expect(await rules.between({ value: 15 }, 3, 10)).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Confirm
|
||||
*/
|
||||
describe('confirm', () => {
|
||||
it('passes when the values are the same strings', async () => expect(await rules.confirm(
|
||||
{ value: 'abc', name: 'password', getFormValues: () => ({ password_confirm: 'abc' }) }
|
||||
)).toBe(true))
|
||||
|
||||
it('passes when the values are the same integers', async () => expect(await rules.confirm(
|
||||
{ value: 4422132, name: 'xyz', getFormValues: () => ({ xyz_confirm: 4422132 }) }
|
||||
)).toBe(true))
|
||||
|
||||
it('passes when using a custom field', async () => expect(await rules.confirm(
|
||||
{ value: 4422132, name: 'name', getFormValues: () => ({ other_field: 4422132 }) },
|
||||
'other_field'
|
||||
)).toBe(true))
|
||||
|
||||
it('passes when using a field ends in _confirm', async () => expect(await rules.confirm(
|
||||
{ value: '$ecret', name: 'password_confirm', getFormValues: () => ({ password: '$ecret' }) }
|
||||
)).toBe(true))
|
||||
|
||||
it('fails when using different strings', async () => expect(await rules.confirm(
|
||||
{ value: 'Justin', name: 'name', getFormValues: () => ({ name_confirm: 'Daniel' }) },
|
||||
)).toBe(false))
|
||||
|
||||
it('fails when the types are different', async () => expect(await rules.confirm(
|
||||
{ value: '1234', name: 'num', getFormValues: () => ({ num_confirm: 1234 }) },
|
||||
)).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Determines if the string is a date
|
||||
*/
|
||||
describe('date', () => {
|
||||
it('passes with month day year', async () => expect(await rules.date({ value: 'December 17, 2020' })).toBe(true))
|
||||
|
||||
it('passes with month day', async () => expect(await rules.date({ value: 'December 17' })).toBe(true))
|
||||
|
||||
it('passes with short month day', async () => expect(await rules.date({ value: 'Dec 17' })).toBe(true))
|
||||
|
||||
it('passes with short month day', async () => expect(await rules.date({ value: 'Dec 17 12:34:15' })).toBe(true))
|
||||
|
||||
it('passes with out of bounds number', async () => expect(await rules.date({ value: 'January 77' })).toBe(true))
|
||||
|
||||
it('passes with only month', async () => expect(await rules.date({ value: 'January' })).toBe(false))
|
||||
|
||||
it('passes with valid date format', async () => expect(await rules.date({ value: '12/17/1987' }, 'MM/DD/YYYY')).toBe(true))
|
||||
|
||||
it('fails with simple number and date format', async () => expect(await rules.date({ value: '1234' }, 'MM/DD/YYYY')).toBe(false))
|
||||
|
||||
it('fails with only day of week', async () => expect(await rules.date({ value: 'saturday' })).toBe(false))
|
||||
|
||||
it('fails with random string', async () => expect(await rules.date({ value: 'Pepsi 17' })).toBe(false))
|
||||
|
||||
it('fails with random number', async () => expect(await rules.date({ value: '1872301237' })).toBe(false))
|
||||
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if email.
|
||||
*
|
||||
* Note: testing is light, regular expression used is here: http://jsfiddle.net/ghvj4gy9/embedded/result,js/
|
||||
*/
|
||||
describe('email', () => {
|
||||
it('passes normal email', async () => expect(await rules.email({ value: 'dev+123@wearebraid.com' })).toBe(true))
|
||||
|
||||
it('passes numeric email', async () => expect(await rules.email({ value: '12345@google.com' })).toBe(true))
|
||||
|
||||
it('passes unicode email', async () => expect(await rules.email({ value: 'àlphä@❤️.ly' })).toBe(true))
|
||||
|
||||
it('passes numeric with new tld', async () => expect(await rules.email({ value: '12345@google.photography' })).toBe(true))
|
||||
|
||||
it('fails string without tld', async () => expect(await rules.email({ value: '12345@localhost' })).toBe(false))
|
||||
|
||||
it('fails string without invalid name', async () => expect(await rules.email({ value: '1*(123)2345@localhost' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if value ends with a one of the specified Strings.
|
||||
*/
|
||||
describe('endsWith', () => {
|
||||
it('fails when value ending is not in stack of single value', async () => {
|
||||
expect(await rules.endsWith({ value: 'andrew@wearebraid.com' }, '@gmail.com')).toBe(false)
|
||||
})
|
||||
|
||||
it('fails when value ending is not in stack of multiple values', async () => {
|
||||
expect(await rules.endsWith({ value: 'andrew@wearebraid.com' }, '@gmail.com', '@yahoo.com')).toBe(false)
|
||||
})
|
||||
|
||||
it('passes when stack consists of zero values', async () => {
|
||||
expect(await rules.endsWith({ value: 'andrew@wearebraid.com' })).toBe(true)
|
||||
})
|
||||
|
||||
it('passes when value ending is in stack of single value', async () => {
|
||||
expect(await rules.endsWith({ value: 'andrew@wearebraid.com' }, '@wearebraid.com')).toBe(true)
|
||||
})
|
||||
|
||||
it('passes when value ending is in stack of multiple values', async () => {
|
||||
expect(await rules.endsWith({ value: 'andrew@wearebraid.com' }, '@yahoo.com', '@wearebraid.com', '@gmail.com')).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* In rule
|
||||
@ -85,217 +288,6 @@ describe('matches', () => {
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Accepted rule
|
||||
*/
|
||||
describe('accepted', () => {
|
||||
it('passes with true', async () => expect(await rules.accepted({ value: 'yes' })).toBe(true))
|
||||
|
||||
it('passes with on', async () => expect(await rules.accepted({ value: 'on' })).toBe(true))
|
||||
|
||||
it('passes with 1', async () => expect(await rules.accepted({ value: '1' })).toBe(true))
|
||||
|
||||
it('passes with number 1', async () => expect(await rules.accepted({ value: 1 })).toBe(true))
|
||||
|
||||
it('passes with boolean true', async () => expect(await rules.accepted({ value: true })).toBe(true))
|
||||
|
||||
it('fail with boolean false', async () => expect(await rules.accepted({ value: false })).toBe(false))
|
||||
|
||||
it('fail with "false"', async () => expect(await rules.accepted({ value: 'false' })).toBe(false))
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* Url rule.
|
||||
*
|
||||
* Note: these are just sanity checks because the actual package we use is
|
||||
* well tested: https://github.com/segmentio/is-url/blob/master/test/index.js
|
||||
*/
|
||||
describe('url', () => {
|
||||
it('passes with http://google.com', async () => expect(await rules.url({ value: 'http://google.com' })).toBe(true))
|
||||
|
||||
it('fails with google.com', async () => expect(await rules.url({ value: 'google.com' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Determines if the string is a date
|
||||
*/
|
||||
describe('date', () => {
|
||||
it('passes with month day year', async () => expect(await rules.date({ value: 'December 17, 2020' })).toBe(true))
|
||||
|
||||
it('passes with month day', async () => expect(await rules.date({ value: 'December 17' })).toBe(true))
|
||||
|
||||
it('passes with short month day', async () => expect(await rules.date({ value: 'Dec 17' })).toBe(true))
|
||||
|
||||
it('passes with short month day', async () => expect(await rules.date({ value: 'Dec 17 12:34:15' })).toBe(true))
|
||||
|
||||
it('passes with out of bounds number', async () => expect(await rules.date({ value: 'January 77' })).toBe(true))
|
||||
|
||||
it('passes with only month', async () => expect(await rules.date({ value: 'January' })).toBe(false))
|
||||
|
||||
it('passes with valid date format', async () => expect(await rules.date({ value: '12/17/1987' }, 'MM/DD/YYYY')).toBe(true))
|
||||
|
||||
it('fails with simple number and date format', async () => expect(await rules.date({ value: '1234' }, 'MM/DD/YYYY')).toBe(false))
|
||||
|
||||
it('fails with only day of week', async () => expect(await rules.date({ value: 'saturday' })).toBe(false))
|
||||
|
||||
it('fails with random string', async () => expect(await rules.date({ value: 'Pepsi 17' })).toBe(false))
|
||||
|
||||
it('fails with random number', async () => expect(await rules.date({ value: '1872301237' })).toBe(false))
|
||||
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a date is after another date
|
||||
*/
|
||||
describe('after', () => {
|
||||
const today = new Date()
|
||||
const tomorrow = new Date()
|
||||
const yesterday = new Date()
|
||||
tomorrow.setDate(today.getDate() + 1)
|
||||
yesterday.setDate(today.getDate() - 1)
|
||||
|
||||
it('passes with tomorrow’s date object', async () => expect(await rules.after({ value: tomorrow })).toBe(true))
|
||||
|
||||
it('passes with future date', async () => expect(await rules.after({ value: 'January 15, 2999' })).toBe(true))
|
||||
|
||||
it('passes with long past date', async () => expect(await rules.after({ value: yesterday }, 'Jan 15, 2000')).toBe(true))
|
||||
|
||||
it('fails with yesterday’s date', async () => expect(await rules.after({ value: yesterday })).toBe(false))
|
||||
|
||||
it('fails with old date string', async () => expect(await rules.after({ value: 'January, 2000' })).toBe(false))
|
||||
|
||||
it('fails with invalid value', async () => expect(await rules.after({ value: '' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if a date is after another date
|
||||
*/
|
||||
describe('before', () => {
|
||||
const today = new Date()
|
||||
const tomorrow = new Date()
|
||||
const yesterday = new Date()
|
||||
tomorrow.setDate(today.getDate() + 1)
|
||||
yesterday.setDate(today.getDate() - 1)
|
||||
|
||||
it('fails with tomorrow’s date object', async () => expect(await rules.before({ value: tomorrow })).toBe(false))
|
||||
|
||||
it('fails with future date', async () => expect(await rules.before({ value: 'January 15, 2999' })).toBe(false))
|
||||
|
||||
it('fails with long past date', async () => expect(await rules.before({ value: yesterday }, 'Jan 15, 2000')).toBe(false))
|
||||
|
||||
it('passes with yesterday’s date', async () => expect(await rules.before({ value: yesterday })).toBe(true))
|
||||
|
||||
it('passes with old date string', async () => expect(await rules.before({ value: 'January, 2000' })).toBe(true))
|
||||
|
||||
it('fails with invalid value', async () => expect(await rules.after({ value: '' })).toBe(false))
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a date is after another date
|
||||
*/
|
||||
describe('alpha', () => {
|
||||
it('passes with simple string', async () => expect(await rules.alpha({ value: 'abc' })).toBe(true))
|
||||
|
||||
it('passes with long string', async () => expect(await rules.alpha({ value: 'lkashdflaosuihdfaisudgflakjsdbflasidufg' })).toBe(true))
|
||||
|
||||
it('passes with single character', async () => expect(await rules.alpha({ value: 'z' })).toBe(true))
|
||||
|
||||
it('passes with accented character', async () => expect(await rules.alpha({ value: 'jüstin' })).toBe(true))
|
||||
|
||||
it('passes with lots of accented characters', async () => expect(await rules.alpha({ value: 'àáâäïíôöÆ' })).toBe(true))
|
||||
|
||||
it('passes with lots of accented characters if invalid set', async () => expect(await rules.alpha({ value: 'àáâäïíôöÆ' }, 'russian')).toBe(true))
|
||||
|
||||
it('fails with lots of accented characters if latin', async () => expect(await rules.alpha({ value: 'àáâäïíôöÆ' }, 'latin')).toBe(false))
|
||||
|
||||
it('fails with numbers', async () => expect(await rules.alpha({ value: 'justin83' })).toBe(false))
|
||||
|
||||
it('fails with symbols', async () => expect(await rules.alpha({ value: '-justin' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if a date is after another date
|
||||
*/
|
||||
describe('number', () => {
|
||||
it('passes with simple number string', async () => expect(await rules.number({ value: '123' })).toBe(true))
|
||||
|
||||
it('passes with simple number', async () => expect(await rules.number({ value: 19832461234 })).toBe(true))
|
||||
|
||||
it('passes with float', async () => expect(await rules.number({ value: 198.32464 })).toBe(true))
|
||||
|
||||
it('passes with decimal in string', async () => expect(await rules.number({ value: '567.23' })).toBe(true))
|
||||
|
||||
it('fails with comma in number string', async () => expect(await rules.number({ value: '123,456' })).toBe(false))
|
||||
|
||||
it('fails with alpha', async () => expect(await rules.number({ value: '123sdf' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if a date alpha and numeric
|
||||
*/
|
||||
describe('alphanumeric', () => {
|
||||
it('passes with simple string', async () => expect(await rules.alphanumeric({ value: '567abc' })).toBe(true))
|
||||
|
||||
it('passes with long string', async () => expect(await rules.alphanumeric({ value: 'lkashdfla234osuihdfaisudgflakjsdbfla567sidufg' })).toBe(true))
|
||||
|
||||
it('passes with single character', async () => expect(await rules.alphanumeric({ value: 'z' })).toBe(true))
|
||||
|
||||
it('passes with accented character', async () => expect(await rules.alphanumeric({ value: 'jüst56in' })).toBe(true))
|
||||
|
||||
it('passes with lots of accented characters', async () => expect(await rules.alphanumeric({ value: 'àáâ7567567äïíôöÆ' })).toBe(true))
|
||||
|
||||
it('passes with lots of accented characters if invalid set', async () => expect(await rules.alphanumeric({ value: '123123àáâäï67íôöÆ' }, 'russian')).toBe(true))
|
||||
|
||||
it('fails with lots of accented characters if latin', async () => expect(await rules.alphanumeric({ value: 'àáâäï123123íôöÆ' }, 'latin')).toBe(false))
|
||||
|
||||
it('fails with decimals in', async () => expect(await rules.alphanumeric({ value: 'abcABC99.123' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if between
|
||||
*/
|
||||
describe('between', () => {
|
||||
it('passes with simple number', async () => expect(await rules.between({ value: 5 }, 0, 10)).toBe(true))
|
||||
|
||||
it('passes with simple number string', async () => expect(await rules.between({ value: '5' }, '0', '10')).toBe(true))
|
||||
|
||||
it('passes with decimal number string', async () => expect(await rules.between({ value: '0.5' }, '0', '1')).toBe(true))
|
||||
|
||||
it('passes with string length', async () => expect(await rules.between({ value: 'abc' }, 2, 4)).toBe(true))
|
||||
|
||||
it('fails with string length too long', async () => expect(await rules.between({ value: 'abcdef' }, 2, 4)).toBe(false))
|
||||
|
||||
it('fails with string length too short', async () => expect(await rules.between({ value: 'abc' }, 3, 10)).toBe(false))
|
||||
|
||||
it('fails with number to small', async () => expect(await rules.between({ value: 0 }, 3, 10)).toBe(false))
|
||||
|
||||
it('fails with number to large', async () => expect(await rules.between({ value: 15 }, 3, 10)).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if email.
|
||||
*
|
||||
* Note: testing is light, regular expression used is here: http://jsfiddle.net/ghvj4gy9/embedded/result,js/
|
||||
*/
|
||||
describe('email', () => {
|
||||
it('passes normal email', async () => expect(await rules.email({ value: 'dev+123@wearebraid.com' })).toBe(true))
|
||||
|
||||
it('passes numeric email', async () => expect(await rules.email({ value: '12345@google.com' })).toBe(true))
|
||||
|
||||
it('passes unicode email', async () => expect(await rules.email({ value: 'àlphä@❤️.ly' })).toBe(true))
|
||||
|
||||
it('passes numeric with new tld', async () => expect(await rules.email({ value: '12345@google.photography' })).toBe(true))
|
||||
|
||||
it('fails string without tld', async () => expect(await rules.email({ value: '12345@localhost' })).toBe(false))
|
||||
|
||||
it('fails string without tld', async () => expect(await rules.email({ value: '12345@localhost' })).toBe(false))
|
||||
|
||||
it('fails string without invalid name', async () => expect(await rules.email({ value: '1*(123)2345@localhost' })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Mime types.
|
||||
*/
|
||||
@ -395,31 +387,85 @@ describe('not', () => {
|
||||
})
|
||||
|
||||
/**
|
||||
* Confirm
|
||||
* Checks if a date is after another date
|
||||
*/
|
||||
describe('confirm', () => {
|
||||
it('passes when the values are the same strings', async () => expect(await rules.confirm(
|
||||
{ value: 'abc', name: 'password', getFormValues: () => ({ password_confirm: 'abc' }) }
|
||||
)).toBe(true))
|
||||
describe('number', () => {
|
||||
it('passes with simple number string', async () => expect(await rules.number({ value: '123' })).toBe(true))
|
||||
|
||||
it('passes when the values are the same integers', async () => expect(await rules.confirm(
|
||||
{ value: 4422132, name: 'xyz', getFormValues: () => ({ xyz_confirm: 4422132 }) }
|
||||
)).toBe(true))
|
||||
it('passes with simple number', async () => expect(await rules.number({ value: 19832461234 })).toBe(true))
|
||||
|
||||
it('passes when using a custom field', async () => expect(await rules.confirm(
|
||||
{ value: 4422132, name: 'name', getFormValues: () => ({ other_field: 4422132 }) },
|
||||
'other_field'
|
||||
)).toBe(true))
|
||||
it('passes with float', async () => expect(await rules.number({ value: 198.32464 })).toBe(true))
|
||||
|
||||
it('passes when using a field ends in _confirm', async () => expect(await rules.confirm(
|
||||
{ value: '$ecret', name: 'password_confirm', getFormValues: () => ({ password: '$ecret' }) }
|
||||
)).toBe(true))
|
||||
it('passes with decimal in string', async () => expect(await rules.number({ value: '567.23' })).toBe(true))
|
||||
|
||||
it('fails when using different strings', async () => expect(await rules.confirm(
|
||||
{ value: 'Justin', name: 'name', getFormValues: () => ({ name_confirm: 'Daniel' }) },
|
||||
)).toBe(false))
|
||||
it('fails with comma in number string', async () => expect(await rules.number({ value: '123,456' })).toBe(false))
|
||||
|
||||
it('fails when the types are different', async () => expect(await rules.confirm(
|
||||
{ value: '1234', name: 'num', getFormValues: () => ({ num_confirm: 1234 }) },
|
||||
)).toBe(false))
|
||||
it('fails with alpha', async () => expect(await rules.number({ value: '123sdf' })).toBe(false))
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* Required rule
|
||||
*/
|
||||
describe('required', () => {
|
||||
it('fails on empty string', async () => expect(await rules.required({ value: '' })).toBe(false))
|
||||
|
||||
it('fails on empty array', async () => expect(await rules.required({ value: [] })).toBe(false))
|
||||
|
||||
it('fails on empty object', async () => expect(await rules.required({ value: {} })).toBe(false))
|
||||
|
||||
it('fails on null', async () => expect(await rules.required({ value: null })).toBe(false))
|
||||
|
||||
it('passes with the number zero', async () => expect(await rules.required({ value: 0 })).toBe(true))
|
||||
|
||||
it('passes with the boolean false', async () => expect(await rules.required({ value: false })).toBe(true))
|
||||
|
||||
it('passes with a non empty array', async () => expect(await rules.required({ value: ['123'] })).toBe(true))
|
||||
|
||||
it('passes with a non empty object', async () => expect(await rules.required({ value: {a: 'b'} })).toBe(true))
|
||||
|
||||
it('passes with empty value if second argument is false', async () => expect(await rules.required({ value: '' }, false)).toBe(true))
|
||||
|
||||
it('passes with empty value if second argument is false string', async () => expect(await rules.required({ value: '' }, 'false')).toBe(true))
|
||||
|
||||
it('passes with FileUpload', async () => expect(await rules.required({ value: new FileUpload({ files: [{ name: 'j.png' }] }) })).toBe(true))
|
||||
|
||||
it('fails with empty FileUpload', async () => expect(await rules.required({ value: new FileUpload({ files: [] }) })).toBe(false))
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if value starts with a one of the specified Strings.
|
||||
*/
|
||||
describe('startsWith', () => {
|
||||
it('fails when value starting is not in stack of single value', async () => {
|
||||
expect(await rules.startsWith({ value: 'taco tuesday' }, 'pizza')).toBe(false)
|
||||
})
|
||||
|
||||
it('fails when value starting is not in stack of multiple values', async () => {
|
||||
expect(await rules.startsWith({ value: 'taco tuesday' }, 'pizza', 'coffee')).toBe(false)
|
||||
})
|
||||
|
||||
it('passes when stack consists of zero values', async () => {
|
||||
expect(await rules.startsWith({ value: 'taco tuesday' })).toBe(true)
|
||||
})
|
||||
|
||||
it('passes when value starting is in stack of single value', async () => {
|
||||
expect(await rules.startsWith({ value: 'taco tuesday' }, 'taco')).toBe(true)
|
||||
})
|
||||
|
||||
it('passes when value starting is in stack of multiple values', async () => {
|
||||
expect(await rules.startsWith({ value: 'taco tuesday' }, 'pizza', 'taco', 'coffee')).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Url rule.
|
||||
*
|
||||
* Note: these are just sanity checks because the actual package we use is
|
||||
* well tested: https://github.com/segmentio/is-url/blob/master/test/index.js
|
||||
*/
|
||||
describe('url', () => {
|
||||
it('passes with http://google.com', async () => expect(await rules.url({ value: 'http://google.com' })).toBe(true))
|
||||
|
||||
it('fails with google.com', async () => expect(await rules.url({ value: 'google.com' })).toBe(false))
|
||||
})
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { parseRules, regexForFormat, cloneDeep, isValueType } from '@/libs/utils'
|
||||
import { parseRules, regexForFormat, cloneDeep, isValueType, snakeCaseToCamelCase } from '@/libs/utils'
|
||||
import rules from '@/libs/rules'
|
||||
import FileUpload from '@/FileUpload';
|
||||
|
||||
@ -117,3 +117,25 @@ describe('cloneDeep', () => {
|
||||
expect(clone.b === c).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('snakeCaseToCamelCase', () => {
|
||||
it('converts underscore separated words to camelCase', () => {
|
||||
expect(snakeCaseToCamelCase('this_is_snake_case')).toBe('thisIsSnakeCase')
|
||||
})
|
||||
|
||||
it('has no effect on already camelCase words', () => {
|
||||
expect(snakeCaseToCamelCase('thisIsCamelCase')).toBe('thisIsCamelCase')
|
||||
})
|
||||
|
||||
it('does not capitalize the first word or strip first underscore if a phrase starts with an underscore', () => {
|
||||
expect(snakeCaseToCamelCase('_this_starts_with_an_underscore')).toBe('_thisStartsWithAnUnderscore')
|
||||
})
|
||||
|
||||
it('ignores double underscores anywhere in a word', () => {
|
||||
expect(snakeCaseToCamelCase('__unlikely__thing__')).toBe('__unlikely__thing__')
|
||||
})
|
||||
|
||||
it('has no effect hyphenated words', () => {
|
||||
expect(snakeCaseToCamelCase('not-a-good-name')).toBe('not-a-good-name')
|
||||
})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user