Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add in rule for number (#44) #53

Merged
merged 1 commit into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const messages = {
'boolean': 'The value must be a boolean',

'number': 'The {{ field }} field must be a number',
'number.in': 'The selected {{ field }} is not in {{ values }}',
'min': 'The {{ field }} field must be at least {{ min }}',
'max': 'The {{ field }} field must not be greater than {{ max }}',
'range': 'The {{ field }} field must be between {{ min }} and {{ max }}',
Expand Down
8 changes: 8 additions & 0 deletions src/schema/number/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
negativeRule,
positiveRule,
withoutDecimalsRule,
inRule,
} from './rules.js'

/**
Expand Down Expand Up @@ -121,4 +122,11 @@ export class VineNumber extends BaseLiteralType<string | number, number, number>
clone(): this {
return new VineNumber(this.cloneOptions(), this.cloneValidations()) as this
}

/**
* Enforce the value to be in a list of allowed values
*/
in(values: number[]) {
return this.use(inRule({ values }))
}
}
16 changes: 16 additions & 0 deletions src/schema/number/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,19 @@ export const withoutDecimalsRule = createRule((value, _, field) => {
field.report(messages.withoutDecimals, 'withoutDecimals', field)
}
})

/**
* Enforce the value to be in a list of allowed values
*/
export const inRule = createRule<{ values: number[] }>((value, options, field) => {
/**
* Skip if the field is not valid.
*/
if (!field.isValid) {
return
}

if (!options.values.includes(value as number)) {
field.report(messages['number.in'], 'in', field, options)
}
})
37 changes: 37 additions & 0 deletions tests/unit/rules/number.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import { test } from '@japa/runner'
import { validator } from '../../../factories/main.js'
import {
inRule,
minRule,
maxRule,
rangeRule,
Expand Down Expand Up @@ -395,3 +396,39 @@ test.group('Number | withoutDecimals', () => {
validated.assertOutput(18)
})
})

test.group('Number | in', () => {
test('skip validation when value is not a number', () => {
const number = numberRule({})
const inArrayRule = inRule({ values: [1, 4] })
const validated = validator.execute([number, inArrayRule], 'foo')

validated.assertErrorsCount(1)
validated.assertError('The dummy field must be a number')
})

test('skip validation when value is not a number with bail mode disabled', () => {
const number = numberRule({})
const inArrayRule = inRule({ values: [1, 4] })
const validated = validator.bail(false).execute([number, inArrayRule], 'foo')

validated.assertErrorsCount(1)
validated.assertError('The dummy field must be a number')
})

test('work fine when value is in an array', () => {
const number = numberRule({})
const inArrayRule = inRule({ values: [1, 4] })
const validated = validator.execute([number, inArrayRule], 4)

validated.assertSucceeded()
})

test('fails when value is not in an array', () => {
const number = numberRule({})
const inArrayRule = inRule({ values: [1, 4] })
const validated = validator.execute([number, inArrayRule], 3)

validated.assertErrorsCount(1)
})
})
34 changes: 34 additions & 0 deletions tests/unit/schema/number.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { refsBuilder } from '@vinejs/compiler'
import { Vine } from '../../../src/vine/main.js'
import { IS_OF_TYPE, PARSE } from '../../../src/symbols.js'
import {
inRule,
maxRule,
minRule,
rangeRule,
Expand Down Expand Up @@ -743,4 +744,37 @@ test.group('VineNumber | applying rules', () => {
options: withoutDecimals.options,
})
})

test('apply in rule', ({ assert }) => {
const refs = refsBuilder()
const schema = vine.number().in([1, 2, 3])

assert.deepEqual(schema[PARSE]('*', refs, { toCamelCase: false }), {
type: 'literal',
fieldName: '*',
propertyName: '*',
bail: true,
allowNull: false,
isOptional: false,
parseFnId: undefined,
validations: [
{
implicit: false,
isAsync: false,
ruleFnId: 'ref://1',
},
{
implicit: false,
isAsync: false,
ruleFnId: 'ref://2',
},
],
})

const inArrayRule = inRule({ values: [1, 2, 3] })
assert.deepEqual(refs.toJSON()['ref://2'], {
validator: inArrayRule.rule.validator,
options: inArrayRule.options,
})
})
})
Loading