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() }, 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() }, 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() }, 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>() }) 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>() }) 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 | 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 | 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>() 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() expectTypeOf(allPages).toEqualTypeOf>() expectTypeOf(lastPageParam).toEqualTypeOf() expectTypeOf(allPageParams).toEqualTypeOf>() return undefined }, getPreviousPageParam: ( firstPage, allPages, firstPageParam, allPageParams, ) => { expectTypeOf(firstPage).toEqualTypeOf() expectTypeOf(allPages).toEqualTypeOf>() expectTypeOf(firstPageParam).toEqualTypeOf() expectTypeOf(allPageParams).toEqualTypeOf>() return undefined }, })) // TODO: Order of generics prevents pageParams to be typed correctly. Using `unknown` for now expectTypeOf(infiniteQuery.data).toEqualTypeOf< InfiniteData | 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() expectTypeOf(isFetchPreviousPageError).toEqualTypeOf() expectTypeOf(isLoadingError).toEqualTypeOf() expectTypeOf(isRefetchError).toEqualTypeOf() }) }) 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 | undefined >() }) }) })