Skip to content

Commit 74c65cc

Browse files
manudeliTkDodo
andauthored
test(react-query): refactor test file structure 1 file by 1 api (TanStack#8262)
Co-authored-by: Dominik Dorfmeister <[email protected]>
1 parent 7085bd1 commit 74c65cc

File tree

4 files changed

+226
-218
lines changed

4 files changed

+226
-218
lines changed

packages/react-query/src/__tests__/prefetch.test-d.tsx renamed to packages/react-query/src/__tests__/usePrefetchInfiniteQuery.test-d.tsx

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,5 @@
11
import { describe, expectTypeOf, it } from 'vitest'
2-
import { usePrefetchInfiniteQuery, usePrefetchQuery } from '..'
3-
4-
describe('usePrefetchQuery', () => {
5-
it('should return nothing', () => {
6-
const result = usePrefetchQuery({
7-
queryKey: ['key'],
8-
queryFn: () => Promise.resolve(5),
9-
})
10-
11-
expectTypeOf(result).toEqualTypeOf<void>()
12-
})
13-
14-
it('should not allow refetchInterval, enabled or throwOnError options', () => {
15-
usePrefetchQuery({
16-
queryKey: ['key'],
17-
queryFn: () => Promise.resolve(5),
18-
// @ts-expect-error TS2345
19-
refetchInterval: 1000,
20-
})
21-
22-
usePrefetchQuery({
23-
queryKey: ['key'],
24-
queryFn: () => Promise.resolve(5),
25-
// @ts-expect-error TS2345
26-
enabled: true,
27-
})
28-
29-
usePrefetchQuery({
30-
queryKey: ['key'],
31-
queryFn: () => Promise.resolve(5),
32-
// @ts-expect-error TS2345
33-
throwOnError: true,
34-
})
35-
})
36-
})
2+
import { usePrefetchInfiniteQuery } from '..'
373

384
describe('useInfinitePrefetchQuery', () => {
395
it('should return nothing', () => {
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import { describe, expect, it, vi } from 'vitest'
2+
import React from 'react'
3+
import { fireEvent, waitFor } from '@testing-library/react'
4+
5+
import {
6+
QueryCache,
7+
usePrefetchInfiniteQuery,
8+
useSuspenseInfiniteQuery,
9+
} from '..'
10+
import { createQueryClient, queryKey, renderWithClient, sleep } from './utils'
11+
12+
import type { InfiniteData, UseSuspenseInfiniteQueryOptions } from '..'
13+
import type { Mock } from 'vitest'
14+
15+
const generateInfiniteQueryOptions = (
16+
data: Array<{ data: string; currentPage: number; totalPages: number }>,
17+
) => {
18+
let currentPage = 0
19+
20+
return {
21+
queryFn: vi
22+
.fn<(...args: Array<any>) => Promise<(typeof data)[number]>>()
23+
.mockImplementation(async () => {
24+
const currentPageData = data[currentPage]
25+
if (!currentPageData) {
26+
throw new Error('No data defined for page ' + currentPage)
27+
}
28+
29+
await sleep(10)
30+
currentPage++
31+
32+
return currentPageData
33+
}),
34+
initialPageParam: 1,
35+
getNextPageParam: (lastPage: (typeof data)[number]) =>
36+
lastPage.currentPage === lastPage.totalPages
37+
? undefined
38+
: lastPage.currentPage + 1,
39+
}
40+
}
41+
42+
describe('usePrefetchInfiniteQuery', () => {
43+
const queryCache = new QueryCache()
44+
const queryClient = createQueryClient({ queryCache })
45+
46+
const Fallback = vi.fn().mockImplementation(() => <div>Loading...</div>)
47+
48+
function Suspended<T = unknown>(props: {
49+
queryOpts: UseSuspenseInfiniteQueryOptions<
50+
T,
51+
Error,
52+
InfiniteData<T>,
53+
any,
54+
Array<string>,
55+
any
56+
>
57+
renderPage: (page: T) => React.JSX.Element
58+
}) {
59+
const state = useSuspenseInfiniteQuery(props.queryOpts)
60+
61+
return (
62+
<div>
63+
{state.data.pages.map((page, index) => (
64+
<div key={index}>{props.renderPage(page)}</div>
65+
))}
66+
<button onClick={() => state.fetchNextPage()}>Next Page</button>
67+
</div>
68+
)
69+
}
70+
71+
it('should prefetch an infinite query if query state does not exist', async () => {
72+
const data = [
73+
{ data: 'Do you fetch on render?', currentPage: 1, totalPages: 3 },
74+
{ data: 'Or do you render as you fetch?', currentPage: 2, totalPages: 3 },
75+
{
76+
data: 'Either way, Tanstack Query helps you!',
77+
currentPage: 3,
78+
totalPages: 3,
79+
},
80+
]
81+
82+
const queryOpts = {
83+
queryKey: queryKey(),
84+
...generateInfiniteQueryOptions(data),
85+
}
86+
87+
function App() {
88+
usePrefetchInfiniteQuery({ ...queryOpts, pages: data.length })
89+
90+
return (
91+
<React.Suspense fallback={<Fallback />}>
92+
<Suspended
93+
queryOpts={queryOpts}
94+
renderPage={(page) => <div>data: {page.data}</div>}
95+
/>
96+
</React.Suspense>
97+
)
98+
}
99+
100+
const rendered = renderWithClient(queryClient, <App />)
101+
102+
await waitFor(() => rendered.getByText('data: Do you fetch on render?'))
103+
fireEvent.click(rendered.getByText('Next Page'))
104+
await waitFor(() =>
105+
rendered.getByText('data: Or do you render as you fetch?'),
106+
)
107+
fireEvent.click(rendered.getByText('Next Page'))
108+
await waitFor(() =>
109+
rendered.getByText('data: Either way, Tanstack Query helps you!'),
110+
)
111+
expect(Fallback).toHaveBeenCalledTimes(1)
112+
expect(queryOpts.queryFn).toHaveBeenCalledTimes(3)
113+
})
114+
115+
it('should not display fallback if the query cache is already populated', async () => {
116+
const queryOpts = {
117+
queryKey: queryKey(),
118+
...generateInfiniteQueryOptions([
119+
{ data: 'Prefetch rocks!', currentPage: 1, totalPages: 3 },
120+
{ data: 'No waterfalls, boy!', currentPage: 2, totalPages: 3 },
121+
{ data: 'Tanstack Query #ftw', currentPage: 3, totalPages: 3 },
122+
]),
123+
}
124+
125+
await queryClient.prefetchInfiniteQuery({ ...queryOpts, pages: 3 })
126+
;(queryOpts.queryFn as Mock).mockClear()
127+
128+
function App() {
129+
usePrefetchInfiniteQuery(queryOpts)
130+
131+
return (
132+
<React.Suspense fallback={<Fallback />}>
133+
<Suspended
134+
queryOpts={queryOpts}
135+
renderPage={(page) => <div>data: {page.data}</div>}
136+
/>
137+
</React.Suspense>
138+
)
139+
}
140+
141+
const rendered = renderWithClient(queryClient, <App />)
142+
143+
await waitFor(() => rendered.getByText('data: Prefetch rocks!'))
144+
fireEvent.click(rendered.getByText('Next Page'))
145+
await waitFor(() => rendered.getByText('data: No waterfalls, boy!'))
146+
fireEvent.click(rendered.getByText('Next Page'))
147+
await waitFor(() => rendered.getByText('data: Tanstack Query #ftw'))
148+
expect(queryOpts.queryFn).not.toHaveBeenCalled()
149+
expect(Fallback).not.toHaveBeenCalled()
150+
})
151+
152+
it('should not create an endless loop when using inside a suspense boundary', async () => {
153+
const queryOpts = {
154+
queryKey: queryKey(),
155+
...generateInfiniteQueryOptions([
156+
{ data: 'Infinite Page 1', currentPage: 1, totalPages: 3 },
157+
{ data: 'Infinite Page 2', currentPage: 1, totalPages: 3 },
158+
{ data: 'Infinite Page 3', currentPage: 1, totalPages: 3 },
159+
]),
160+
}
161+
162+
function Prefetch({ children }: { children: React.ReactNode }) {
163+
usePrefetchInfiniteQuery(queryOpts)
164+
return <>{children}</>
165+
}
166+
167+
function App() {
168+
return (
169+
<React.Suspense>
170+
<Prefetch>
171+
<Suspended
172+
queryOpts={queryOpts}
173+
renderPage={(page) => <div>data: {page.data}</div>}
174+
/>
175+
</Prefetch>
176+
</React.Suspense>
177+
)
178+
}
179+
180+
const rendered = renderWithClient(queryClient, <App />)
181+
await waitFor(() => rendered.getByText('data: Infinite Page 1'))
182+
fireEvent.click(rendered.getByText('Next Page'))
183+
await waitFor(() => rendered.getByText('data: Infinite Page 2'))
184+
fireEvent.click(rendered.getByText('Next Page'))
185+
await waitFor(() => rendered.getByText('data: Infinite Page 3'))
186+
expect(queryOpts.queryFn).toHaveBeenCalledTimes(3)
187+
})
188+
})
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { describe, expectTypeOf, it } from 'vitest'
2+
import { usePrefetchQuery } from '..'
3+
4+
describe('usePrefetchQuery', () => {
5+
it('should return nothing', () => {
6+
const result = usePrefetchQuery({
7+
queryKey: ['key'],
8+
queryFn: () => Promise.resolve(5),
9+
})
10+
11+
expectTypeOf(result).toEqualTypeOf<void>()
12+
})
13+
14+
it('should not allow refetchInterval, enabled or throwOnError options', () => {
15+
usePrefetchQuery({
16+
queryKey: ['key'],
17+
queryFn: () => Promise.resolve(5),
18+
// @ts-expect-error TS2345
19+
refetchInterval: 1000,
20+
})
21+
22+
usePrefetchQuery({
23+
queryKey: ['key'],
24+
queryFn: () => Promise.resolve(5),
25+
// @ts-expect-error TS2345
26+
enabled: true,
27+
})
28+
29+
usePrefetchQuery({
30+
queryKey: ['key'],
31+
queryFn: () => Promise.resolve(5),
32+
// @ts-expect-error TS2345
33+
throwOnError: true,
34+
})
35+
})
36+
})

0 commit comments

Comments
 (0)