11import * as React from 'react'
2- import { act , render , cleanup } from '@testing-library/react'
2+ import { act , render , cleanup , waitFor } from '@testing-library/react'
33import '@testing-library/jest-dom'
44import arrayMutators from 'final-form-arrays'
55import { ErrorBoundary } from './testUtils'
6- import { Form , useField } from 'react-final-form'
6+ import { Form , useField , useFormState } from 'react-final-form'
77import useFieldArray from './useFieldArray'
8+ import { ARRAY_ERROR } from 'final-form'
89
910const onSubmitMock = ( values : any ) => { }
1011
@@ -41,7 +42,11 @@ describe('FieldArray', () => {
4142 return null
4243 }
4344 render (
44- < Form onSubmit = { onSubmitMock } mutators = { arrayMutators as any } subscription = { { } } >
45+ < Form
46+ onSubmit = { onSubmitMock }
47+ mutators = { arrayMutators as any }
48+ subscription = { { } }
49+ >
4550 { ( ) => (
4651 < form >
4752 < MyFieldArray />
@@ -65,9 +70,9 @@ describe('FieldArray', () => {
6570 // undefined is passed instead of a no-op function that always returns undefined.
6671 // This prevents final-form from tracking this field as having a validator,
6772 // which would trigger unnecessary form-wide validation.
68-
73+
6974 const useFieldSpy = jest . spyOn ( require ( 'react-final-form' ) , 'useField' )
70-
75+
7176 const MyFieldArray = ( ) => {
7277 const fieldArray = useFieldArray ( 'names' )
7378 return null
@@ -89,17 +94,17 @@ describe('FieldArray', () => {
8994
9095 // Verify that useField was called with validate: undefined
9196 const useFieldCalls = useFieldSpy . mock . calls
92- const relevantCall = useFieldCalls . find ( call => call [ 0 ] === 'names' )
97+ const relevantCall = useFieldCalls . find ( ( call ) => call [ 0 ] === 'names' )
9398 expect ( relevantCall ) . toBeDefined ( )
9499 expect ( relevantCall ! [ 1 ] . validate ) . toBeUndefined ( )
95-
100+
96101 useFieldSpy . mockRestore ( )
97102 } )
98103
99104 it ( 'should call validator when validate prop is provided' , ( ) => {
100105 const fieldValidate = jest . fn ( ( ) => undefined )
101106 const fieldArraySpy = jest . fn ( )
102-
107+
103108 const MyFieldArray = ( ) => {
104109 const fieldArray = useFieldArray ( 'names' , { validate : fieldValidate } )
105110 fieldArraySpy ( fieldArray )
@@ -126,11 +131,115 @@ describe('FieldArray', () => {
126131
127132 // Get the last call before mutations
128133 const lastCallBeforeMutations = fieldArraySpy . mock . calls . length - 1
129-
134+
130135 // Push an item to trigger validation again
131- act ( ( ) => fieldArraySpy . mock . calls [ lastCallBeforeMutations ] [ 0 ] . fields . push ( 'alice' ) )
136+ act ( ( ) =>
137+ fieldArraySpy . mock . calls [ lastCallBeforeMutations ] [ 0 ] . fields . push ( 'alice' )
138+ )
132139
133140 // Field validation should be called again after mutation
134141 expect ( fieldValidate . mock . calls . length ) . toBeGreaterThan ( initialCalls )
135142 } )
143+
144+ it ( 'should handle array errors' , ( ) => {
145+ const spy = jest . fn ( )
146+ const MyFieldArray = ( ) => {
147+ spy ( useFieldArray ( 'names' , { validate : ( values ) => [ 'required' ] } ) )
148+ return null
149+ }
150+ render (
151+ < Form
152+ onSubmit = { onSubmitMock }
153+ mutators = { arrayMutators as any }
154+ subscription = { { } }
155+ >
156+ { ( ) => (
157+ < form >
158+ < MyFieldArray />
159+ </ form >
160+ ) }
161+ </ Form >
162+ )
163+
164+ expect ( spy ) . toHaveBeenCalledWith (
165+ expect . objectContaining ( {
166+ meta : expect . objectContaining ( {
167+ error : [ 'required' ]
168+ } )
169+ } )
170+ )
171+ } )
172+
173+ it ( 'should handle string error' , ( ) => {
174+ const spy = jest . fn ( )
175+ const spyState = jest . fn ( )
176+ const MyFieldArray = ( ) => {
177+ spy ( useFieldArray ( 'names' , { validate : ( values ) => 'failed' } ) )
178+ return null
179+ }
180+ const Debug = ( ) => {
181+ spyState ( useFormState ( ) . errors )
182+ return null
183+ }
184+ render (
185+ < Form
186+ onSubmit = { onSubmitMock }
187+ mutators = { arrayMutators as any }
188+ subscription = { { } }
189+ >
190+ { ( ) => (
191+ < form >
192+ < MyFieldArray />
193+ < Debug />
194+ </ form >
195+ ) }
196+ </ Form >
197+ )
198+
199+ expect ( spy ) . toHaveBeenCalledWith (
200+ expect . objectContaining ( {
201+ meta : expect . objectContaining ( {
202+ error : 'failed'
203+ } )
204+ } )
205+ )
206+ const expected : any [ ] = [ ]
207+ ; ( expected as any ) [ ARRAY_ERROR ] = 'failed'
208+
209+ expect ( spyState ) . toHaveBeenCalledWith ( { names : expected } )
210+ } )
211+ it ( 'should handle Promises errors' , async ( ) => {
212+ const spy = jest . fn ( )
213+ const MyFieldArray = ( ) => {
214+ spy (
215+ useFieldArray ( 'names' , {
216+ validate : ( values ) => Promise . resolve ( [ 'await fail' ] )
217+ } )
218+ )
219+ return null
220+ }
221+ render (
222+ < Form
223+ onSubmit = { onSubmitMock }
224+ mutators = { arrayMutators as any }
225+ subscription = { { } }
226+ >
227+ { ( ) => (
228+ < form >
229+ < MyFieldArray />
230+ </ form >
231+ ) }
232+ </ Form >
233+ )
234+
235+ waitFor ( ( ) =>
236+ expect ( spy ) . toHaveBeenCalledWith (
237+ expect . objectContaining ( {
238+ meta : expect . objectContaining ( {
239+ error : [ 'await fail' ]
240+ } )
241+ } )
242+ )
243+ )
244+ } )
136245} )
0 commit comments