Skip to content

Commit

Permalink
fix(core): fix required validate with wrong order (#2508)
Browse files Browse the repository at this point in the history
* fix(core): fix required validate with wrong order

* chore: fix ci

* test: add more tests
  • Loading branch information
janryWang authored Nov 25, 2021
1 parent cadd63b commit f0ac991
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 35 deletions.
59 changes: 58 additions & 1 deletion packages/core/src/__tests__/field.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -519,12 +519,35 @@ test('setValidateRule', () => {
validator: 'phone',
})
)
const field4 = attach(
form.createField({
name: 'dd',
validator: { format: 'phone' },
})
)
const field5 = attach(
form.createField({
name: 'ee',
validator: [{ format: 'phone' }],
})
)
const field6 = attach(
form.createField({
name: 'ff',
})
)
field1.setValidatorRule('format', 'phone')
field2.setValidatorRule('max', 3)
field3.setValidatorRule('format', 'url')
field4.setValidatorRule('min', 3)
field5.setValidatorRule('min', 3)
field6.setValidatorRule('min', 3)
expect(field1.validator).toEqual([{ required: true }, { format: 'phone' }])
expect(field3.validator).toEqual({ format: 'url' })
expect(field2.validator).toEqual(['phone', { max: 3 }])
expect(field3.validator).toEqual({ format: 'url' })
expect(field4.validator).toEqual({ format: 'phone', min: 3 })
expect(field5.validator).toEqual([{ format: 'phone' }, { min: 3 }])
expect(field6.validator).toEqual({ min: 3 })
})

test('query', () => {
Expand Down Expand Up @@ -1528,6 +1551,40 @@ test('initial value with empty', () => {
})

test('field submit', async () => {
const form = attach(
createForm({
initialValues: {
aa: {
cc: 'cc',
},
bb: 'bb',
},
})
)
const childForm = attach(
form.createObjectField({
name: 'aa',
})
)
attach(
form.createField({
name: 'bb',
})
)
attach(
form.createField({
name: 'cc',
basePath: 'aa',
})
)
const onSubmit = jest.fn()
await childForm.submit(onSubmit)
expect(onSubmit).toBeCalledWith({
cc: 'cc',
})
})

test('field submit with error', async () => {
const form = attach(createForm())
const childForm = attach(
form.createObjectField({
Expand Down
31 changes: 31 additions & 0 deletions packages/core/src/__tests__/form.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1530,3 +1530,34 @@ test('validate will skip uneditable', async () => {
expect(bb.invalid).toBeFalsy()
expect(validator).toBeCalledTimes(3)
})

test('validator order with format', async () => {
const form = attach(createForm())

attach(
form.createField({
name: 'aa',
required: true,
validator: {
format: 'url',
message: 'custom',
},
})
)

attach(
form.createField({
name: 'bb',
required: true,
validator: (value) => {
if (!value) return ''
return value !== '111' ? 'custom' : ''
},
})
)
const results = await form.submit<any[]>(() => {}).catch((e) => e)
expect(results.map(({ messages }) => messages)).toEqual([
['The field value is required'],
['The field value is required'],
])
})
26 changes: 8 additions & 18 deletions packages/core/src/shared/internals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ export const setValidatorRule = (field: Field, name: string, value: any) => {
if (hasRule) {
if (isArr(field.validator)) {
field.validator = field.validator.map((desc: any) => {
if (hasOwnProperty.call(desc, name)) {
if (isPlainObj(desc) && hasOwnProperty.call(desc, name)) {
desc[name] = value
return desc
}
Expand All @@ -326,26 +326,16 @@ export const setValidatorRule = (field: Field, name: string, value: any) => {
} else {
field.validator.push(rule)
}
} else if (isPlainObj(field.validator)) {
field.validator[name] = value
} else if (field.validator) {
} else {
if (name === 'required') {
field.validator = [
{
[name]: value,
},
field.validator,
]
field.validator = [rule, field.validator]
} else if (isPlainObj(field.validator)) {
field.validator[name] = value
} else if (field.validator) {
field.validator = [field.validator, rule]
} else {
field.validator = [
field.validator,
{
[name]: value,
},
]
field.validator = rule
}
} else {
field.validator = [rule]
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions packages/validator/src/__tests__/validator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,3 +454,15 @@ test('validator template with format', async () => {
'123=123&123'
)
})

test('validator order with format', async () => {
hasError(
await validate('', [
{ required: true },
{
format: 'url',
},
]),
'The field value is required'
)
})
47 changes: 31 additions & 16 deletions packages/validator/src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,23 @@ export const parseValidatorDescriptions = <Context = any>(
})
}

export const parseIValidatorRules = (
rules: IValidatorRules
export const parseValidatorRules = (
rules: IValidatorRules = {}
): ValidatorParsedFunction[] => {
const rulesKeys = Object.keys(rules || {}).sort((key) =>
key === 'validator' ? 1 : -1
)
const getRulesKeys = (): string[] => {
const keys = []
if ('required' in rules) {
keys.push('required')
}
for (let key in rules) {
if (key === 'required' || key === 'validator') continue
keys.push(key)
}
if ('validator' in rules) {
keys.push('validator')
}
return keys
}
const getContext = (context: any, value: any) => {
return {
...rules,
Expand Down Expand Up @@ -112,11 +123,13 @@ export const parseIValidatorRules = (
}
}
}
return rulesKeys.reduce((buf, key) => {
return getRulesKeys().reduce((buf, key) => {
const callback = getValidateRules(key)
return callback
? buf.concat(createValidate(callback, getRuleMessage(rules, key)))
: buf
if (callback) {
const validator = createValidate(callback, getRuleMessage(rules, key))
return buf.concat(validator)
}
return buf
}, [])
}

Expand All @@ -125,11 +138,13 @@ export const parseValidator = <Context = any>(
options: IValidatorOptions = {}
) => {
const array = isArr(validator) ? validator : [validator]
const results: ValidatorParsedFunction<Context>[] = []
return array.reduce((buf, description) => {
const rules = parseValidatorDescription(description)
if (options?.triggerType && options.triggerType !== rules.triggerType)
return buf
return rules ? buf.concat(parseIValidatorRules(rules)) : buf
}, results)
return array.reduce<ValidatorParsedFunction<Context>[]>(
(buf, description) => {
const rules = parseValidatorDescription(description)
if (options?.triggerType && options.triggerType !== rules.triggerType)
return buf
return rules ? buf.concat(parseValidatorRules(rules)) : buf
},
[]
)
}

0 comments on commit f0ac991

Please sign in to comment.