snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
autofix.ci / autofix (push) Failing after 4s
Release / Release (push) Has been skipped
GitHub Actions Security Analysis / Run zizmor (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-16 01:13:08 +05:00
commit 3a013ccdfe
3570 changed files with 490194 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
<script lang="ts">
import { untrack } from 'svelte'
import { queryKey, sleep } from '@tanstack/query-test-utils'
import { createInfiniteQuery } from '../../src/index.js'
import { setQueryClientContext } from '../../src/context.js'
import type { QueryClient, QueryObserverResult } from '@tanstack/query-core'
type Props = {
queryClient: QueryClient
states: { value: Array<QueryObserverResult> }
}
let { queryClient, states }: Props = $props()
setQueryClientContext(queryClient)
const query = createInfiniteQuery(() => ({
queryKey: queryKey(),
queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),
getNextPageParam: (lastPage) => lastPage + 1,
initialPageParam: 0,
}))
$effect(() => {
// @ts-expect-error
states.value = [...untrack(() => states.value), $state.snapshot(query)]
})
</script>
<div>Status: {query.status}</div>

View File

@@ -0,0 +1,39 @@
<script lang="ts">
import { QueryClient } from '@tanstack/query-core'
import { createInfiniteQuery } from '../../src/index.js'
import { setQueryClientContext } from '../../src/context.js'
import { sleep } from '@tanstack/query-test-utils'
type Props = {
queryClient: QueryClient
}
let { queryClient }: Props = $props()
const queryKey = ['test']
let firstPage = $state(0)
setQueryClientContext(queryClient)
const query = createInfiniteQuery(() => ({
queryKey: queryKey,
queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),
getNextPageParam: (lastPage) => lastPage + 1,
initialPageParam: firstPage,
}))
</script>
<button
onclick={() => {
queryClient.setQueryData(queryKey, {
pages: [7, 8],
pageParams: [7, 8],
})
firstPage = 7
}}
>
setPages
</button>
<div>Data: {JSON.stringify(query.data)}</div>

View File

@@ -0,0 +1,31 @@
<script lang="ts">
import { untrack } from 'svelte'
import { createInfiniteQuery } from '../../src/index.js'
import { setQueryClientContext } from '../../src/context.js'
import type { QueryClient, QueryObserverResult } from '@tanstack/query-core'
import { queryKey, sleep } from '@tanstack/query-test-utils'
type Props = {
queryClient: QueryClient
states: { value: Array<QueryObserverResult> }
}
let { queryClient, states }: Props = $props()
setQueryClientContext(queryClient)
const query = createInfiniteQuery(() => ({
queryKey: queryKey(),
queryFn: ({ pageParam }) => sleep(10).then(() => pageParam),
getNextPageParam: (lastPage) => lastPage + 1,
initialPageParam: 0,
initialData: { pages: [0], pageParams: [0] },
}))
$effect(() => {
// @ts-expect-error
states.value = [...untrack(() => states.value), $state.snapshot(query)]
})
</script>
<div>Status: {query.status}</div>

View File

@@ -0,0 +1,34 @@
<script lang="ts">
import { untrack } from 'svelte'
import { createInfiniteQuery } from '../../src/index.js'
import { setQueryClientContext } from '../../src/context.js'
import type { QueryClient, QueryObserverResult } from '@tanstack/query-core'
import { queryKey, sleep } from '@tanstack/query-test-utils'
type Props = {
queryClient: QueryClient
states: { value: Array<QueryObserverResult> }
}
let { queryClient, states }: Props = $props()
setQueryClientContext(queryClient)
const query = createInfiniteQuery(() => ({
queryKey: queryKey(),
queryFn: () => sleep(10).then(() => ({ count: 1 })),
select: (data) => ({
pages: data.pages.map((x) => `count: ${x.count}`),
pageParams: data.pageParams,
}),
getNextPageParam: () => undefined,
initialPageParam: 0,
}))
$effect(() => {
// @ts-expect-error
states.value = [...untrack(() => states.value), $state.snapshot(query)]
})
</script>
<div>{query.data?.pages.join(',')}</div>

