diff --git a/packages/react-query/src/__tests__/mutationOptions.test.tsx b/packages/react-query/src/__tests__/mutationOptions.test.tsx index 118574cbeb..36ee1090a0 100644 --- a/packages/react-query/src/__tests__/mutationOptions.test.tsx +++ b/packages/react-query/src/__tests__/mutationOptions.test.tsx @@ -16,30 +16,84 @@ describe('mutationOptions', () => { vi.useRealTimers() }) - it('should return the object received as a parameter without any modification.', () => { + it('should return the object received as a parameter without any modification (with mutationKey in mutationOptions)', () => { const object = { mutationKey: ['key'], - mutationFn: () => Promise.resolve(5), + mutationFn: () => sleep(10).then(() => 5), } as const expect(mutationOptions(object)).toStrictEqual(object) }) - it('should return the number of fetching mutations when used with useIsMutating', async () => { + it('should return the object received as a parameter without any modification (without mutationKey in mutationOptions)', () => { + const object = { + mutationFn: () => sleep(10).then(() => 5), + } as const + + expect(mutationOptions(object)).toStrictEqual(object) + }) + + it('should return the number of fetching mutations when used with useIsMutating (with mutationKey in mutationOptions)', async () => { const isMutatingArray: Array = [] const queryClient = new QueryClient() + const mutationOpts = mutationOptions({ + mutationKey: ['key'], + mutationFn: () => sleep(50).then(() => 'data'), + }) function IsMutating() { const isMutating = useIsMutating() + isMutatingArray.push(isMutating) + return null } + function Mutation() { + const { mutate } = useMutation(mutationOpts) + + return ( +
+ +
+ ) + } + + function Page() { + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + expect(isMutatingArray[0]).toEqual(0) + await vi.advanceTimersByTimeAsync(0) + expect(isMutatingArray[1]).toEqual(1) + await vi.advanceTimersByTimeAsync(51) + expect(isMutatingArray[2]).toEqual(0) + expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0) + }) + + it('should return the number of fetching mutations when used with useIsMutating (without mutationKey in mutationOptions)', async () => { + const isMutatingArray: Array = [] + const queryClient = new QueryClient() const mutationOpts = mutationOptions({ - mutationKey: ['key'], mutationFn: () => sleep(50).then(() => 'data'), }) + function IsMutating() { + const isMutating = useIsMutating() + + isMutatingArray.push(isMutating) + + return null + } + function Mutation() { const { mutate } = useMutation(mutationOpts) @@ -60,8 +114,8 @@ describe('mutationOptions', () => { } const rendered = renderWithClient(queryClient, ) - fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) expect(isMutatingArray[0]).toEqual(0) await vi.advanceTimersByTimeAsync(0) expect(isMutatingArray[1]).toEqual(1) @@ -70,10 +124,115 @@ describe('mutationOptions', () => { expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0) }) - it('should return the number of fetching mutations when used with queryClient.isMutating', async () => { + it('should return the number of fetching mutations when used with useIsMutating', async () => { + const isMutatingArray: Array = [] + const queryClient = new QueryClient() + const mutationOpts1 = mutationOptions({ + mutationKey: ['key'], + mutationFn: () => sleep(50).then(() => 'data1'), + }) + const mutationOpts2 = mutationOptions({ + mutationFn: () => sleep(50).then(() => 'data2'), + }) + + function IsMutating() { + const isMutating = useIsMutating() + + isMutatingArray.push(isMutating) + + return null + } + + function Mutation() { + const { mutate: mutate1 } = useMutation(mutationOpts1) + const { mutate: mutate2 } = useMutation(mutationOpts2) + + return ( +
+ + +
+ ) + } + + function Page() { + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + fireEvent.click(rendered.getByRole('button', { name: /mutate1/i })) + fireEvent.click(rendered.getByRole('button', { name: /mutate2/i })) + expect(isMutatingArray[0]).toEqual(0) + await vi.advanceTimersByTimeAsync(0) + expect(isMutatingArray[1]).toEqual(2) + await vi.advanceTimersByTimeAsync(51) + expect(isMutatingArray[2]).toEqual(0) + expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0) + }) + + it('should return the number of fetching mutations when used with useIsMutating (filter mutationOpts1.mutationKey)', async () => { const isMutatingArray: Array = [] const queryClient = new QueryClient() + const mutationOpts1 = mutationOptions({ + mutationKey: ['key'], + mutationFn: () => sleep(50).then(() => 'data1'), + }) + const mutationOpts2 = mutationOptions({ + mutationFn: () => sleep(50).then(() => 'data2'), + }) + + function IsMutating() { + const isMutating = useIsMutating({ + mutationKey: mutationOpts1.mutationKey, + }) + isMutatingArray.push(isMutating) + + return null + } + + function Mutation() { + const { mutate: mutate1 } = useMutation(mutationOpts1) + const { mutate: mutate2 } = useMutation(mutationOpts2) + + return ( +
+ + +
+ ) + } + + function Page() { + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + fireEvent.click(rendered.getByRole('button', { name: /mutate1/i })) + fireEvent.click(rendered.getByRole('button', { name: /mutate2/i })) + expect(isMutatingArray[0]).toEqual(0) + await vi.advanceTimersByTimeAsync(0) + expect(isMutatingArray[1]).toEqual(1) + await vi.advanceTimersByTimeAsync(51) + expect(isMutatingArray[2]).toEqual(0) + expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0) + }) + + it('should return the number of fetching mutations when used with queryClient.isMutating (with mutationKey in mutationOptions)', async () => { + const isMutatingArray: Array = [] + const queryClient = new QueryClient() const mutationOpts = mutationOptions({ mutationKey: ['mutation'], mutationFn: () => sleep(500).then(() => 'data'), @@ -82,6 +241,7 @@ describe('mutationOptions', () => { function Mutation() { const isMutating = queryClient.isMutating(mutationOpts) const { mutate } = useMutation(mutationOpts) + isMutatingArray.push(isMutating) return ( @@ -92,8 +252,39 @@ describe('mutationOptions', () => { } const rendered = renderWithClient(queryClient, ) + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + expect(isMutatingArray[0]).toEqual(0) + await vi.advanceTimersByTimeAsync(0) + expect(isMutatingArray[1]).toEqual(1) + await vi.advanceTimersByTimeAsync(501) + expect(isMutatingArray[2]).toEqual(0) + expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0) + }) + it('should return the number of fetching mutations when used with queryClient.isMutating (without mutationKey in mutationOptions)', async () => { + const isMutatingArray: Array = [] + const queryClient = new QueryClient() + const mutationOpts = mutationOptions({ + mutationFn: () => sleep(500).then(() => 'data'), + }) + + function Mutation() { + const isMutating = queryClient.isMutating() + const { mutate } = useMutation(mutationOpts) + + isMutatingArray.push(isMutating) + + return ( +
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) expect(isMutatingArray[0]).toEqual(0) await vi.advanceTimersByTimeAsync(0) expect(isMutatingArray[1]).toEqual(1) @@ -102,22 +293,100 @@ describe('mutationOptions', () => { expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0) }) - it('should return the number of fetching mutations when used with useMutationState', async () => { + it('should return the number of fetching mutations when used with queryClient.isMutating', async () => { + const isMutatingArray: Array = [] + const queryClient = new QueryClient() + const mutationOpts1 = mutationOptions({ + mutationKey: ['mutation'], + mutationFn: () => sleep(500).then(() => 'data1'), + }) + const mutationOpts2 = mutationOptions({ + mutationFn: () => sleep(500).then(() => 'data2'), + }) + + function Mutation() { + const isMutating = queryClient.isMutating() + const { mutate: mutate1 } = useMutation(mutationOpts1) + const { mutate: mutate2 } = useMutation(mutationOpts2) + + isMutatingArray.push(isMutating) + + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + fireEvent.click(rendered.getByRole('button', { name: /mutate1/i })) + fireEvent.click(rendered.getByRole('button', { name: /mutate2/i })) + expect(isMutatingArray[0]).toEqual(0) + await vi.advanceTimersByTimeAsync(0) + expect(isMutatingArray[1]).toEqual(2) + await vi.advanceTimersByTimeAsync(501) + expect(isMutatingArray[2]).toEqual(0) + expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0) + }) + + it('should return the number of fetching mutations when used with queryClient.isMutating (filter mutationOpt1.mutationKey)', async () => { + const isMutatingArray: Array = [] + const queryClient = new QueryClient() + const mutationOpts1 = mutationOptions({ + mutationKey: ['mutation'], + mutationFn: () => sleep(500).then(() => 'data1'), + }) + const mutationOpts2 = mutationOptions({ + mutationFn: () => sleep(500).then(() => 'data2'), + }) + + function Mutation() { + const isMutating = queryClient.isMutating({ + mutationKey: mutationOpts1.mutationKey, + }) + const { mutate: mutate1 } = useMutation(mutationOpts1) + const { mutate: mutate2 } = useMutation(mutationOpts2) + + isMutatingArray.push(isMutating) + + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + fireEvent.click(rendered.getByRole('button', { name: /mutate1/i })) + fireEvent.click(rendered.getByRole('button', { name: /mutate2/i })) + expect(isMutatingArray[0]).toEqual(0) + await vi.advanceTimersByTimeAsync(0) + expect(isMutatingArray[1]).toEqual(1) + await vi.advanceTimersByTimeAsync(501) + expect(isMutatingArray[2]).toEqual(0) + expect(isMutatingArray[isMutatingArray.length - 1]).toEqual(0) + }) + + it('should return the number of fetching mutations when used with useMutationState (with mutationKey in mutationOptions)', async () => { const mutationStateArray: Array< MutationState > = [] const queryClient = new QueryClient() - const mutationOpts = mutationOptions({ mutationKey: ['mutation'], - mutationFn: () => Promise.resolve('data'), + mutationFn: () => sleep(10).then(() => 'data'), }) function Mutation() { const { mutate } = useMutation(mutationOpts) const data = useMutationState({ - filters: { ...mutationOpts, status: 'success' }, + filters: { mutationKey: mutationOpts.mutationKey, status: 'success' }, }) + mutationStateArray.push(...data) return ( @@ -128,10 +397,130 @@ describe('mutationOptions', () => { } const rendered = renderWithClient(queryClient, ) + + expect(mutationStateArray.length).toEqual(0) + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + await vi.advanceTimersByTimeAsync(11) + expect(mutationStateArray.length).toEqual(1) + expect(mutationStateArray[0]?.data).toEqual('data') + }) - await vi.advanceTimersByTimeAsync(0) + it('should return the number of fetching mutations when used with useMutationState (without mutationKey in mutationOptions)', async () => { + const mutationStateArray: Array< + MutationState + > = [] + const queryClient = new QueryClient() + const mutationOpts = mutationOptions({ + mutationFn: () => sleep(10).then(() => 'data'), + }) + + function Mutation() { + const { mutate } = useMutation(mutationOpts) + const data = useMutationState({ + filters: { status: 'success' }, + }) + + mutationStateArray.push(...data) + + return ( +
+ +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + expect(mutationStateArray.length).toEqual(0) + + fireEvent.click(rendered.getByRole('button', { name: /mutate/i })) + await vi.advanceTimersByTimeAsync(11) expect(mutationStateArray.length).toEqual(1) expect(mutationStateArray[0]?.data).toEqual('data') }) + + it('should return the number of fetching mutations when used with useMutationState', async () => { + const mutationStateArray: Array< + MutationState + > = [] + const queryClient = new QueryClient() + const mutationOpts1 = mutationOptions({ + mutationKey: ['mutation'], + mutationFn: () => sleep(10).then(() => 'data1'), + }) + const mutationOpts2 = mutationOptions({ + mutationFn: () => sleep(10).then(() => 'data2'), + }) + + function Mutation() { + const { mutate: mutate1 } = useMutation(mutationOpts1) + const { mutate: mutate2 } = useMutation(mutationOpts2) + const data = useMutationState({ + filters: { status: 'success' }, + }) + + mutationStateArray.push(...data) + + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + expect(mutationStateArray.length).toEqual(0) + + fireEvent.click(rendered.getByRole('button', { name: /mutate1/i })) + fireEvent.click(rendered.getByRole('button', { name: /mutate2/i })) + await vi.advanceTimersByTimeAsync(11) + expect(mutationStateArray.length).toEqual(2) + expect(mutationStateArray[0]?.data).toEqual('data1') + expect(mutationStateArray[1]?.data).toEqual('data2') + }) + + it('should return the number of fetching mutations when used with useMutationState (filter mutationOpt1.mutationKey)', async () => { + const mutationStateArray: Array< + MutationState + > = [] + const queryClient = new QueryClient() + const mutationOpts1 = mutationOptions({ + mutationKey: ['mutation'], + mutationFn: () => sleep(10).then(() => 'data1'), + }) + const mutationOpts2 = mutationOptions({ + mutationFn: () => sleep(10).then(() => 'data2'), + }) + + function Mutation() { + const { mutate: mutate1 } = useMutation(mutationOpts1) + const { mutate: mutate2 } = useMutation(mutationOpts2) + const data = useMutationState({ + filters: { mutationKey: mutationOpts1.mutationKey, status: 'success' }, + }) + + mutationStateArray.push(...data) + + return ( +
+ + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + expect(mutationStateArray.length).toEqual(0) + + fireEvent.click(rendered.getByRole('button', { name: /mutate1/i })) + fireEvent.click(rendered.getByRole('button', { name: /mutate2/i })) + await vi.advanceTimersByTimeAsync(11) + expect(mutationStateArray.length).toEqual(1) + expect(mutationStateArray[0]?.data).toEqual('data1') + expect(mutationStateArray[1]).toBeFalsy() + }) })