1
0
mirror of synced 2025-02-16 20:53:13 +03:00

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:
Andrew Boyd 2020-03-03 06:53:04 -05:00 committed by GitHub
parent c7a3e1a015
commit 4bfe43719d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 407 additions and 278 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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
*/

View File

@ -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 {

View File

@ -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 doesnt end with a valid value.`
}
return `${value}” doesnt 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 doesnt start with a valid value.`
}
return `${value}” doesnt start with a valid value.`
},
/**
* Value is not a url.
*/

View File

@ -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 tomorrows 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 yesterdays 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 tomorrows 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 yesterdays 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 tomorrows 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 yesterdays 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 tomorrows 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 yesterdays 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))
})

View File

@ -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')
})
})