diff --git a/packages/preact-query/src/__tests__/useSuspenseQuery.test.tsx b/packages/preact-query/src/__tests__/useSuspenseQuery.test.tsx index 8397312bb6..bdad41475d 100644 --- a/packages/preact-query/src/__tests__/useSuspenseQuery.test.tsx +++ b/packages/preact-query/src/__tests__/useSuspenseQuery.test.tsx @@ -8,6 +8,7 @@ import { QueryCache, QueryClient, QueryErrorResetBoundary, + experimental_streamedQuery, skipToken, useQueryErrorResetBoundary, useSuspenseInfiniteQuery, @@ -1045,4 +1046,138 @@ describe('useSuspenseQuery', () => { consoleErrorSpy.mockRestore() process.env.NODE_ENV = envCopy }) + + it('should release suspense when setQueryData is called while fetch is in-flight', async () => { + const key = queryKey() + + function Content() { + const { data } = useSuspenseQuery({ + queryKey: key, + queryFn: () => sleep(10000).then(() => 'fetched'), + }) + return
data: {data}
+ } + + function Page() { + return ( +
+ + + + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + expect(rendered.getByText('loading')).toBeInTheDocument() + + fireEvent.click(rendered.getByText('set data')) + await vi.advanceTimersByTimeAsync(0) + + expect(rendered.getByText('data: manual data')).toBeInTheDocument() + }) + + it('should release suspense when streamedQuery receives first chunk', async () => { + const key = queryKey() + + async function* numberGenerator() { + await sleep(10) + yield 'chunk1' + await sleep(10) + yield 'chunk2' + } + + function Page() { + const { data } = useSuspenseQuery({ + queryKey: key, + queryFn: experimental_streamedQuery({ + streamFn: () => numberGenerator(), + }), + }) + return
data: {data}
+ } + + const streamedClient = new QueryClient({ + queryCache, + }) + + const rendered = renderWithClient( + streamedClient, + + + , + ) + + expect(rendered.getByText('loading')).toBeInTheDocument() + + await vi.advanceTimersByTimeAsync(10) + + expect(rendered.getByText('data: chunk1')).toBeInTheDocument() + }) + + it('should release suspense when setQueryData is called before component mounts', async () => { + const key = queryKey() + queryClient.setQueryData(key, 'preloaded') + + function Page() { + const { data } = useSuspenseQuery({ + queryKey: key, + queryFn: () => sleep(10000).then(() => 'fetched'), + }) + return
data: {data}
+ } + + const rendered = renderWithClient( + queryClient, + + + , + ) + + await vi.advanceTimersByTimeAsync(0) + + expect(rendered.getByText('data: preloaded')).toBeInTheDocument() + }) + + it('should NOT release suspense when setQueryData is called with undefined', async () => { + const key = queryKey() + + function Content() { + const { data } = useSuspenseQuery({ + queryKey: key, + queryFn: () => sleep(10000).then(() => 'fetched'), + }) + return
data: {data}
+ } + + function Page() { + return ( +
+ + + + +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + expect(rendered.getByText('loading')).toBeInTheDocument() + + fireEvent.click(rendered.getByText('set undefined')) + await vi.advanceTimersByTimeAsync(0) + + // Suspense should NOT release — setQueryData(undefined) doesn't satisfy + // the query.state.data !== undefined guard in fetchOptimistic + expect(rendered.getByText('loading')).toBeInTheDocument() + }) })