Skip to content

Commit

Permalink
feat: add support for comparing nested values in sameAs and notSameAs…
Browse files Browse the repository at this point in the history
… rules

Closes: #20
  • Loading branch information
thetutlage committed Nov 20, 2023
1 parent ce6c52c commit 628b4c7
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 6 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@japa/expect-type": "^2.0.0",
"@japa/runner": "^3.0.5",
"@swc/core": "^1.3.96",
"@types/dlv": "^1.1.4",
"@types/node": "^20.9.2",
"benchmark": "^2.1.4",
"c8": "^8.0.1",
Expand All @@ -63,6 +64,7 @@
"@types/validator": "^13.11.6",
"@vinejs/compiler": "^2.3.0",
"camelcase": "^8.0.0",
"dlv": "^1.1.3",
"normalize-url": "^8.0.0",
"validator": "^13.11.0"
},
Expand Down
25 changes: 19 additions & 6 deletions src/schema/string/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
* file that was distributed with this source code.
*/

import normalizeEmail from 'validator/lib/normalizeEmail.js'
import delve from 'dlv'
import camelcase from 'camelcase'
import normalizeUrl from 'normalize-url'
import escape from 'validator/lib/escape.js'
import type { FieldContext } from '@vinejs/compiler/types'
import normalizeEmail from 'validator/lib/normalizeEmail.js'

import { helpers } from '../../vine/helpers.js'
import { messages } from '../../defaults.js'
import { helpers } from '../../vine/helpers.js'
import { createRule } from '../../vine/create_rule.js'
import type {
URLOptions,
Expand All @@ -26,8 +29,18 @@ import type {
AlphaNumericOptions,
NormalizeEmailOptions,
} from '../../types.js'
import camelcase from 'camelcase'
import normalizeUrl from 'normalize-url'

/**
* Returns the nested value from the field root
* object or the sibling value from the field
* parent object
*/
function getNestedValue(key: string, field: FieldContext) {
if (key.indexOf('.') > -1) {
return delve(field.data, key)
}
return field.parent[key]
}

/**
* Validates the value to be a string
Expand Down Expand Up @@ -280,7 +293,7 @@ export const sameAsRule = createRule<{ otherField: string }>((value, options, fi
return
}

const input = field.parent[options.otherField]
const input = getNestedValue(options.otherField, field)

/**
* Performing validation and reporting error
Expand All @@ -302,7 +315,7 @@ export const notSameAsRule = createRule<{ otherField: string }>((value, options,
return
}

const input = field.parent[options.otherField]
const input = getNestedValue(options.otherField, field)

/**
* Performing validation and reporting error
Expand Down
81 changes: 81 additions & 0 deletions tests/unit/rules/string.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,44 @@ test.group('String | sameAs', () => {
},
},
},
{
errorsCount: 1,
rule: sameAsRule({ otherField: 'old.password' }),
value: 'foo',
field: {
name: 'password_confirmation',
parent: {},
},
error: 'The password_confirmation field and old.password field must be the same',
},
{
errorsCount: 1,
rule: sameAsRule({ otherField: 'old.password' }),
value: 'foo',
field: {
name: 'password_confirmation',
parent: {},
data: {
old: {
password: 'bar',
},
},
},
error: 'The password_confirmation field and old.password field must be the same',
},
{
rule: sameAsRule({ otherField: 'old.password' }),
value: 'foo',
field: {
name: 'password_confirmation',
parent: {},
data: {
old: {
password: 'foo',
},
},
},
},
])
.run(stringRuleValidator)
})
Expand Down Expand Up @@ -825,6 +863,49 @@ test.group('String | notSameAs', () => {
},
},
},
{
errorsCount: 1,
rule: notSameAsRule({ otherField: 'old.password' }),
value: 'foo',
field: {
name: 'password_confirmation',
parent: {
password: '',
},
data: {
old: {
password: 'foo',
},
},
},
error: 'The password_confirmation field and old.password field must be different',
},
{
rule: notSameAsRule({ otherField: 'old.password' }),
value: 'foo',
field: {
name: 'password_confirmation',
parent: {
password: '',
},
data: {
old: {
password: 'bar',
},
},
},
},
{
rule: notSameAsRule({ otherField: 'old.password' }),
value: 'foo',
field: {
name: 'password_confirmation',
parent: {
password: '',
},
data: {},
},
},
])
.run(stringRuleValidator)
})
Expand Down

0 comments on commit 628b4c7

Please sign in to comment.