View File

@@ -0,0 +1,174 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { fireEvent, render } from '@testing-library/svelte'
import { QueryClient } from '@tanstack/query-core'
import { ref } from '../utils.svelte.js'
import Base from './Base.svelte'
import Select from './Select.svelte'
import ChangeClient from './ChangeClient.svelte'
import InitialData from './InitialData.svelte'
import type { QueryObserverResult } from '@tanstack/query-core'
describe('createInfiniteQuery', () => {
let queryClient: QueryClient
beforeEach(() => {
vi.useFakeTimers()
queryClient = new QueryClient()
})
afterEach(() => {
queryClient.clear()
vi.useRealTimers()
})
it('should return the correct states for a successful query', async () => {
let states = ref<Array<QueryObserverResult>>([])
const rendered = render(Base, {
props: {
queryClient,
states,
},
})
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('Status: success')).toBeInTheDocument()
expect(states.value).toHaveLength(2)
expect(states.value[0]).toEqual({
data: undefined,
dataUpdatedAt: 0,
error: null,
errorUpdatedAt: 0,
failureCount: 0,
failureReason: null,
errorUpdateCount: 0,
fetchNextPage: expect.any(Function),
fetchPreviousPage: expect.any(Function),
hasNextPage: false,
hasPreviousPage: false,
isError: false,
isFetched: false,
isFetchedAfterMount: false,
isFetching: true,
isPaused: false,
isFetchNextPageError: false,
isFetchingNextPage: false,
isFetchPreviousPageError: false,
isFetchingPreviousPage: false,
isLoading: true,
isPending: true,
isInitialLoading: true,
isLoadingError: false,
isPlaceholderData: false,
isRefetchError: false,
isRefetching: false,
isStale: true,
isSuccess: false,
isEnabled: true,
refetch: expect.any(Function),
status: 'pending',
fetchStatus: 'fetching',
})
expect(states.value[1]).toEqual({
data: { pages: [0], pageParams: [0] },
dataUpdatedAt: expect.any(Number),
error: null,
errorUpdatedAt: 0,
failureCount: 0,
failureReason: null,
errorUpdateCount: 0,
fetchNextPage: expect.any(Function),
fetchPreviousPage: expect.any(Function),
hasNextPage: true,
hasPreviousPage: false,
isError: false,
isFetched: true,
isFetchedAfterMount: true,
isFetching: false,
isPaused: false,
isFetchNextPageError: false,
isFetchingNextPage: false,
isFetchPreviousPageError: false,
isFetchingPreviousPage: false,
isLoading: false,
isPending: false,
isInitialLoading: false,
isLoadingError: false,
isPlaceholderData: false,
isRefetchError: false,
isRefetching: false,
isStale: true,
isSuccess: true,
isEnabled: true,
refetch: expect.any(Function),
status: 'success',
fetchStatus: 'idle',
})
})
it('should render with initialData and no pending state', async () => {
let states = ref<Array<QueryObserverResult>>([])
const rendered = render(InitialData, {
props: {
queryClient,
states,
},
})
expect(rendered.getByText('Status: success')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(states.value.every((state) => state.status === 'success')).toBe(true)
expect(states.value[0]?.data).toEqual({ pages: [0], pageParams: [0] })
})
it('should be able to select a part of the data', async () => {
let states = ref<Array<QueryObserverResult>>([])
const rendered = render(Select, {
props: {
queryClient,
states,
},
})
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('count: 1')).toBeInTheDocument()
expect(states.value).toHaveLength(2)
expect(states.value[0]).toMatchObject({
data: undefined,
isSuccess: false,
})
expect(states.value[1]).toMatchObject({
data: { pages: ['count: 1'] },
isSuccess: true,
})
})
it('should be able to set new pages with the query client', async () => {
const rendered = render(ChangeClient, {
props: {
queryClient,
},
})
await vi.advanceTimersByTimeAsync(10)
expect(
rendered.getByText('Data: {"pages":[0],"pageParams":[0]}'),
).toBeInTheDocument()
fireEvent.click(rendered.getByRole('button', { name: /setPages/i }))
await vi.advanceTimersByTimeAsync(10)
expect(
rendered.getByText('Data: {"pages":[7,8],"pageParams":[7,8]}'),
).toBeInTheDocument()
})
})

