@@ -100,6 +100,332 @@ describe('useMutation', () => {
100100 expect ( queryByRole ( 'heading' ) ) . toBeNull ( )
101101 } )
102102
103+ it ( 'should call mutate callbacks when useMutation has no callbacks' , async ( ) => {
104+ const callbacks : Array < string > = [ ]
105+
106+ function Page ( ) {
107+ const { mutate } = useMutation ( {
108+ mutationFn : ( text : string ) => sleep ( 10 ) . then ( ( ) => text ) ,
109+ } )
110+
111+ return (
112+ < button
113+ onClick = { ( ) =>
114+ mutate ( 'todo' , {
115+ onSuccess : ( ) => {
116+ callbacks . push ( 'mutate.onSuccess' )
117+ } ,
118+ onSettled : ( ) => {
119+ callbacks . push ( 'mutate.onSettled' )
120+ } ,
121+ } )
122+ }
123+ >
124+ mutate
125+ </ button >
126+ )
127+ }
128+
129+ const rendered = renderWithClient ( queryClient , < Page /> )
130+
131+ fireEvent . click ( rendered . getByRole ( 'button' , { name : / m u t a t e / i } ) )
132+ await vi . advanceTimersByTimeAsync ( 10 )
133+
134+ expect ( callbacks ) . toEqual ( [ 'mutate.onSuccess' , 'mutate.onSettled' ] )
135+ } )
136+
137+ it ( 'should call mutateAsync callbacks when useMutation has no callbacks' , async ( ) => {
138+ const callbacks : Array < string > = [ ]
139+
140+ function Page ( ) {
141+ const { mutateAsync } = useMutation ( {
142+ mutationFn : ( text : string ) => sleep ( 10 ) . then ( ( ) => text ) ,
143+ } )
144+
145+ useEffect ( ( ) => {
146+ setActTimeout ( async ( ) => {
147+ await mutateAsync ( 'todo' , {
148+ onSuccess : ( ) => {
149+ callbacks . push ( 'mutateAsync.onSuccess' )
150+ } ,
151+ onSettled : ( ) => {
152+ callbacks . push ( 'mutateAsync.onSettled' )
153+ } ,
154+ } )
155+ } , 0 )
156+ } , [ mutateAsync ] )
157+
158+ return null
159+ }
160+
161+ renderWithClient ( queryClient , < Page /> )
162+
163+ await vi . advanceTimersByTimeAsync ( 10 )
164+
165+ expect ( callbacks ) . toEqual ( [
166+ 'mutateAsync.onSuccess' ,
167+ 'mutateAsync.onSettled' ,
168+ ] )
169+ } )
170+
171+ it ( 'should call mutate error callbacks when useMutation has no callbacks' , async ( ) => {
172+ const callbacks : Array < string > = [ ]
173+
174+ function Page ( ) {
175+ const { mutate } = useMutation ( {
176+ mutationFn : ( _text : string ) =>
177+ sleep ( 10 ) . then ( ( ) => {
178+ throw new Error ( 'oops' )
179+ } ) ,
180+ } )
181+
182+ return (
183+ < button
184+ onClick = { ( ) =>
185+ mutate ( 'todo' , {
186+ onError : ( ) => {
187+ callbacks . push ( 'mutate.onError' )
188+ } ,
189+ onSettled : ( ) => {
190+ callbacks . push ( 'mutate.onSettled' )
191+ } ,
192+ } )
193+ }
194+ >
195+ mutate
196+ </ button >
197+ )
198+ }
199+
200+ const rendered = renderWithClient ( queryClient , < Page /> )
201+
202+ fireEvent . click ( rendered . getByRole ( 'button' , { name : / m u t a t e / i } ) )
203+ await vi . advanceTimersByTimeAsync ( 10 )
204+
205+ expect ( callbacks ) . toEqual ( [ 'mutate.onError' , 'mutate.onSettled' ] )
206+ } )
207+
208+ it ( 'should call mutateAsync error callbacks when useMutation has no callbacks' , async ( ) => {
209+ const callbacks : Array < string > = [ ]
210+
211+ function Page ( ) {
212+ const { mutateAsync } = useMutation ( {
213+ mutationFn : async ( _text : string ) =>
214+ sleep ( 10 ) . then ( ( ) => {
215+ throw new Error ( 'oops' )
216+ } ) ,
217+ } )
218+
219+ useEffect ( ( ) => {
220+ setActTimeout ( async ( ) => {
221+ try {
222+ await mutateAsync ( 'todo' , {
223+ onError : ( ) => {
224+ callbacks . push ( 'mutateAsync.onError' )
225+ } ,
226+ onSettled : ( ) => {
227+ callbacks . push ( 'mutateAsync.onSettled' )
228+ } ,
229+ } )
230+ } catch { }
231+ } , 0 )
232+ } , [ mutateAsync ] )
233+
234+ return null
235+ }
236+
237+ renderWithClient ( queryClient , < Page /> )
238+
239+ await vi . advanceTimersByTimeAsync ( 10 )
240+
241+ expect ( callbacks ) . toEqual ( [ 'mutateAsync.onError' , 'mutateAsync.onSettled' ] )
242+ } )
243+
244+ it ( 'should call only mutate onSuccess when useMutation has no callbacks' , async ( ) => {
245+ const callbacks : Array < string > = [ ]
246+
247+ function Page ( ) {
248+ const { mutate } = useMutation ( {
249+ mutationFn : ( text : string ) => sleep ( 10 ) . then ( ( ) => text ) ,
250+ } )
251+
252+ return (
253+ < button
254+ onClick = { ( ) =>
255+ mutate ( 'todo' , {
256+ onSuccess : ( ) => {
257+ callbacks . push ( 'mutate.onSuccess' )
258+ } ,
259+ } )
260+ }
261+ >
262+ mutate
263+ </ button >
264+ )
265+ }
266+
267+ const rendered = renderWithClient ( queryClient , < Page /> )
268+
269+ fireEvent . click ( rendered . getByRole ( 'button' , { name : / m u t a t e / i } ) )
270+ await vi . advanceTimersByTimeAsync ( 10 )
271+
272+ expect ( callbacks ) . toEqual ( [ 'mutate.onSuccess' ] )
273+ } )
274+
275+ it ( 'should call only mutate onError when useMutation has no callbacks' , async ( ) => {
276+ const callbacks : Array < string > = [ ]
277+
278+ function Page ( ) {
279+ const { mutate } = useMutation ( {
280+ mutationFn : ( _text : string ) =>
281+ sleep ( 10 ) . then ( ( ) => {
282+ throw new Error ( 'oops' )
283+ } ) ,
284+ } )
285+
286+ return (
287+ < button
288+ onClick = { ( ) =>
289+ mutate ( 'todo' , {
290+ onError : ( ) => {
291+ callbacks . push ( 'mutate.onError' )
292+ } ,
293+ } )
294+ }
295+ >
296+ mutate
297+ </ button >
298+ )
299+ }
300+
301+ const rendered = renderWithClient ( queryClient , < Page /> )
302+
303+ fireEvent . click ( rendered . getByRole ( 'button' , { name : / m u t a t e / i } ) )
304+ await vi . advanceTimersByTimeAsync ( 10 )
305+
306+ expect ( callbacks ) . toEqual ( [ 'mutate.onError' ] )
307+ } )
308+
309+ it ( 'should call only mutate onSettled when useMutation has no callbacks' , async ( ) => {
310+ const callbacks : Array < string > = [ ]
311+
312+ function Page ( ) {
313+ const { mutate } = useMutation ( {
314+ mutationFn : ( text : string ) => sleep ( 10 ) . then ( ( ) => text ) ,
315+ } )
316+
317+ return (
318+ < button
319+ onClick = { ( ) =>
320+ mutate ( 'todo' , {
321+ onSettled : ( ) => {
322+ callbacks . push ( 'mutate.onSettled' )
323+ } ,
324+ } )
325+ }
326+ >
327+ mutate
328+ </ button >
329+ )
330+ }
331+
332+ const rendered = renderWithClient ( queryClient , < Page /> )
333+
334+ fireEvent . click ( rendered . getByRole ( 'button' , { name : / m u t a t e / i } ) )
335+ await vi . advanceTimersByTimeAsync ( 10 )
336+
337+ expect ( callbacks ) . toEqual ( [ 'mutate.onSettled' ] )
338+ } )
339+
340+ it ( 'should call only mutateAsync onSuccess when useMutation has no callbacks' , async ( ) => {
341+ const callbacks : Array < string > = [ ]
342+
343+ function Page ( ) {
344+ const { mutateAsync } = useMutation ( {
345+ mutationFn : ( text : string ) => sleep ( 10 ) . then ( ( ) => text ) ,
346+ } )
347+
348+ useEffect ( ( ) => {
349+ setActTimeout ( async ( ) => {
350+ await mutateAsync ( 'todo' , {
351+ onSuccess : ( ) => {
352+ callbacks . push ( 'mutateAsync.onSuccess' )
353+ } ,
354+ } )
355+ } , 0 )
356+ } , [ mutateAsync ] )
357+
358+ return null
359+ }
360+
361+ renderWithClient ( queryClient , < Page /> )
362+
363+ await vi . advanceTimersByTimeAsync ( 10 )
364+
365+ expect ( callbacks ) . toEqual ( [ 'mutateAsync.onSuccess' ] )
366+ } )
367+
368+ it ( 'should call only mutateAsync onError when useMutation has no callbacks' , async ( ) => {
369+ const callbacks : Array < string > = [ ]
370+
371+ function Page ( ) {
372+ const { mutateAsync } = useMutation ( {
373+ mutationFn : async ( _text : string ) =>
374+ sleep ( 10 ) . then ( ( ) => {
375+ throw new Error ( 'oops' )
376+ } ) ,
377+ } )
378+
379+ useEffect ( ( ) => {
380+ setActTimeout ( async ( ) => {
381+ try {
382+ await mutateAsync ( 'todo' , {
383+ onError : ( ) => {
384+ callbacks . push ( 'mutateAsync.onError' )
385+ } ,
386+ } )
387+ } catch { }
388+ } , 0 )
389+ } , [ mutateAsync ] )
390+
391+ return null
392+ }
393+
394+ renderWithClient ( queryClient , < Page /> )
395+
396+ await vi . advanceTimersByTimeAsync ( 10 )
397+
398+ expect ( callbacks ) . toEqual ( [ 'mutateAsync.onError' ] )
399+ } )
400+
401+ it ( 'should call only mutateAsync onSettled when useMutation has no callbacks' , async ( ) => {
402+ const callbacks : Array < string > = [ ]
403+
404+ function Page ( ) {
405+ const { mutateAsync } = useMutation ( {
406+ mutationFn : ( text : string ) => sleep ( 10 ) . then ( ( ) => text ) ,
407+ } )
408+
409+ useEffect ( ( ) => {
410+ setActTimeout ( async ( ) => {
411+ await mutateAsync ( 'todo' , {
412+ onSettled : ( ) => {
413+ callbacks . push ( 'mutateAsync.onSettled' )
414+ } ,
415+ } )
416+ } , 0 )
417+ } , [ mutateAsync ] )
418+
419+ return null
420+ }
421+
422+ renderWithClient ( queryClient , < Page /> )
423+
424+ await vi . advanceTimersByTimeAsync ( 10 )
425+
426+ expect ( callbacks ) . toEqual ( [ 'mutateAsync.onSettled' ] )
427+ } )
428+
103429 it ( 'should be able to call `onSuccess` and `onSettled` after each successful mutate' , async ( ) => {
104430 let count = 0
105431 const onSuccessMock = vi . fn ( )
0 commit comments