@@ -2,11 +2,16 @@ import * as React from 'react';
22import { jest } from '@jest/globals' ;
33import { QueryClient , QueryClientProvider } from '@tanstack/react-query' ;
44import { render , waitFor } from '@testing-library/react' ;
5- import type { CreateResult , RaRecord , UpdateResult } from 'react-admin' ;
6- import { DataProviderContext , testDataProvider } from 'react-admin' ;
5+ import {
6+ type CreateResult ,
7+ DataProviderContext ,
8+ type MutationMode ,
9+ type RaRecord ,
10+ type UpdateResult ,
11+ testDataProvider ,
12+ } from 'react-admin' ;
713import { MemoryRouter , Route , Routes } from 'react-router-dom' ;
814
9- import useOnSubmit from './useOnSubmit.js' ;
1015import schemaAnalyzer from './hydra/schemaAnalyzer.js' ;
1116import { API_FIELDS_DATA } from './__fixtures__/parsedData.js' ;
1217
@@ -23,6 +28,16 @@ const onSubmitProps = {
2328} ;
2429
2530jest . mock ( './getIdentifierValue.js' ) ;
31+ const notify = jest . fn ( ) ;
32+ const reactAdminActual = jest . requireActual ( 'react-admin' ) as Record <
33+ string ,
34+ unknown
35+ > ;
36+ jest . mock ( 'react-admin' , ( ) => ( {
37+ __esModule : true ,
38+ ...reactAdminActual ,
39+ useNotify : ( ) => notify ,
40+ } ) ) ;
2641
2742test . each ( [
2843 {
@@ -41,6 +56,7 @@ test.each([
4156] ) (
4257 'Call create with file input ($name)' ,
4358 async ( values : Omit < RaRecord , 'id' > ) => {
59+ const { default : useOnSubmit } = await import ( './useOnSubmit.js' ) ;
4460 let save ;
4561 const Dummy = ( ) => {
4662 const onSubmit = useOnSubmit ( onSubmitProps ) ;
@@ -93,6 +109,7 @@ test.each([
93109 cover : null ,
94110 } ,
95111] ) ( 'Call update without file inputs ($name)' , async ( values : RaRecord ) => {
112+ const { default : useOnSubmit } = await import ( './useOnSubmit.js' ) ;
96113 let save ;
97114 const Dummy = ( ) => {
98115 const onSubmit = useOnSubmit ( onSubmitProps ) ;
@@ -125,3 +142,55 @@ test.each([
125142 } ) ;
126143 } ) ;
127144} ) ;
145+
146+ test . each `
147+ submissionErrors | mutationMode | shouldNotify
148+ ${ { name : 'Required' } } | ${ 'pessimistic' } | ${ false }
149+ ${ { name : 'Required' } } | ${ 'optimistic' } | ${ true }
150+ ${ { name : 'Required' } } | ${ 'undoable' } | ${ true }
151+ ${ null } | ${ 'pessimistic' } | ${ true }
152+ ` (
153+ 'notification handling on validation errors ($submissionErrors, $mutationMode)' ,
154+ async ( { submissionErrors, mutationMode, shouldNotify } ) => {
155+ const { default : useOnSubmit } = await import ( './useOnSubmit.js' ) ;
156+ notify . mockClear ( ) ;
157+ dataProvider . create = jest . fn ( ( ) =>
158+ Promise . reject ( new Error ( 'Service Unavailable' ) ) ,
159+ ) ;
160+
161+ let save ;
162+ const Dummy = ( ) => {
163+ const onSubmit = useOnSubmit ( {
164+ ...onSubmitProps ,
165+ mutationMode : mutationMode as MutationMode ,
166+ schemaAnalyzer : {
167+ ...onSubmitProps . schemaAnalyzer ,
168+ getSubmissionErrors : ( ) => submissionErrors ,
169+ } ,
170+ } ) ;
171+ save = onSubmit ;
172+ return < span /> ;
173+ } ;
174+
175+ render (
176+ < DataProviderContext . Provider value = { dataProvider } >
177+ < QueryClientProvider client = { new QueryClient ( ) } >
178+ < MemoryRouter initialEntries = { [ '/books/create' ] } >
179+ < Routes >
180+ < Route path = "/books/create" element = { < Dummy /> } />
181+ </ Routes >
182+ </ MemoryRouter >
183+ </ QueryClientProvider >
184+ </ DataProviderContext . Provider > ,
185+ ) ;
186+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
187+ // @ts -ignore
188+ const errors = await save ( { author : 'Author 1' } ) ;
189+
190+ await waitFor ( ( ) => {
191+ expect ( dataProvider . create ) . toHaveBeenCalled ( ) ;
192+ } ) ;
193+ ( shouldNotify ? expect ( notify ) : expect ( notify ) . not ) . toHaveBeenCalled ( ) ;
194+ expect ( errors ) . toEqual ( submissionErrors ?? { } ) ;
195+ } ,
196+ ) ;
0 commit comments