From 00240cc14b13b3f86acfad562f2fd5325c4e01d5 Mon Sep 17 00:00:00 2001 From: Wonsuk Choi Date: Sun, 6 Sep 2026 15:39:14 +0900 Subject: [PATCH 1/2] test(vue-query): add tests for 'initialData' with a failed refetch and 'skipToken' dependent query --- .../src/__tests__/useInfiniteQuery.test.ts | 56 +++++++++++++++++++ .../vue-query/src/__tests__/useQuery.test.ts | 26 +++++++++ 2 files changed, 82 insertions(+) diff --git a/packages/vue-query/src/__tests__/useInfiniteQuery.test.ts b/packages/vue-query/src/__tests__/useInfiniteQuery.test.ts index a321b4c5c2..9708e7e502 100644 --- a/packages/vue-query/src/__tests__/useInfiniteQuery.test.ts +++ b/packages/vue-query/src/__tests__/useInfiniteQuery.test.ts @@ -1,5 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { ref } from 'vue-demi' +import { skipToken } from '@tanstack/query-core' import { queryKey, sleep } from '@tanstack/query-test-utils' import { useInfiniteQuery } from '../useInfiniteQuery' import { infiniteQueryOptions } from '../infiniteQueryOptions' @@ -129,4 +130,59 @@ describe('useInfiniteQuery', () => { expect(hasNextPage.value).toBe(false) expect(isFetching.value).toBe(false) }) + + it('should keep initialData visible alongside the error when a refetch fails', async () => { + const key = queryKey() + const { data, status, isError } = useInfiniteQuery({ + queryKey: key, + queryFn: () => + sleep(10).then(() => Promise.reject(new Error('Some error'))), + initialData: { pages: [1], pageParams: [1] }, + getNextPageParam: (lastPage: number) => lastPage + 1, + initialPageParam: 0, + retry: false, + }) + + expect(data.value).toStrictEqual({ pages: [1], pageParams: [1] }) + expect(status.value).toStrictEqual('success') + expect(isError.value).toBe(false) + + await vi.advanceTimersByTimeAsync(10) + + expect(data.value).toStrictEqual({ pages: [1], pageParams: [1] }) + expect(status.value).toStrictEqual('error') + expect(isError.value).toBe(true) + }) + + it('should not fetch when queryFn is skipToken, and fetch once it is replaced', async () => { + const key = queryKey() + const postId = ref() + + const { data, isFetching } = useInfiniteQuery(() => ({ + queryKey: key, + queryFn: + postId.value != null + ? ({ pageParam }: { pageParam: number }) => + sleep(10).then( + () => `comments for ${postId.value} page ${pageParam}`, + ) + : skipToken, + initialPageParam: 0, + getNextPageParam: () => 12, + })) + + expect(isFetching.value).toBe(false) + + await vi.advanceTimersByTimeAsync(10) + expect(isFetching.value).toBe(false) + expect(data.value).toBeUndefined() + + postId.value = '1' + await vi.advanceTimersByTimeAsync(10) + + expect(data.value).toStrictEqual({ + pages: ['comments for 1 page 0'], + pageParams: [0], + }) + }) }) diff --git a/packages/vue-query/src/__tests__/useQuery.test.ts b/packages/vue-query/src/__tests__/useQuery.test.ts index a648d3b001..099d48daa5 100644 --- a/packages/vue-query/src/__tests__/useQuery.test.ts +++ b/packages/vue-query/src/__tests__/useQuery.test.ts @@ -537,6 +537,32 @@ describe('useQuery', () => { }) }) + it('should keep initialData visible alongside the error when a refetch fails', async () => { + const key = queryKey() + + const query = useQuery({ + queryKey: key, + queryFn: () => + sleep(10).then(() => Promise.reject(new Error('Some error'))), + initialData: 'seeded data', + retry: false, + }) + + expect(query).toMatchObject({ + status: { value: 'success' }, + data: { value: 'seeded data' }, + isError: { value: false }, + }) + + await vi.advanceTimersByTimeAsync(10) + + expect(query).toMatchObject({ + status: { value: 'error' }, + data: { value: 'seeded data' }, + isError: { value: true }, + }) + }) + it('should keep the previous page visible while the next page loads with keepPreviousData', async () => { const key = queryKey() const page = ref(0) From 6d993f433bedb4b8f9b147558acf3ef442fc4ff0 Mon Sep 17 00:00:00 2001 From: Wonsuk Choi Date: Sun, 6 Sep 2026 23:12:54 +0900 Subject: [PATCH 2/2] test(vue-query/useInfiniteQuery): assert 'queryFn' call count in skipToken test --- .../src/__tests__/useInfiniteQuery.test.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/vue-query/src/__tests__/useInfiniteQuery.test.ts b/packages/vue-query/src/__tests__/useInfiniteQuery.test.ts index 9708e7e502..8a0c19a50e 100644 --- a/packages/vue-query/src/__tests__/useInfiniteQuery.test.ts +++ b/packages/vue-query/src/__tests__/useInfiniteQuery.test.ts @@ -157,16 +157,13 @@ describe('useInfiniteQuery', () => { it('should not fetch when queryFn is skipToken, and fetch once it is replaced', async () => { const key = queryKey() const postId = ref() + const queryFn = vi.fn(({ pageParam }: { pageParam: number }) => + sleep(10).then(() => `comments for ${postId.value} page ${pageParam}`), + ) const { data, isFetching } = useInfiniteQuery(() => ({ queryKey: key, - queryFn: - postId.value != null - ? ({ pageParam }: { pageParam: number }) => - sleep(10).then( - () => `comments for ${postId.value} page ${pageParam}`, - ) - : skipToken, + queryFn: postId.value != null ? queryFn : skipToken, initialPageParam: 0, getNextPageParam: () => 12, })) @@ -174,12 +171,14 @@ describe('useInfiniteQuery', () => { expect(isFetching.value).toBe(false) await vi.advanceTimersByTimeAsync(10) + expect(queryFn).not.toHaveBeenCalled() expect(isFetching.value).toBe(false) expect(data.value).toBeUndefined() postId.value = '1' await vi.advanceTimersByTimeAsync(10) + expect(queryFn).toHaveBeenCalledTimes(1) expect(data.value).toStrictEqual({ pages: ['comments for 1 page 0'], pageParams: [0],