@@ -2991,6 +2991,68 @@ describe('form api', () => {
29912991 expect ( passconfirmField . state . meta . errors . length ) . toBe ( 0 )
29922992 } )
29932993
2994+ it ( 'should not leave linked fields stuck in isValidating when multiple setValue calls trigger concurrent async validation' , async ( ) => {
2995+ vi . useFakeTimers ( )
2996+
2997+ const validationFn = vi . fn ( )
2998+
2999+ const form = new FormApi ( {
3000+ defaultValues : {
3001+ street : '' ,
3002+ houseNo : '' ,
3003+ zipCode : '' ,
3004+ city : '' ,
3005+ } ,
3006+ } )
3007+
3008+ form . mount ( )
3009+
3010+ const street = new FieldApi ( {
3011+ form,
3012+ name : 'street' ,
3013+ validators : {
3014+ onChangeListenTo : [ 'houseNo' , 'zipCode' , 'city' ] ,
3015+ onChangeAsyncDebounceMs : 300 ,
3016+ onChangeAsync : async ( ) => {
3017+ await sleep ( 500 )
3018+ await validationFn ( )
3019+ return undefined
3020+ } ,
3021+ } ,
3022+ } )
3023+ const houseNo = new FieldApi ( { form, name : 'houseNo' } )
3024+ const zipCode = new FieldApi ( { form, name : 'zipCode' } )
3025+ const city = new FieldApi ( { form, name : 'city' } )
3026+
3027+ street . mount ( )
3028+ houseNo . mount ( )
3029+ zipCode . mount ( )
3030+ city . mount ( )
3031+
3032+ // Simulate browser autofill: all fields set in rapid succession
3033+ street . setValue ( 'Foo Street' )
3034+ houseNo . setValue ( '2' )
3035+ zipCode . setValue ( '12345' )
3036+ city . setValue ( 'Barrington' )
3037+
3038+ // Run debounce + async validation
3039+ await vi . runAllTimersAsync ( )
3040+
3041+ expect . soft ( validationFn ) . toHaveBeenCalledTimes ( 1 )
3042+
3043+ expect . soft ( street . getMeta ( ) . isValidating ) . toBe ( false )
3044+ expect . soft ( houseNo . getMeta ( ) . isValidating ) . toBe ( false )
3045+ expect . soft ( zipCode . getMeta ( ) . isValidating ) . toBe ( false )
3046+ expect . soft ( city . getMeta ( ) . isValidating ) . toBe ( false )
3047+
3048+ expect . soft ( form . state . isFieldsValidating ) . toBe ( false )
3049+ expect . soft ( form . state . isFieldsValid ) . toBe ( true )
3050+ expect . soft ( form . state . isValid ) . toBe ( true )
3051+ expect . soft ( form . state . canSubmit ) . toBe ( true )
3052+
3053+ vi . useRealTimers ( )
3054+ } )
3055+
29943056 it ( "should set field errors from the form's onMount validator" , async ( ) => {
29953057 const form = new FormApi ( {
29963058 defaultValues : {
0 commit comments