@@ -4877,6 +4877,154 @@ describe('validateForm()', () => {
48774877 errors = node . querySelectorAll ( '.error-detail' ) ;
48784878 expect ( errors ) . toHaveLength ( 0 ) ;
48794879 } ) ;
4880+
4881+ it ( 'Should keep non-blocking extraErrors in state when schema is valid and extraErrorsBlockSubmit is not set' , ( ) => {
4882+ const formRef = createRef < Form > ( ) ;
4883+ const schema : RJSFSchema = {
4884+ type : 'object' ,
4885+ properties : {
4886+ foo : { type : 'string' } ,
4887+ } ,
4888+ } ;
4889+ const extraErrors = {
4890+ foo : {
4891+ __errors : [ 'async error for foo' ] ,
4892+ } ,
4893+ } as unknown as ErrorSchema ;
4894+ const props : NoValFormProps = {
4895+ ref : formRef ,
4896+ schema,
4897+ formData : { foo : 'valid' } ,
4898+ extraErrors,
4899+ } ;
4900+ const { onError } = createFormComponent ( props ) ;
4901+
4902+ let result : boolean | undefined ;
4903+ act ( ( ) => {
4904+ result = formRef . current ! . validateForm ( ) ;
4905+ } ) ;
4906+
4907+ // Should return true (non-blocking)
4908+ expect ( result ) . toBe ( true ) ;
4909+ // extraErrors should remain visible in state
4910+ expect ( formRef . current ! . state . errors ) . toHaveLength ( 1 ) ;
4911+ expect ( formRef . current ! . state . errors [ 0 ] . message ) . toBe ( 'async error for foo' ) ;
4912+ expect ( formRef . current ! . state . errorSchema ) . toEqual ( extraErrors ) ;
4913+ // onError should NOT be called for non-blocking errors
4914+ expect ( onError ) . not . toHaveBeenCalled ( ) ;
4915+ } ) ;
4916+
4917+ it ( 'Should return false and call onError when extraErrors are present with extraErrorsBlockSubmit set' , ( ) => {
4918+ const formRef = createRef < Form > ( ) ;
4919+ const schema : RJSFSchema = {
4920+ type : 'object' ,
4921+ properties : {
4922+ foo : { type : 'string' } ,
4923+ } ,
4924+ } ;
4925+ const extraErrors = {
4926+ foo : {
4927+ __errors : [ 'blocking async error' ] ,
4928+ } ,
4929+ } as unknown as ErrorSchema ;
4930+ const props : NoValFormProps = {
4931+ ref : formRef ,
4932+ schema,
4933+ formData : { foo : 'valid' } ,
4934+ extraErrors,
4935+ extraErrorsBlockSubmit : true ,
4936+ } ;
4937+ const { onError } = createFormComponent ( props ) ;
4938+
4939+ let result : boolean | undefined ;
4940+ act ( ( ) => {
4941+ result = formRef . current ! . validateForm ( ) ;
4942+ } ) ;
4943+
4944+ // Should return false (blocking)
4945+ expect ( result ) . toBe ( false ) ;
4946+ // Merged errors should be in state
4947+ expect ( formRef . current ! . state . errors ) . toHaveLength ( 1 ) ;
4948+ expect ( formRef . current ! . state . errors [ 0 ] . message ) . toBe ( 'blocking async error' ) ;
4949+ // onError SHOULD be called
4950+ expect ( onError ) . toHaveBeenCalledWith (
4951+ expect . arrayContaining ( [ expect . objectContaining ( { message : 'blocking async error' } ) ] ) ,
4952+ ) ;
4953+ } ) ;
4954+
4955+ it ( 'Should show both schema and extraErrors in state when schema is invalid regardless of extraErrorsBlockSubmit' , ( ) => {
4956+ const formRef = createRef < Form > ( ) ;
4957+ const schema : RJSFSchema = {
4958+ type : 'object' ,
4959+ required : [ 'foo' ] ,
4960+ properties : {
4961+ foo : { type : 'string' } ,
4962+ } ,
4963+ } ;
4964+ const extraErrors = {
4965+ foo : {
4966+ __errors : [ 'async error for foo' ] ,
4967+ } ,
4968+ } as unknown as ErrorSchema ;
4969+ const props : NoValFormProps = {
4970+ ref : formRef ,
4971+ schema,
4972+ formData : { } ,
4973+ extraErrors,
4974+ // extraErrorsBlockSubmit intentionally omitted
4975+ } ;
4976+ createFormComponent ( props ) ;
4977+
4978+ let result : boolean | undefined ;
4979+ act ( ( ) => {
4980+ result = formRef . current ! . validateForm ( ) ;
4981+ } ) ;
4982+
4983+ // Schema error blocks submission → false
4984+ expect ( result ) . toBe ( false ) ;
4985+ // Both schema error and extra error should be in state
4986+ const errorMessages = formRef . current ! . state . errors . map ( ( e ) => e . message ) ;
4987+ expect ( errorMessages ) . toContain ( "must have required property 'foo'" ) ;
4988+ expect ( errorMessages ) . toContain ( 'async error for foo' ) ;
4989+ } ) ;
4990+
4991+ it ( 'Should clear extraErrors from state when extraErrors prop is removed and validateForm is called again' , ( ) => {
4992+ const formRef = createRef < Form > ( ) ;
4993+ const schema : RJSFSchema = {
4994+ type : 'object' ,
4995+ properties : {
4996+ foo : { type : 'string' } ,
4997+ } ,
4998+ } ;
4999+ const extraErrors = {
5000+ foo : {
5001+ __errors : [ 'async error for foo' ] ,
5002+ } ,
5003+ } as unknown as ErrorSchema ;
5004+ const props : NoValFormProps = {
5005+ ref : formRef ,
5006+ schema,
5007+ formData : { foo : 'valid' } ,
5008+ extraErrors,
5009+ } ;
5010+ const { rerender } = createFormComponent ( props ) ;
5011+
5012+ // First call: extraErrors should appear in state
5013+ act ( ( ) => {
5014+ formRef . current ! . validateForm ( ) ;
5015+ } ) ;
5016+ expect ( formRef . current ! . state . errors ) . toHaveLength ( 1 ) ;
5017+
5018+ // Rerender without extraErrors
5019+ rerender ( { ...props , extraErrors : undefined } ) ;
5020+
5021+ // Second call: no extraErrors, no schema errors → state should be cleared
5022+ act ( ( ) => {
5023+ formRef . current ! . validateForm ( ) ;
5024+ } ) ;
5025+ expect ( formRef . current ! . state . errors ) . toHaveLength ( 0 ) ;
5026+ expect ( formRef . current ! . state . errorSchema ) . toEqual ( { } ) ;
5027+ } ) ;
48805028} ) ;
48815029
48825030describe ( 'setFieldValue()' , ( ) => {
0 commit comments