@tanstack/vue-query
Version:
Hooks for managing, caching and syncing asynchronous and remote data in Vue
278 lines (246 loc) • 7.25 kB
text/typescript
import { describe, it } from 'vitest'
import { reactive } from 'vue-demi'
import { useQuery } from '../useQuery'
import { queryOptions } from '../queryOptions'
import { doNotExecute, simpleFetcher } from './test-utils'
import type { UseQueryOptions } from '../useQuery'
import type { Equal, Expect } from './test-utils'
describe('initialData', () => {
describe('Config object overload', () => {
it('TData should always be defined when initialData is provided as an object', () => {
doNotExecute(() => {
const { data } = reactive(
useQuery({
queryKey: ['key'],
queryFn: () => {
return {
wow: true,
}
},
initialData: {
wow: true,
},
}),
)
const result: Expect<Equal<{ wow: boolean }, typeof data>> = true
return result
})
})
it('TData should be defined when passed through queryOptions', () => {
doNotExecute(() => {
const options = queryOptions({
queryKey: ['key'],
queryFn: () => {
return {
wow: true,
}
},
initialData: {
wow: true,
},
})
const { data } = reactive(useQuery(options))
const result: Expect<Equal<{ wow: boolean }, typeof data>> = true
return result
})
})
it('it should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => {
doNotExecute(() => {
const options = queryOptions({
queryKey: ['key'],
queryFn: () => Promise.resolve(1),
})
const query = reactive(
useQuery({
...options,
select: (data) => data > 1,
}),
)
const result: Expect<Equal<boolean | undefined, typeof query.data>> =
true
return result
})
})
it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {
doNotExecute(() => {
const { data } = reactive(
useQuery({
queryKey: ['key'],
queryFn: () => {
return {
wow: true,
}
},
initialData: () => ({
wow: true,
}),
}),
)
const result: Expect<Equal<{ wow: boolean }, typeof data>> = true
return result
})
})
it('TData should have undefined in the union when initialData is NOT provided', () => {
doNotExecute(() => {
const { data } = reactive(
useQuery({
queryKey: ['key'],
queryFn: () => {
return {
wow: true,
}
},
}),
)
const result: Expect<Equal<{ wow: boolean } | undefined, typeof data>> =
true
return result
})
})
it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {
doNotExecute(() => {
const { data } = reactive(
useQuery({
queryKey: ['key'],
queryFn: () => {
return {
wow: true,
}
},
initialData: () => undefined as { wow: boolean } | undefined,
}),
)
const result: Expect<Equal<{ wow: boolean } | undefined, typeof data>> =
true
return result
})
})
it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => {
doNotExecute(() => {
const { data, isSuccess } = reactive(
useQuery({
queryKey: ['key'],
queryFn: () => {
return {
wow: true,
}
},
initialData: () => undefined as { wow: boolean } | undefined,
}),
)
if (isSuccess) {
const result: Expect<Equal<{ wow: boolean }, typeof data>> = true
return result
}
return false
})
})
})
describe('custom composables', () => {
it('should allow custom composables using UseQueryOptions', () => {
doNotExecute(() => {
type Data = string
const useCustomQuery = (
options?: Omit<UseQueryOptions<Data>, 'queryKey' | 'queryFn'>,
) => {
return useQuery({
...options,
queryKey: ['todos-key'],
queryFn: () => Promise.resolve('data'),
})
}
const { data } = reactive(useCustomQuery())
const result: Expect<Equal<Data | undefined, typeof data>> = true
return result
})
})
})
describe('structuralSharing', () => {
it('should restrict to same types', () => {
doNotExecute(() => {
useQuery({
queryKey: ['key'],
queryFn: () => 5,
structuralSharing: (_oldData, newData) => {
return newData
},
})
})
})
})
describe('Discriminated union return type', () => {
it('data should be possibly undefined by default', () => {
doNotExecute(() => {
const query = reactive(
useQuery({
queryKey: ['key'],
queryFn: simpleFetcher,
}),
)
const result: Expect<Equal<string | undefined, typeof query.data>> =
true
return result
})
})
it('data should be defined when query is success', () => {
doNotExecute(() => {
const query = reactive(
useQuery({
queryKey: ['key'],
queryFn: simpleFetcher,
}),
)
if (query.isSuccess) {
const result: Expect<Equal<string, typeof query.data>> = true
return result
}
return
})
})
it('error should be null when query is success', () => {
doNotExecute(() => {
const query = reactive(
useQuery({
queryKey: ['key'],
queryFn: simpleFetcher,
}),
)
if (query.isSuccess) {
const result: Expect<Equal<null, typeof query.error>> = true
return result
}
return
})
})
it('data should be undefined when query is pending', () => {
doNotExecute(() => {
const query = reactive(
useQuery({
queryKey: ['key'],
queryFn: simpleFetcher,
}),
)
if (query.isPending) {
const result: Expect<Equal<undefined, typeof query.data>> = true
return result
}
return
})
})
it('error should be defined when query is error', () => {
doNotExecute(() => {
const query = reactive(
useQuery({
queryKey: ['key'],
queryFn: simpleFetcher,
}),
)
if (query.isError) {
const result: Expect<Equal<Error, typeof query.error>> = true
return result
}
return
})
})
})
})