View File

@@ -0,0 +1,227 @@
import { describe, expectTypeOf, it } from 'vitest'
import { QueryClient } from '@tanstack/query-core'
import { queryKey } from '@tanstack/query-test-utils'
import { createInfiniteQuery, infiniteQueryOptions } from '../../src/index.js'
import type { InfiniteData } from '@tanstack/query-core'
describe('createInfiniteQuery', () => {
describe('pageParam', () => {
it('initialPageParam should define type of param passed to queryFunctionContext', () => {
createInfiniteQuery(() => ({
queryKey: queryKey(),
queryFn: ({ pageParam }) => {
expectTypeOf(pageParam).toEqualTypeOf<number>()
},
initialPageParam: 1,
getNextPageParam: () => undefined,
}))
})
it('direction should be passed to queryFn of createInfiniteQuery', () => {
createInfiniteQuery(() => ({
queryKey: queryKey(),
queryFn: ({ direction }) => {
expectTypeOf(direction).toEqualTypeOf<'forward' | 'backward'>()
},
initialPageParam: 1,
getNextPageParam: () => undefined,
}))
})
it('initialPageParam should define type of param passed to queryFunctionContext for fetchInfiniteQuery', () => {
const queryClient = new QueryClient()
// grandfathered direct test
// eslint-disable-next-line no-restricted-syntax
queryClient.fetchInfiniteQuery({
queryKey: queryKey(),
queryFn: ({ pageParam }) => {
expectTypeOf(pageParam).toEqualTypeOf<number>()
},
initialPageParam: 1,
})
})
it('initialPageParam should define type of param passed to queryFunctionContext for prefetchInfiniteQuery', () => {
const queryClient = new QueryClient()
// grandfathered direct test
// eslint-disable-next-line no-restricted-syntax
queryClient.prefetchInfiniteQuery({
queryKey: queryKey(),
queryFn: ({ pageParam }) => {
expectTypeOf(pageParam).toEqualTypeOf<number>()
},
initialPageParam: 1,
})
})
})
describe('initialData', () => {
it('TData should always be defined when initialData is provided', () => {
const { data } = createInfiniteQuery(() => ({
queryKey: queryKey(),
queryFn: ({ pageParam }) => {
return pageParam * 5
},
initialPageParam: 1,
getNextPageParam: () => undefined,
initialData: { pages: [5], pageParams: [1] },
}))
// TODO: Order of generics prevents pageParams to be typed correctly. Using `unknown` for now
expectTypeOf(data).toEqualTypeOf<InfiniteData<number, unknown>>()
})
it('TData should always be defined when initialData is provided through infiniteQueryOptions', () => {
const options = infiniteQueryOptions({
queryKey: queryKey(),
queryFn: ({ pageParam }: { pageParam: number }) => {
return pageParam * 5
},
initialPageParam: 1,
getNextPageParam: () => undefined,
initialData: { pages: [5], pageParams: [1] },
})
const { data } = createInfiniteQuery(() => options)
// known issue: type of pageParams is unknown when returned from createInfiniteQuery
expectTypeOf(data).toEqualTypeOf<InfiniteData<number, unknown>>()
})
it('TData should have undefined in the union when initialData is NOT provided', () => {
const { data } = createInfiniteQuery(() => ({
queryKey: queryKey(),
queryFn: ({ pageParam }) => {
return pageParam * 5
},
initialPageParam: 1,
getNextPageParam: () => undefined,
}))
expectTypeOf(data).toEqualTypeOf<
InfiniteData<number, unknown> | undefined
>()
})
})
describe('select', () => {
it('should still return paginated data if no select result', () => {
const infiniteQuery = createInfiniteQuery(() => ({
queryKey: queryKey(),
queryFn: ({ pageParam }) => {
return pageParam * 5
},
initialPageParam: 1,
getNextPageParam: () => undefined,
}))
// TODO: Order of generics prevents pageParams to be typed correctly. Using `unknown` for now
expectTypeOf(infiniteQuery.data).toEqualTypeOf<
InfiniteData<number, unknown> | undefined
>()
})
it('should be able to transform data to arbitrary result', () => {
const infiniteQuery = createInfiniteQuery(() => ({
queryKey: queryKey(),
queryFn: ({ pageParam }) => {
return pageParam * 5
},
initialPageParam: 1,
getNextPageParam: () => undefined,
select: (data) => {
expectTypeOf(data).toEqualTypeOf<InfiniteData<number, number>>()
return 'selected' as const
},
}))
expectTypeOf(infiniteQuery.data).toEqualTypeOf<'selected' | undefined>()
})
})
describe('getNextPageParam / getPreviousPageParam', () => {
it('should get typed params', () => {
const infiniteQuery = createInfiniteQuery(() => ({
queryKey: queryKey(),
queryFn: ({ pageParam }) => {
return String(pageParam)
},
initialPageParam: 1,
getNextPageParam: (
lastPage,
allPages,
lastPageParam,
allPageParams,
) => {
expectTypeOf(lastPage).toEqualTypeOf<string>()
expectTypeOf(allPages).toEqualTypeOf<Array<string>>()
expectTypeOf(lastPageParam).toEqualTypeOf<number>()
expectTypeOf(allPageParams).toEqualTypeOf<Array<number>>()
return undefined
},
getPreviousPageParam: (
firstPage,
allPages,
firstPageParam,
allPageParams,
) => {
expectTypeOf(firstPage).toEqualTypeOf<string>()
expectTypeOf(allPages).toEqualTypeOf<Array<string>>()
expectTypeOf(firstPageParam).toEqualTypeOf<number>()
expectTypeOf(allPageParams).toEqualTypeOf<Array<number>>()
return undefined
},
}))
// TODO: Order of generics prevents pageParams to be typed correctly. Using `unknown` for now
expectTypeOf(infiniteQuery.data).toEqualTypeOf<
InfiniteData<string, unknown> | undefined
>()
})
})
describe('error booleans', () => {
it('should not be permanently `false`', () => {
const {
isFetchNextPageError,
isFetchPreviousPageError,
isLoadingError,
isRefetchError,
} = createInfiniteQuery(() => ({
queryKey: queryKey(),
queryFn: ({ pageParam }) => {
return pageParam * 5
},
initialPageParam: 1,
getNextPageParam: () => undefined,
}))
expectTypeOf(isFetchNextPageError).toEqualTypeOf<boolean>()
expectTypeOf(isFetchPreviousPageError).toEqualTypeOf<boolean>()
expectTypeOf(isLoadingError).toEqualTypeOf<boolean>()
expectTypeOf(isRefetchError).toEqualTypeOf<boolean>()
})
})
describe('queryClient', () => {
it('should accept queryClient as second argument', () => {
const queryClient = new QueryClient()
const infiniteQuery = createInfiniteQuery(
() => ({
queryKey: queryKey(),
queryFn: ({ pageParam }) => {
return pageParam * 5
},
initialPageParam: 1,
getNextPageParam: () => undefined,
}),
() => queryClient,
)
// TODO: Order of generics prevents pageParams to be typed correctly. Using `unknown` for now
expectTypeOf(infiniteQuery.data).toEqualTypeOf<
InfiniteData<number, unknown> | undefined
>()
})
})
})