diff --git a/packages/react-query/src/__tests__/useMutation.test.tsx b/packages/react-query/src/__tests__/useMutation.test.tsx index d162f3ab17..49ab1d632b 100644 --- a/packages/react-query/src/__tests__/useMutation.test.tsx +++ b/packages/react-query/src/__tests__/useMutation.test.tsx @@ -453,8 +453,6 @@ describe('useMutation', () => { const rendered = renderWithClient(queryClient, ) - window.dispatchEvent(new Event('offline')) - await waitFor(() => { expect( rendered.getByText('error: null, status: idle, isPaused: false'), @@ -471,8 +469,8 @@ describe('useMutation', () => { expect(count).toBe(0) - onlineMock.mockRestore() - window.dispatchEvent(new Event('online')) + onlineMock.mockReturnValue(true) + queryClient.getMutationCache().resumePausedMutations() await sleep(100) @@ -483,6 +481,7 @@ describe('useMutation', () => { }) expect(count).toBe(2) + onlineMock.mockRestore() }) it('should call onMutate even if paused', async () => { @@ -515,8 +514,6 @@ describe('useMutation', () => { await rendered.findByText('data: null, status: idle, isPaused: false') - window.dispatchEvent(new Event('offline')) - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) await rendered.findByText('data: null, status: pending, isPaused: true') @@ -524,13 +521,15 @@ describe('useMutation', () => { expect(onMutate).toHaveBeenCalledTimes(1) expect(onMutate).toHaveBeenCalledWith('todo') - onlineMock.mockRestore() - window.dispatchEvent(new Event('online')) + onlineMock.mockReturnValue(true) + queryClient.getMutationCache().resumePausedMutations() await rendered.findByText('data: 1, status: success, isPaused: false') expect(onMutate).toHaveBeenCalledTimes(1) expect(count).toBe(1) + + onlineMock.mockRestore() }) it('should optimistically go to paused state if offline', async () => { @@ -564,8 +563,6 @@ describe('useMutation', () => { await rendered.findByText('data: null, status: idle, isPaused: false') - window.dispatchEvent(new Event('offline')) - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) await rendered.findByText('data: null, status: pending, isPaused: true') @@ -574,22 +571,25 @@ describe('useMutation', () => { expect(states[0]).toBe('idle, false') expect(states[1]).toBe('pending, true') - onlineMock.mockRestore() - window.dispatchEvent(new Event('online')) + onlineMock.mockReturnValue(true) + queryClient.getMutationCache().resumePausedMutations() await rendered.findByText('data: 1, status: success, isPaused: false') + + onlineMock.mockRestore() }) it('should be able to retry a mutation when online', async () => { const onlineMock = mockOnlineManagerIsOnline(false) + const key = queryKey() let count = 0 - const states: Array> = [] function Page() { const state = useMutation({ + mutationKey: key, mutationFn: async (_text: string) => { - await sleep(1) + await sleep(10) count++ return count > 1 ? Promise.resolve('data') @@ -600,69 +600,50 @@ describe('useMutation', () => { networkMode: 'offlineFirst', }) - states.push(state) - - const { mutate } = state - - React.useEffect(() => { - setActTimeout(() => { - window.dispatchEvent(new Event('offline')) - mutate('todo') - }, 10) - }, [mutate]) - - return null + return ( + + state.mutate('todo')}>mutate + status: {state.status} + isPaused: {String(state.isPaused)} + data: {state.data ?? 'null'} + + ) } - renderWithClient(queryClient, ) - - await sleep(50) + const rendered = renderWithClient(queryClient, ) - expect(states.length).toBe(4) - expect(states[0]).toMatchObject({ - isPending: false, - isPaused: false, - failureCount: 0, - failureReason: null, - }) - expect(states[1]).toMatchObject({ - isPending: true, - isPaused: false, - failureCount: 0, - failureReason: null, - }) - expect(states[2]).toMatchObject({ - isPending: true, - isPaused: false, - failureCount: 1, - failureReason: new Error('oops'), - }) - expect(states[3]).toMatchObject({ - isPending: true, + await waitFor(() => rendered.getByText('status: idle')) + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + await waitFor(() => rendered.getByText('isPaused: true')) + + expect( + queryClient.getMutationCache().findAll({ mutationKey: key }).length, + ).toBe(1) + expect( + queryClient.getMutationCache().findAll({ mutationKey: key })[0]?.state, + ).toMatchObject({ + status: 'pending', isPaused: true, failureCount: 1, failureReason: new Error('oops'), }) - onlineMock.mockRestore() - window.dispatchEvent(new Event('online')) + onlineMock.mockReturnValue(true) + queryClient.getMutationCache().resumePausedMutations() - await sleep(50) + await waitFor(() => rendered.getByText('data: data')) - expect(states.length).toBe(6) - expect(states[4]).toMatchObject({ - isPending: true, - isPaused: false, - failureCount: 1, - failureReason: new Error('oops'), - }) - expect(states[5]).toMatchObject({ - isPending: false, + expect( + queryClient.getMutationCache().findAll({ mutationKey: key })[0]?.state, + ).toMatchObject({ + status: 'success', isPaused: false, failureCount: 0, failureReason: null, data: 'data', }) + + onlineMock.mockRestore() }) it('should not change state if unmounted', async () => { diff --git a/packages/react-query/src/__tests__/useQuery.test.tsx b/packages/react-query/src/__tests__/useQuery.test.tsx index eec7607c9e..5f5c2345e9 100644 --- a/packages/react-query/src/__tests__/useQuery.test.tsx +++ b/packages/react-query/src/__tests__/useQuery.test.tsx @@ -5216,12 +5216,11 @@ describe('useQuery', () => { } const rendered = renderWithClient(queryClient, ) - window.dispatchEvent(new Event('offline')) await waitFor(() => rendered.getByText('status: pending, isPaused: true')) - onlineMock.mockRestore() - window.dispatchEvent(new Event('online')) + onlineMock.mockReturnValue(true) + queryClient.getQueryCache().onOnline() await waitFor(() => rendered.getByText('status: success, isPaused: false'), @@ -5231,6 +5230,7 @@ describe('useQuery', () => { }) expect(states).toEqual(['paused', 'fetching', 'idle']) + onlineMock.mockRestore() }) it('online queries should not refetch if you are offline', async () => { @@ -5269,7 +5269,6 @@ describe('useQuery', () => { await waitFor(() => rendered.getByText('data: data1')) const onlineMock = mockOnlineManagerIsOnline(false) - window.dispatchEvent(new Event('offline')) fireEvent.click(rendered.getByRole('button', { name: /invalidate/i })) @@ -5280,8 +5279,8 @@ describe('useQuery', () => { ) await waitFor(() => rendered.getByText('failureReason: null')) - onlineMock.mockRestore() - window.dispatchEvent(new Event('online')) + onlineMock.mockReturnValue(true) + queryClient.getQueryCache().onOnline() await waitFor(() => rendered.getByText( @@ -5299,6 +5298,8 @@ describe('useQuery', () => { await waitFor(() => { expect(rendered.getByText('data: data2')).toBeInTheDocument() }) + + onlineMock.mockRestore() }) it('online queries should not refetch if you are offline and refocus', async () => { @@ -5488,7 +5489,6 @@ describe('useQuery', () => { const onlineMock = mockOnlineManagerIsOnline(false) const rendered = renderWithClient(queryClient, ) - window.dispatchEvent(new Event('offline')) await waitFor(() => rendered.getByText('status: success, fetchStatus: paused'), @@ -5511,10 +5511,8 @@ describe('useQuery', () => { window.dispatchEvent(new Event('visibilitychange')) }) - onlineMock.mockRestore() - act(() => { - window.dispatchEvent(new Event('online')) - }) + onlineMock.mockReturnValue(true) + queryClient.getQueryCache().onOnline() await waitFor(() => rendered.getByText('status: success, fetchStatus: idle'), @@ -5524,6 +5522,8 @@ describe('useQuery', () => { }) expect(count).toBe(1) + + onlineMock.mockRestore() }) it('online queries should pause retries if you are offline', async () => { @@ -5560,7 +5560,6 @@ describe('useQuery', () => { ) const onlineMock = mockOnlineManagerIsOnline(false) - window.dispatchEvent(new Event('offline')) await sleep(20) @@ -5574,7 +5573,7 @@ describe('useQuery', () => { expect(count).toBe(1) onlineMock.mockReturnValue(true) - window.dispatchEvent(new Event('online')) + queryClient.getQueryCache().onOnline() await waitFor(() => rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'), @@ -5625,16 +5624,14 @@ describe('useQuery', () => { const rendered = renderWithClient(queryClient, ) - window.dispatchEvent(new Event('offline')) - await waitFor(() => rendered.getByText('status: pending, fetchStatus: paused'), ) fireEvent.click(rendered.getByRole('button', { name: /hide/i })) - onlineMock.mockRestore() - window.dispatchEvent(new Event('online')) + onlineMock.mockReturnValue(true) + queryClient.getQueryCache().onOnline() await waitFor(() => { expect(queryClient.getQueryState(key)).toMatchObject({ @@ -5646,6 +5643,8 @@ describe('useQuery', () => { // give it a bit more time to make sure queryFn is not called again await sleep(15) expect(count).toBe(1) + + onlineMock.mockRestore() }) it('online queries should not fetch if paused and we go online when cancelled and no refetchOnReconnect', async () => { @@ -5695,7 +5694,7 @@ describe('useQuery', () => { expect(count).toBe(0) onlineMock.mockReturnValue(true) - window.dispatchEvent(new Event('online')) + queryClient.getQueryCache().onOnline() await sleep(15) @@ -5767,7 +5766,7 @@ describe('useQuery', () => { await sleep(15) onlineMock.mockReturnValue(true) - window.dispatchEvent(new Event('online')) + queryClient.getQueryCache().onOnline() await sleep(15) @@ -5901,8 +5900,6 @@ describe('useQuery', () => { const rendered = renderWithClient(queryClient, ) - window.dispatchEvent(new Event('offline')) - await waitFor(() => rendered.getByText( 'status: pending, fetchStatus: paused, failureCount: 1', @@ -5912,8 +5909,8 @@ describe('useQuery', () => { expect(count).toBe(1) - onlineMock.mockRestore() - window.dispatchEvent(new Event('online')) + onlineMock.mockReturnValue(true) + queryClient.getQueryCache().onOnline() await waitFor(() => rendered.getByText('status: error, fetchStatus: idle, failureCount: 3'), @@ -5921,6 +5918,7 @@ describe('useQuery', () => { await waitFor(() => rendered.getByText('failureReason: failed3')) expect(count).toBe(3) + onlineMock.mockRestore() }) }) diff --git a/packages/react-query/src/__tests__/utils.tsx b/packages/react-query/src/__tests__/utils.tsx index a32f5c2592..f640fd3d7b 100644 --- a/packages/react-query/src/__tests__/utils.tsx +++ b/packages/react-query/src/__tests__/utils.tsx @@ -4,7 +4,7 @@ import { act, render } from '@testing-library/react' import * as utils from '@tanstack/query-core' import { QueryClient, QueryClientProvider, onlineManager } from '..' import type { QueryClientConfig } from '..' -import type { SpyInstance } from 'vitest' +import type { MockInstance } from 'vitest' export function renderWithClient( client: QueryClient, @@ -48,13 +48,13 @@ export function createQueryClient(config?: QueryClientConfig): QueryClient { export function mockVisibilityState( value: DocumentVisibilityState, -): SpyInstance<[], DocumentVisibilityState> { +): MockInstance<[], DocumentVisibilityState> { return vi.spyOn(document, 'visibilityState', 'get').mockReturnValue(value) } export function mockOnlineManagerIsOnline( value: boolean, -): SpyInstance<[], boolean> { +): MockInstance<[], boolean> { return vi.spyOn(onlineManager, 'isOnline').mockReturnValue(value) }