From 4c1cfedaba465285405efea255aa55704d3b6809 Mon Sep 17 00:00:00 2001 From: Janry Date: Thu, 30 Sep 2021 16:07:00 +0800 Subject: [PATCH] fix(core): fix validate skip (#2265) --- packages/core/src/__tests__/form.spec.ts | 213 +++++++++++++++++++++++ packages/core/src/models/Field.ts | 6 +- packages/core/src/shared/internals.ts | 15 +- 3 files changed, 224 insertions(+), 10 deletions(-) diff --git a/packages/core/src/__tests__/form.spec.ts b/packages/core/src/__tests__/form.spec.ts index 49f81866e04..2a298e4b8a3 100644 --- a/packages/core/src/__tests__/form.spec.ts +++ b/packages/core/src/__tests__/form.spec.ts @@ -1244,3 +1244,216 @@ test('designable form', () => { expect(form.values.aa).toEqual(321) expect(form.initialValues.bb).toEqual(321) }) + +test('validate will skip display none', async () => { + const form = attach(createForm()) + const validator = jest.fn() + const aa = attach( + form.createField({ + name: 'aa', + validator() { + validator() + return 'error' + }, + }) + ) + const bb = attach( + form.createField({ + name: 'bb', + validator() { + validator() + return 'error' + }, + }) + ) + try { + await form.validate() + } catch (e) { + expect(e).toEqual([ + { + triggerType: 'onInput', + type: 'error', + code: 'ValidateError', + messages: ['error'], + address: 'aa', + path: 'aa', + }, + { + triggerType: 'onInput', + type: 'error', + code: 'ValidateError', + messages: ['error'], + address: 'bb', + path: 'bb', + }, + ]) + } + expect(aa.invalid).toBeTruthy() + expect(bb.invalid).toBeTruthy() + expect(validator).toBeCalledTimes(2) + aa.display = 'none' + try { + await form.validate() + } catch (e) { + expect(e).toEqual([ + { + triggerType: 'onInput', + type: 'error', + code: 'ValidateError', + messages: ['error'], + address: 'bb', + path: 'bb', + }, + ]) + } + expect(aa.invalid).toBeFalsy() + expect(bb.invalid).toBeTruthy() + expect(validator).toBeCalledTimes(3) + bb.display = 'none' + await form.validate() + expect(aa.invalid).toBeFalsy() + expect(bb.invalid).toBeFalsy() + expect(validator).toBeCalledTimes(3) +}) + +test('validate will skip unmounted', async () => { + const form = attach(createForm()) + const validator = jest.fn() + const aa = attach( + form.createField({ + name: 'aa', + validator() { + validator() + return 'error' + }, + }) + ) + const bb = attach( + form.createField({ + name: 'bb', + validator() { + validator() + return 'error' + }, + }) + ) + try { + await form.validate() + } catch (e) { + expect(e).toEqual([ + { + triggerType: 'onInput', + type: 'error', + code: 'ValidateError', + messages: ['error'], + address: 'aa', + path: 'aa', + }, + { + triggerType: 'onInput', + type: 'error', + code: 'ValidateError', + messages: ['error'], + address: 'bb', + path: 'bb', + }, + ]) + } + expect(aa.invalid).toBeTruthy() + expect(bb.invalid).toBeTruthy() + expect(validator).toBeCalledTimes(2) + aa.onUnmount() + try { + await form.validate() + } catch (e) { + expect(e).toEqual([ + { + triggerType: 'onInput', + type: 'error', + code: 'ValidateError', + messages: ['error'], + address: 'bb', + path: 'bb', + }, + ]) + } + expect(aa.invalid).toBeFalsy() + expect(bb.invalid).toBeTruthy() + expect(validator).toBeCalledTimes(3) + bb.onUnmount() + await form.validate() + expect(aa.invalid).toBeFalsy() + expect(bb.invalid).toBeFalsy() + expect(validator).toBeCalledTimes(3) +}) + +test('validate will skip uneditable', async () => { + const form = attach(createForm()) + const validator = jest.fn() + const aa = attach( + form.createField({ + name: 'aa', + validator() { + validator() + return 'error' + }, + }) + ) + const bb = attach( + form.createField({ + name: 'bb', + validator() { + validator() + return 'error' + }, + }) + ) + try { + await form.validate() + } catch (e) { + expect(e).toEqual([ + { + triggerType: 'onInput', + type: 'error', + code: 'ValidateError', + messages: ['error'], + address: 'aa', + path: 'aa', + }, + { + triggerType: 'onInput', + type: 'error', + code: 'ValidateError', + messages: ['error'], + address: 'bb', + path: 'bb', + }, + ]) + } + expect(aa.invalid).toBeTruthy() + expect(bb.invalid).toBeTruthy() + expect(validator).toBeCalledTimes(2) + aa.editable = false + try { + await form.validate() + } catch (e) { + expect(e).toEqual([ + { + triggerType: 'onInput', + type: 'error', + code: 'ValidateError', + messages: ['error'], + address: 'bb', + path: 'bb', + }, + ]) + } + expect(aa.invalid).toBeFalsy() + expect(bb.invalid).toBeTruthy() + expect(validator).toBeCalledTimes(3) + bb.editable = false + await form.validate() + expect(aa.invalid).toBeFalsy() + expect(bb.invalid).toBeFalsy() + expect(validator).toBeCalledTimes(3) +}) diff --git a/packages/core/src/models/Field.ts b/packages/core/src/models/Field.ts index 0dea099e47b..6e7bb92e8ae 100644 --- a/packages/core/src/models/Field.ts +++ b/packages/core/src/models/Field.ts @@ -253,9 +253,9 @@ export class Field< } ), reaction( - () => this.pattern, - (pattern) => { - if (pattern !== 'editable') { + () => [this.pattern, this.unmounted], + ([pattern, unmounted]) => { + if (pattern !== 'editable' || unmounted) { this.setFeedback({ type: 'error', messages: [], diff --git a/packages/core/src/shared/internals.ts b/packages/core/src/shared/internals.ts index 472c249136e..8db6e021486 100644 --- a/packages/core/src/shared/internals.ts +++ b/packages/core/src/shared/internals.ts @@ -255,17 +255,18 @@ export const validateToFeedbacks = async ( field: Field, triggerType?: ValidatorTriggerType ) => { + if ( + field.pattern !== 'editable' || + field.display !== 'visible' || + field.unmounted + ) + return {} + const results = await validate(field.value, field.validator, { triggerType, validateFirst: field.props.validateFirst || field.form.props.validateFirst, context: field, }) - const takeSkipCondition = () => { - if (field.display !== 'visible') return true - if (field.pattern !== 'editable') return true - if (field.unmounted) return true - return false - } batch(() => { each(results, (messages, type) => { @@ -273,7 +274,7 @@ export const validateToFeedbacks = async ( triggerType, type, code: pascalCase(`validate-${type}`), - messages: takeSkipCondition() ? [] : messages, + messages: messages, } as any) }) })