From da1f81db252941bf92332974bbf6e7036739ac78 Mon Sep 17 00:00:00 2001 From: Wonsuk Choi Date: Sat, 18 Jul 2026 21:32:04 +0900 Subject: [PATCH] test({react,preact}-query/usePrefetchInfiniteQuery): inline single-use helpers and adopt the 'pageParam' mock convention --- .../usePrefetchInfiniteQuery.test.tsx | 91 ++++++++--------- .../usePrefetchInfiniteQuery.test.tsx | 98 ++++++++----------- 2 files changed, 84 insertions(+), 105 deletions(-) diff --git a/packages/preact-query/src/__tests__/usePrefetchInfiniteQuery.test.tsx b/packages/preact-query/src/__tests__/usePrefetchInfiniteQuery.test.tsx index 1f168ef8f2..8a6b781919 100644 --- a/packages/preact-query/src/__tests__/usePrefetchInfiniteQuery.test.tsx +++ b/packages/preact-query/src/__tests__/usePrefetchInfiniteQuery.test.tsx @@ -3,7 +3,6 @@ import { fireEvent } from '@testing-library/preact' import type { VNode } from 'preact' import { Suspense } from 'preact/compat' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import type { Mock } from 'vitest' import { QueryCache, @@ -13,33 +12,6 @@ import { } from '..' import { renderWithClient } from './utils' -const generateInfiniteQueryOptions = ( - data: Array<{ data: string; currentPage: number; totalPages: number }>, -) => { - let currentPage = 0 - - return { - queryFn: vi - .fn<(...args: Array) => Promise<(typeof data)[number]>>() - .mockImplementation(async () => { - const currentPageData = data[currentPage] - if (!currentPageData) { - throw new Error(`No data defined for page ${currentPage}`) - } - - await sleep(10) - currentPage++ - - return currentPageData - }), - initialPageParam: 1, - getNextPageParam: (lastPage: (typeof data)[number]) => - lastPage.currentPage === lastPage.totalPages - ? undefined - : lastPage.currentPage + 1, - } -} - describe('usePrefetchInfiniteQuery', () => { let queryCache: QueryCache let queryClient: QueryClient @@ -60,18 +32,21 @@ describe('usePrefetchInfiniteQuery', () => { it('should prefetch an infinite query if query state does not exist', async () => { const data = [ - { data: 'Do you fetch on render?', currentPage: 1, totalPages: 3 }, - { data: 'Or do you render as you fetch?', currentPage: 2, totalPages: 3 }, - { - data: 'Either way, Tanstack Query helps you!', - currentPage: 3, - totalPages: 3, - }, + 'Do you fetch on render?', + 'Or do you render as you fetch?', + 'Either way, Tanstack Query helps you!', ] const queryOpts = { queryKey: queryKey(), - ...generateInfiniteQueryOptions(data), + queryFn: vi + .fn<(context: { pageParam: number }) => Promise>() + .mockImplementation(({ pageParam }) => + sleep(10).then(() => data[pageParam]!), + ), + initialPageParam: 0, + getNextPageParam: (_lastPage: string, allPages: Array) => + allPages.length < data.length ? allPages.length : undefined, } function Page() { @@ -80,7 +55,7 @@ describe('usePrefetchInfiniteQuery', () => { return (
{state.data.pages.map((page, index) => ( -
data: {page.data}
+
data: {page}
))}
@@ -114,18 +89,27 @@ describe('usePrefetchInfiniteQuery', () => { }) it('should not display fallback if the query cache is already populated', async () => { + const data = [ + 'Prefetch rocks!', + 'No waterfalls, boy!', + 'Tanstack Query #ftw', + ] + const queryOpts = { queryKey: queryKey(), - ...generateInfiniteQueryOptions([ - { data: 'Prefetch rocks!', currentPage: 1, totalPages: 3 }, - { data: 'No waterfalls, boy!', currentPage: 2, totalPages: 3 }, - { data: 'Tanstack Query #ftw', currentPage: 3, totalPages: 3 }, - ]), + queryFn: vi + .fn<(context: { pageParam: number }) => Promise>() + .mockImplementation(({ pageParam }) => + sleep(10).then(() => data[pageParam]!), + ), + initialPageParam: 0, + getNextPageParam: (_lastPage: string, allPages: Array) => + allPages.length < data.length ? allPages.length : undefined, } queryClient.prefetchInfiniteQuery({ ...queryOpts, pages: 3 }) await vi.advanceTimersByTimeAsync(30) - ;(queryOpts.queryFn as Mock).mockClear() + queryOpts.queryFn.mockClear() function Page() { const state = useSuspenseInfiniteQuery(queryOpts) @@ -133,7 +117,7 @@ describe('usePrefetchInfiniteQuery', () => { return (
{state.data.pages.map((page, index) => ( -
data: {page.data}
+
data: {page}
))}
@@ -162,13 +146,20 @@ describe('usePrefetchInfiniteQuery', () => { }) it('should not create an endless loop when using inside a suspense boundary', async () => { + const data = ['Infinite Page 1', 'Infinite Page 2', 'Infinite Page 3'] + const queryOpts = { queryKey: queryKey(), - ...generateInfiniteQueryOptions([ - { data: 'Infinite Page 1', currentPage: 1, totalPages: 3 }, - { data: 'Infinite Page 2', currentPage: 1, totalPages: 3 }, - { data: 'Infinite Page 3', currentPage: 1, totalPages: 3 }, - ]), + queryFn: vi + .fn<(context: { pageParam: number }) => Promise>() + .mockImplementation(({ pageParam }) => + sleep(10).then(() => data[pageParam]!), + ), + initialPageParam: 0, + // always reports another page available, to guard against an endless + // auto-advance loop rather than a bounded pagination sequence + getNextPageParam: (_lastPage: string, allPages: Array) => + allPages.length, } function Prefetch({ children }: { children: VNode }) { @@ -182,7 +173,7 @@ describe('usePrefetchInfiniteQuery', () => { return (
{state.data.pages.map((page, index) => ( -
data: {page.data}
+
data: {page}
))}
diff --git a/packages/react-query/src/__tests__/usePrefetchInfiniteQuery.test.tsx b/packages/react-query/src/__tests__/usePrefetchInfiniteQuery.test.tsx index 1dd2ea1525..7e3df99f01 100644 --- a/packages/react-query/src/__tests__/usePrefetchInfiniteQuery.test.tsx +++ b/packages/react-query/src/__tests__/usePrefetchInfiniteQuery.test.tsx @@ -9,37 +9,6 @@ import { useSuspenseInfiniteQuery, } from '..' import { renderWithClient } from './utils' -import type { Mock } from 'vitest' - -const createFallback = () => - vi.fn().mockImplementation(() =>
Loading...
) - -const generateInfiniteQueryOptions = ( - data: Array<{ data: string; currentPage: number; totalPages: number }>, -) => { - let currentPage = 0 - - return { - queryFn: vi - .fn<(...args: Array) => Promise<(typeof data)[number]>>() - .mockImplementation(async () => { - const currentPageData = data[currentPage] - if (!currentPageData) { - throw new Error('No data defined for page ' + currentPage) - } - - await sleep(10) - currentPage++ - - return currentPageData - }), - initialPageParam: 1, - getNextPageParam: (lastPage: (typeof data)[number]) => - lastPage.currentPage === lastPage.totalPages - ? undefined - : lastPage.currentPage + 1, - } -} describe('usePrefetchInfiniteQuery', () => { let queryCache: QueryCache @@ -57,20 +26,23 @@ describe('usePrefetchInfiniteQuery', () => { }) it('should prefetch an infinite query if query state does not exist', async () => { - const Fallback = createFallback() + const Fallback = vi.fn().mockImplementation(() =>
Loading...
) const data = [ - { data: 'Do you fetch on render?', currentPage: 1, totalPages: 3 }, - { data: 'Or do you render as you fetch?', currentPage: 2, totalPages: 3 }, - { - data: 'Either way, Tanstack Query helps you!', - currentPage: 3, - totalPages: 3, - }, + 'Do you fetch on render?', + 'Or do you render as you fetch?', + 'Either way, Tanstack Query helps you!', ] const queryOpts = { queryKey: queryKey(), - ...generateInfiniteQueryOptions(data), + queryFn: vi + .fn<(context: { pageParam: number }) => Promise>() + .mockImplementation(({ pageParam }) => + sleep(10).then(() => data[pageParam]!), + ), + initialPageParam: 0, + getNextPageParam: (_lastPage: string, allPages: Array) => + allPages.length < data.length ? allPages.length : undefined, } function Page() { @@ -79,7 +51,7 @@ describe('usePrefetchInfiniteQuery', () => { return (
{state.data.pages.map((page, index) => ( -
data: {page.data}
+
data: {page}
))}
@@ -113,19 +85,28 @@ describe('usePrefetchInfiniteQuery', () => { }) it('should not display fallback if the query cache is already populated', async () => { - const Fallback = createFallback() + const Fallback = vi.fn().mockImplementation(() =>
Loading...
) + const data = [ + 'Prefetch rocks!', + 'No waterfalls, boy!', + 'Tanstack Query #ftw', + ] + const queryOpts = { queryKey: queryKey(), - ...generateInfiniteQueryOptions([ - { data: 'Prefetch rocks!', currentPage: 1, totalPages: 3 }, - { data: 'No waterfalls, boy!', currentPage: 2, totalPages: 3 }, - { data: 'Tanstack Query #ftw', currentPage: 3, totalPages: 3 }, - ]), + queryFn: vi + .fn<(context: { pageParam: number }) => Promise>() + .mockImplementation(({ pageParam }) => + sleep(10).then(() => data[pageParam]!), + ), + initialPageParam: 0, + getNextPageParam: (_lastPage: string, allPages: Array) => + allPages.length < data.length ? allPages.length : undefined, } queryClient.prefetchInfiniteQuery({ ...queryOpts, pages: 3 }) await vi.advanceTimersByTimeAsync(30) - ;(queryOpts.queryFn as Mock).mockClear() + queryOpts.queryFn.mockClear() function Page() { const state = useSuspenseInfiniteQuery(queryOpts) @@ -133,7 +114,7 @@ describe('usePrefetchInfiniteQuery', () => { return (
{state.data.pages.map((page, index) => ( -
data: {page.data}
+
data: {page}
))}
@@ -162,13 +143,20 @@ describe('usePrefetchInfiniteQuery', () => { }) it('should not create an endless loop when using inside a suspense boundary', async () => { + const data = ['Infinite Page 1', 'Infinite Page 2', 'Infinite Page 3'] + const queryOpts = { queryKey: queryKey(), - ...generateInfiniteQueryOptions([ - { data: 'Infinite Page 1', currentPage: 1, totalPages: 3 }, - { data: 'Infinite Page 2', currentPage: 1, totalPages: 3 }, - { data: 'Infinite Page 3', currentPage: 1, totalPages: 3 }, - ]), + queryFn: vi + .fn<(context: { pageParam: number }) => Promise>() + .mockImplementation(({ pageParam }) => + sleep(10).then(() => data[pageParam]!), + ), + initialPageParam: 0, + // always reports another page available, to guard against an endless + // auto-advance loop rather than a bounded pagination sequence + getNextPageParam: (_lastPage: string, allPages: Array) => + allPages.length, } function Prefetch({ children }: { children: React.ReactNode }) { @@ -182,7 +170,7 @@ describe('usePrefetchInfiniteQuery', () => { return (
{state.data.pages.map((page, index) => ( -
data: {page.data}
+
data: {page}
))}