Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
import { describe, expectTypeOf, it } from 'vitest'
import { QueryClient } from '@tanstack/query-core'
import { queryKey } from '@tanstack/query-test-utils'
import { createInfiniteQuery } 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()
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()
queryClient.prefetchInfiniteQuery({
queryKey: queryKey(),
queryFn: ({ pageParam }) => {
expectTypeOf(pageParam).toEqualTypeOf<number>()
},
initialPageParam: 1,
})
})
})

describe('initialData', () => {
it('TData should have undefined in the union even 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> | undefined
>()
})

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
>()
})
})
})
138 changes: 138 additions & 0 deletions packages/svelte-query/tests/createMutation/createMutation.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { describe, expectTypeOf, it } from 'vitest'
import { QueryClient } from '@tanstack/query-core'
import { createMutation } from '../../src/index.js'
import type { DefaultError } from '@tanstack/query-core'
import type { CreateMutationResult } from '../../src/types.js'

describe('createMutation', () => {
it('should infer TData from mutationFn return type', () => {
const mutation = createMutation(() => ({
mutationFn: () => Promise.resolve('data'),
}))

expectTypeOf(mutation.data).toEqualTypeOf<string | undefined>()
expectTypeOf(mutation.error).toEqualTypeOf<DefaultError | null>()
})

it('should infer TVariables from mutationFn parameter', () => {
const mutation = createMutation(() => ({
mutationFn: (vars: { id: string }) => Promise.resolve(vars.id),
}))

expectTypeOf(mutation.mutate).toBeCallableWith({ id: '1' })
expectTypeOf(mutation.data).toEqualTypeOf<string | undefined>()
})

it('should infer TOnMutateResult from onMutate return type', () => {
createMutation(() => ({
mutationFn: () => Promise.resolve('data'),
onMutate: () => {
return { token: 'abc' }
},
onSuccess: (_data, _variables, onMutateResult) => {
expectTypeOf(onMutateResult).toEqualTypeOf<{ token: string }>()
},
onError: (_error, _variables, onMutateResult) => {
expectTypeOf(onMutateResult).toEqualTypeOf<
{ token: string } | undefined
>()
},
}))
})

it('should allow explicit generic types', () => {
const mutation = createMutation<string, Error, { id: number }>(() => ({
mutationFn: (vars) => {
expectTypeOf(vars).toEqualTypeOf<{ id: number }>()
return Promise.resolve('result')
},
}))

expectTypeOf(mutation.data).toEqualTypeOf<string | undefined>()
expectTypeOf(mutation.error).toEqualTypeOf<Error | null>()
})

it('should return correct CreateMutationResult type', () => {
const mutation = createMutation(() => ({
mutationFn: () => Promise.resolve(42),
}))

expectTypeOf(mutation).toEqualTypeOf<
CreateMutationResult<number, DefaultError, void, unknown>
>()
})

it('should type mutateAsync with correct return type', () => {
const mutation = createMutation(() => ({
mutationFn: (id: string) => Promise.resolve(id.length),
}))

expectTypeOf(mutation.mutateAsync).toBeCallableWith('test')
expectTypeOf(mutation.mutateAsync('test')).toEqualTypeOf<Promise<number>>()
})

it('should default TVariables to void when mutationFn has no parameters', () => {
const mutation = createMutation(() => ({
mutationFn: () => Promise.resolve('data'),
}))

expectTypeOf(mutation.mutate).toBeCallableWith()
})

it('should infer custom TError type', () => {
class CustomError extends Error {
code: number
constructor(code: number) {
super()
this.code = code
}
}

const mutation = createMutation<string, CustomError>(() => ({
mutationFn: () => Promise.resolve('data'),
}))

expectTypeOf(mutation.error).toEqualTypeOf<CustomError | null>()
expectTypeOf(mutation.data).toEqualTypeOf<string | undefined>()
})

it('should infer types for onSettled callback', () => {
createMutation(() => ({
mutationFn: () => Promise.resolve(42),
onSettled: (data, error, _variables, _onMutateResult) => {
expectTypeOf(data).toEqualTypeOf<number | undefined>()
expectTypeOf(error).toEqualTypeOf<DefaultError | null>()
},
}))
})

it('should infer custom TError in onError callback', () => {
class CustomError extends Error {
code: number
constructor(code: number) {
super()
this.code = code
}
}

createMutation<string, CustomError>(() => ({
mutationFn: () => Promise.resolve('data'),
onError: (error) => {
expectTypeOf(error).toEqualTypeOf<CustomError>()
},
}))
})

it('should accept queryClient as second argument', () => {
const queryClient = new QueryClient()

const mutation = createMutation(
() => ({
mutationFn: () => Promise.resolve('data'),
}),
() => queryClient,
)

expectTypeOf(mutation.data).toEqualTypeOf<string | undefined>()
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, expectTypeOf, it } from 'vitest'
import { useMutationState } from '../../src/index.js'
import type { MutationState, MutationStatus } from '@tanstack/query-core'

describe('useMutationState', () => {
it('should default to MutationState', () => {
const result = useMutationState({
filters: { status: 'pending' },
})

expectTypeOf(result).toEqualTypeOf<
Array<MutationState<unknown, Error, unknown, unknown>>
>()
})

it('should infer with select', () => {
const result = useMutationState({
filters: { status: 'pending' },
select: (mutation) => mutation.state.status,
})

expectTypeOf(result).toEqualTypeOf<Array<MutationStatus>>()
})
})
Loading