diff --git a/packages/angular-query-experimental/src/__tests__/inject-mutation.test-d.ts b/packages/angular-query-experimental/src/__tests__/inject-mutation.test-d.ts index f331bb02de..b3a45d1c37 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-mutation.test-d.ts +++ b/packages/angular-query-experimental/src/__tests__/inject-mutation.test-d.ts @@ -3,69 +3,73 @@ import { sleep } from '@tanstack/query-test-utils' import { injectMutation } from '..' import type { Signal } from '@angular/core' -describe('Discriminated union return type', () => { - test('data should be possibly undefined by default', () => { - const mutation = injectMutation(() => ({ - mutationFn: () => sleep(0).then(() => 'string'), - })) +describe('injectMutation', () => { + describe('Discriminated union return type', () => { + test('data should be possibly undefined by default', () => { + const mutation = injectMutation(() => ({ + mutationFn: () => sleep(0).then(() => 'string'), + })) - expectTypeOf(mutation.data).toEqualTypeOf>() - }) + expectTypeOf(mutation.data).toEqualTypeOf>() + }) - test('data should be defined when mutation is success', () => { - const mutation = injectMutation(() => ({ - mutationFn: () => sleep(0).then(() => 'string'), - })) + test('data should be defined when mutation is success', () => { + const mutation = injectMutation(() => ({ + mutationFn: () => sleep(0).then(() => 'string'), + })) - if (mutation.isSuccess()) { - expectTypeOf(mutation.data).toEqualTypeOf>() - } - }) + if (mutation.isSuccess()) { + expectTypeOf(mutation.data).toEqualTypeOf>() + } + }) - test('error should be null when mutation is success', () => { - const mutation = injectMutation(() => ({ - mutationFn: () => sleep(0).then(() => 'string'), - })) + test('error should be null when mutation is success', () => { + const mutation = injectMutation(() => ({ + mutationFn: () => sleep(0).then(() => 'string'), + })) - if (mutation.isSuccess()) { - expectTypeOf(mutation.error).toEqualTypeOf>() - } - }) + if (mutation.isSuccess()) { + expectTypeOf(mutation.error).toEqualTypeOf>() + } + }) - test('data should be undefined when mutation is pending', () => { - const mutation = injectMutation(() => ({ - mutationFn: () => sleep(0).then(() => 'string'), - })) + test('data should be undefined when mutation is pending', () => { + const mutation = injectMutation(() => ({ + mutationFn: () => sleep(0).then(() => 'string'), + })) - if (mutation.isPending()) { - expectTypeOf(mutation.data).toEqualTypeOf>() - } - }) + if (mutation.isPending()) { + expectTypeOf(mutation.data).toEqualTypeOf>() + } + }) - test('error should be defined when mutation is error', () => { - const mutation = injectMutation(() => ({ - mutationFn: () => sleep(0).then(() => 'string'), - })) + test('error should be defined when mutation is error', () => { + const mutation = injectMutation(() => ({ + mutationFn: () => sleep(0).then(() => 'string'), + })) - if (mutation.isError()) { - expectTypeOf(mutation.error).toEqualTypeOf>() - } - }) + if (mutation.isError()) { + expectTypeOf(mutation.error).toEqualTypeOf>() + } + }) - test('should narrow variables', () => { - const mutation = injectMutation(() => ({ - mutationFn: (_variables: string) => sleep(0).then(() => 'string'), - })) + test('should narrow variables', () => { + const mutation = injectMutation(() => ({ + mutationFn: (_variables: string) => sleep(0).then(() => 'string'), + })) - if (mutation.isIdle()) { - expectTypeOf(mutation.variables).toEqualTypeOf>() - } - if (mutation.isPending()) { - expectTypeOf(mutation.variables).toEqualTypeOf>() - } - if (mutation.isSuccess()) { - expectTypeOf(mutation.variables).toEqualTypeOf>() - } - expectTypeOf(mutation.variables).toEqualTypeOf>() + if (mutation.isIdle()) { + expectTypeOf(mutation.variables).toEqualTypeOf>() + } + if (mutation.isPending()) { + expectTypeOf(mutation.variables).toEqualTypeOf>() + } + if (mutation.isSuccess()) { + expectTypeOf(mutation.variables).toEqualTypeOf>() + } + expectTypeOf(mutation.variables).toEqualTypeOf< + Signal + >() + }) }) }) diff --git a/packages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts b/packages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts index 62547fd9e0..de3f7e6857 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts +++ b/packages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts @@ -5,173 +5,177 @@ import { queryOptions } from '../query-options' import type { CreateQueryOptions, CreateQueryResult, OmitKeyof } from '..' import type { Signal } from '@angular/core' -describe('InjectQueries config object overload', () => { - it('TData should always be defined when initialData is provided as an object', () => { - const query1 = { - queryKey: ['key1'], - queryFn: () => { - return { - wow: true, - } - }, - initialData: { - wow: false, - }, - } - - const query2 = { - queryKey: ['key2'], - queryFn: () => 'Query Data', - initialData: 'initial data', - } - - const query3 = { - queryKey: ['key2'], - queryFn: () => 'Query Data', - } - - const queryResults = injectQueries(() => ({ - queries: [query1, query2, query3], - })) - - const query1Data = queryResults()[0].data() - const query2Data = queryResults()[1].data() - const query3Data = queryResults()[2].data() - - expectTypeOf(query1Data).toEqualTypeOf<{ wow: boolean }>() - expectTypeOf(query2Data).toEqualTypeOf() - expectTypeOf(query3Data).toEqualTypeOf() - }) +describe('injectQueries', () => { + describe('config object overload', () => { + it('TData should always be defined when initialData is provided as an object', () => { + const query1 = { + queryKey: ['key1'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: false, + }, + } - it('TData should be defined when passed through queryOptions', () => { - const options = queryOptions({ - queryKey: ['key'], - queryFn: () => { - return { - wow: true, - } - }, - initialData: { - wow: true, - }, - }) - const queryResults = injectQueries(() => ({ queries: [options] })) + const query2 = { + queryKey: ['key2'], + queryFn: () => 'Query Data', + initialData: 'initial data', + } - const data = queryResults()[0].data() + const query3 = { + queryKey: ['key2'], + queryFn: () => 'Query Data', + } - expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>() - }) + const queryResults = injectQueries(() => ({ + queries: [query1, query2, query3], + })) + + const query1Data = queryResults()[0].data() + const query2Data = queryResults()[1].data() + const query3Data = queryResults()[2].data() - it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into injectQuery', () => { - const query1 = queryOptions({ - queryKey: ['key'], - queryFn: () => Promise.resolve(1), - select: (data) => data > 1, + expectTypeOf(query1Data).toEqualTypeOf<{ wow: boolean }>() + expectTypeOf(query2Data).toEqualTypeOf() + expectTypeOf(query3Data).toEqualTypeOf() }) - const query2 = { - queryKey: ['key'], - queryFn: () => Promise.resolve(1), - select: (data: number) => data > 1, - } + it('TData should be defined when passed through queryOptions', () => { + const options = queryOptions({ + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + const queryResults = injectQueries(() => ({ queries: [options] })) - const queryResults = injectQueries(() => ({ queries: [query1, query2] })) - const query1Data = queryResults()[0].data() - const query2Data = queryResults()[1].data() + const data = queryResults()[0].data() - expectTypeOf(query1Data).toEqualTypeOf() - expectTypeOf(query2Data).toEqualTypeOf() - }) + expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>() + }) - it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { - const queryResults = injectQueries(() => ({ - queries: [ - { - queryKey: ['key'], - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => undefined as { wow: boolean } | undefined, - }, - ], - })) + it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into injectQuery', () => { + const query1 = queryOptions({ + queryKey: ['key'], + queryFn: () => Promise.resolve(1), + select: (data) => data > 1, + }) + + const query2 = { + queryKey: ['key'], + queryFn: () => Promise.resolve(1), + select: (data: number) => data > 1, + } - const data = queryResults()[0].data() + const queryResults = injectQueries(() => ({ queries: [query1, query2] })) + const query1Data = queryResults()[0].data() + const query2Data = queryResults()[1].data() - expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>() - }) + expectTypeOf(query1Data).toEqualTypeOf() + expectTypeOf(query2Data).toEqualTypeOf() + }) - describe('custom injectable', () => { - it('should allow custom hooks using UseQueryOptions', () => { - type Data = string - - const injectCustomQueries = ( - options?: OmitKeyof, 'queryKey' | 'queryFn'>, - ) => { - return injectQueries(() => ({ - queries: [ - { - ...options, - queryKey: ['todos-key'], - queryFn: () => Promise.resolve('data'), + it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { + const queryResults = injectQueries(() => ({ + queries: [ + { + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } }, - ], - })) - } + initialData: () => undefined as { wow: boolean } | undefined, + }, + ], + })) - const queryResults = injectCustomQueries() const data = queryResults()[0].data() - expectTypeOf(data).toEqualTypeOf() + expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>() }) - }) - it('TData should have correct type when conditional skipToken is passed', () => { - const queryResults = injectQueries(() => ({ - queries: [ - { - queryKey: ['withSkipToken'], - queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), - }, - ], - })) + describe('custom injectable', () => { + it('should allow custom hooks using UseQueryOptions', () => { + type Data = string + + const injectCustomQueries = ( + options?: OmitKeyof, 'queryKey' | 'queryFn'>, + ) => { + return injectQueries(() => ({ + queries: [ + { + ...options, + queryKey: ['todos-key'], + queryFn: () => Promise.resolve('data'), + }, + ], + })) + } - const firstResult = queryResults()[0] + const queryResults = injectCustomQueries() + const data = queryResults()[0].data() - expectTypeOf(firstResult).toEqualTypeOf>() - expectTypeOf(firstResult.data()).toEqualTypeOf() - }) + expectTypeOf(data).toEqualTypeOf() + }) + }) + + it('TData should have correct type when conditional skipToken is passed', () => { + const queryResults = injectQueries(() => ({ + queries: [ + { + queryKey: ['withSkipToken'], + queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), + }, + ], + })) + + const firstResult = queryResults()[0] + + expectTypeOf(firstResult).toEqualTypeOf< + CreateQueryResult + >() + expectTypeOf(firstResult.data()).toEqualTypeOf() + }) - it('should return correct data for dynamic queries with mixed result types', () => { - const Queries1 = { - get: () => - queryOptions({ - queryKey: ['key1'], - queryFn: () => Promise.resolve(1), - }), - } - const Queries2 = { - get: () => - queryOptions({ - queryKey: ['key2'], - queryFn: () => Promise.resolve(true), - }), - } - - const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() })) - const result = injectQueries(() => ({ - queries: [...queries1List, { ...Queries2.get() }], - })) - - expectTypeOf(result).branded.toEqualTypeOf< - Signal< - [ - ...Array>, - CreateQueryResult, - ] - > - >() + it('should return correct data for dynamic queries with mixed result types', () => { + const Queries1 = { + get: () => + queryOptions({ + queryKey: ['key1'], + queryFn: () => Promise.resolve(1), + }), + } + const Queries2 = { + get: () => + queryOptions({ + queryKey: ['key2'], + queryFn: () => Promise.resolve(true), + }), + } + + const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() })) + const result = injectQueries(() => ({ + queries: [...queries1List, { ...Queries2.get() }], + })) + + expectTypeOf(result).branded.toEqualTypeOf< + Signal< + [ + ...Array>, + CreateQueryResult, + ] + > + >() + }) }) }) diff --git a/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts b/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts index 541ad65f14..a220ccfa6f 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts +++ b/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts @@ -3,177 +3,179 @@ import { sleep } from '@tanstack/query-test-utils' import { injectQuery, queryOptions } from '..' import type { Signal } from '@angular/core' -describe('initialData', () => { - describe('Config object overload', () => { - it('TData should always be defined when initialData is provided as an object', () => { - const { data } = injectQuery(() => ({ - queryKey: ['key'], - queryFn: () => ({ wow: true }), - initialData: { wow: true }, - })) +describe('injectQuery', () => { + describe('initialData', () => { + describe('Config object overload', () => { + it('TData should always be defined when initialData is provided as an object', () => { + const { data } = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => ({ wow: true }), + initialData: { wow: true }, + })) - expectTypeOf(data).toEqualTypeOf>() - }) + expectTypeOf(data).toEqualTypeOf>() + }) - it('TData should be defined when passed through queryOptions', () => { - const options = () => - queryOptions({ + it('TData should be defined when passed through queryOptions', () => { + const options = () => + queryOptions({ + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: { + wow: true, + }, + }) + const { data } = injectQuery(options) + + expectTypeOf(data).toEqualTypeOf>() + }) + + it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => { + const options = queryOptions({ + queryKey: ['key'], + queryFn: () => Promise.resolve(1), + }) + + const query = injectQuery(() => ({ + ...options, + select: (data) => data > 1, + })) + + expectTypeOf(query.data).toEqualTypeOf>() + }) + + it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => { + const { data } = injectQuery(() => ({ queryKey: ['key'], queryFn: () => { return { wow: true, } }, - initialData: { + initialData: () => ({ wow: true, + }), + })) + + expectTypeOf(data).toEqualTypeOf>() + }) + + it('TData should have undefined in the union when initialData is NOT provided', () => { + const { data } = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } }, - }) - const { data } = injectQuery(options) + })) - expectTypeOf(data).toEqualTypeOf>() - }) + expectTypeOf(data).toEqualTypeOf>() + }) - it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => { - const options = queryOptions({ - queryKey: ['key'], - queryFn: () => Promise.resolve(1), + it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { + const { data } = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => undefined as { wow: boolean } | undefined, + })) + + expectTypeOf(data).toEqualTypeOf>() }) - const query = injectQuery(() => ({ - ...options, - select: (data) => data > 1, - })) + it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => { + return { + wow: true, + } + }, + initialData: () => undefined as { wow: boolean } | undefined, + })) - expectTypeOf(query.data).toEqualTypeOf>() + if (query.isSuccess()) { + expectTypeOf(query.data).toEqualTypeOf>() + } + }) }) - it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => { - const { data } = injectQuery(() => ({ - queryKey: ['key'], - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => ({ - wow: true, - }), - })) - - expectTypeOf(data).toEqualTypeOf>() + describe('structuralSharing', () => { + it('should be able to use structuralSharing with unknown types', () => { + // https://github.com/TanStack/query/issues/6525#issuecomment-1938411343 + injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => 5, + structuralSharing: (oldData, newData) => { + expectTypeOf(oldData).toBeUnknown() + expectTypeOf(newData).toBeUnknown() + return newData + }, + })) + }) }) + }) - it('TData should have undefined in the union when initialData is NOT provided', () => { - const { data } = injectQuery(() => ({ + describe('Discriminated union return type', () => { + test('data should be possibly undefined by default', () => { + const query = injectQuery(() => ({ queryKey: ['key'], - queryFn: () => { - return { - wow: true, - } - }, + queryFn: () => sleep(0).then(() => 'Some data'), })) - expectTypeOf(data).toEqualTypeOf>() + expectTypeOf(query.data).toEqualTypeOf>() }) - it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { - const { data } = injectQuery(() => ({ + test('data should be defined when query is success', () => { + const query = injectQuery(() => ({ queryKey: ['key'], - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => undefined as { wow: boolean } | undefined, + queryFn: () => sleep(0).then(() => 'Some data'), })) - expectTypeOf(data).toEqualTypeOf>() + if (query.isSuccess()) { + expectTypeOf(query.data).toEqualTypeOf>() + } }) - it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => { + test('error should be null when query is success', () => { const query = injectQuery(() => ({ queryKey: ['key'], - queryFn: () => { - return { - wow: true, - } - }, - initialData: () => undefined as { wow: boolean } | undefined, + queryFn: () => sleep(0).then(() => 'Some data'), })) if (query.isSuccess()) { - expectTypeOf(query.data).toEqualTypeOf>() + expectTypeOf(query.error).toEqualTypeOf>() } }) - }) - describe('structuralSharing', () => { - it('should be able to use structuralSharing with unknown types', () => { - // https://github.com/TanStack/query/issues/6525#issuecomment-1938411343 - injectQuery(() => ({ + test('data should be undefined when query is pending', () => { + const query = injectQuery(() => ({ queryKey: ['key'], - queryFn: () => 5, - structuralSharing: (oldData, newData) => { - expectTypeOf(oldData).toBeUnknown() - expectTypeOf(newData).toBeUnknown() - return newData - }, + queryFn: () => sleep(0).then(() => 'Some data'), })) - }) - }) -}) - -describe('Discriminated union return type', () => { - test('data should be possibly undefined by default', () => { - const query = injectQuery(() => ({ - queryKey: ['key'], - queryFn: () => sleep(0).then(() => 'Some data'), - })) - - expectTypeOf(query.data).toEqualTypeOf>() - }) - - test('data should be defined when query is success', () => { - const query = injectQuery(() => ({ - queryKey: ['key'], - queryFn: () => sleep(0).then(() => 'Some data'), - })) - - if (query.isSuccess()) { - expectTypeOf(query.data).toEqualTypeOf>() - } - }) - - test('error should be null when query is success', () => { - const query = injectQuery(() => ({ - queryKey: ['key'], - queryFn: () => sleep(0).then(() => 'Some data'), - })) - - if (query.isSuccess()) { - expectTypeOf(query.error).toEqualTypeOf>() - } - }) - - test('data should be undefined when query is pending', () => { - const query = injectQuery(() => ({ - queryKey: ['key'], - queryFn: () => sleep(0).then(() => 'Some data'), - })) - if (query.isPending()) { - expectTypeOf(query.data).toEqualTypeOf>() - } - }) + if (query.isPending()) { + expectTypeOf(query.data).toEqualTypeOf>() + } + }) - test('error should be defined when query is error', () => { - const query = injectQuery(() => ({ - queryKey: ['key'], - queryFn: () => sleep(0).then(() => 'Some data'), - })) + test('error should be defined when query is error', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => sleep(0).then(() => 'Some data'), + })) - if (query.isError()) { - expectTypeOf(query.error).toEqualTypeOf>() - } + if (query.isError()) { + expectTypeOf(query.error).toEqualTypeOf>() + } + }) }) })