|  | 
|  | 1 | +import { describe, expectTypeOf, it } from 'vitest' | 
|  | 2 | +import { skipToken } from '..' | 
|  | 3 | +import { injectQueries } from '../inject-queries' | 
|  | 4 | +import { queryOptions } from '../query-options' | 
|  | 5 | +import type { CreateQueryOptions, CreateQueryResult, OmitKeyof } from '..' | 
|  | 6 | +import type { Signal } from '@angular/core' | 
|  | 7 | + | 
|  | 8 | +describe('InjectQueries config object overload', () => { | 
|  | 9 | +  it('TData should always be defined when initialData is provided as an object', () => { | 
|  | 10 | +    const query1 = { | 
|  | 11 | +      queryKey: ['key1'], | 
|  | 12 | +      queryFn: () => { | 
|  | 13 | +        return { | 
|  | 14 | +          wow: true, | 
|  | 15 | +        } | 
|  | 16 | +      }, | 
|  | 17 | +      initialData: { | 
|  | 18 | +        wow: false, | 
|  | 19 | +      }, | 
|  | 20 | +    } | 
|  | 21 | + | 
|  | 22 | +    const query2 = { | 
|  | 23 | +      queryKey: ['key2'], | 
|  | 24 | +      queryFn: () => 'Query Data', | 
|  | 25 | +      initialData: 'initial data', | 
|  | 26 | +    } | 
|  | 27 | + | 
|  | 28 | +    const query3 = { | 
|  | 29 | +      queryKey: ['key2'], | 
|  | 30 | +      queryFn: () => 'Query Data', | 
|  | 31 | +    } | 
|  | 32 | + | 
|  | 33 | +    const queryResults = injectQueries(() => ({ | 
|  | 34 | +      queries: [query1, query2, query3], | 
|  | 35 | +    })) | 
|  | 36 | + | 
|  | 37 | +    const query1Data = queryResults()[0].data() | 
|  | 38 | +    const query2Data = queryResults()[1].data() | 
|  | 39 | +    const query3Data = queryResults()[2].data() | 
|  | 40 | + | 
|  | 41 | +    expectTypeOf(query1Data).toEqualTypeOf<{ wow: boolean }>() | 
|  | 42 | +    expectTypeOf(query2Data).toEqualTypeOf<string>() | 
|  | 43 | +    expectTypeOf(query3Data).toEqualTypeOf<string | undefined>() | 
|  | 44 | +  }) | 
|  | 45 | + | 
|  | 46 | +  it('TData should be defined when passed through queryOptions', () => { | 
|  | 47 | +    const options = queryOptions({ | 
|  | 48 | +      queryKey: ['key'], | 
|  | 49 | +      queryFn: () => { | 
|  | 50 | +        return { | 
|  | 51 | +          wow: true, | 
|  | 52 | +        } | 
|  | 53 | +      }, | 
|  | 54 | +      initialData: { | 
|  | 55 | +        wow: true, | 
|  | 56 | +      }, | 
|  | 57 | +    }) | 
|  | 58 | +    const queryResults = injectQueries(() => ({ queries: [options] })) | 
|  | 59 | + | 
|  | 60 | +    const data = queryResults()[0].data() | 
|  | 61 | + | 
|  | 62 | +    expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>() | 
|  | 63 | +  }) | 
|  | 64 | + | 
|  | 65 | +  it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into injectQuery', () => { | 
|  | 66 | +    const query1 = queryOptions({ | 
|  | 67 | +      queryKey: ['key'], | 
|  | 68 | +      queryFn: () => Promise.resolve(1), | 
|  | 69 | +      select: (data) => data > 1, | 
|  | 70 | +    }) | 
|  | 71 | + | 
|  | 72 | +    const query2 = { | 
|  | 73 | +      queryKey: ['key'], | 
|  | 74 | +      queryFn: () => Promise.resolve(1), | 
|  | 75 | +      select: (data: number) => data > 1, | 
|  | 76 | +    } | 
|  | 77 | + | 
|  | 78 | +    const queryResults = injectQueries(() => ({ queries: [query1, query2] })) | 
|  | 79 | +    const query1Data = queryResults()[0].data() | 
|  | 80 | +    const query2Data = queryResults()[1].data() | 
|  | 81 | + | 
|  | 82 | +    expectTypeOf(query1Data).toEqualTypeOf<boolean | undefined>() | 
|  | 83 | +    expectTypeOf(query2Data).toEqualTypeOf<boolean | undefined>() | 
|  | 84 | +  }) | 
|  | 85 | + | 
|  | 86 | +  it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => { | 
|  | 87 | +    const queryResults = injectQueries(() => ({ | 
|  | 88 | +      queries: [ | 
|  | 89 | +        { | 
|  | 90 | +          queryKey: ['key'], | 
|  | 91 | +          queryFn: () => { | 
|  | 92 | +            return { | 
|  | 93 | +              wow: true, | 
|  | 94 | +            } | 
|  | 95 | +          }, | 
|  | 96 | +          initialData: () => undefined as { wow: boolean } | undefined, | 
|  | 97 | +        }, | 
|  | 98 | +      ], | 
|  | 99 | +    })) | 
|  | 100 | + | 
|  | 101 | +    const data = queryResults()[0].data() | 
|  | 102 | + | 
|  | 103 | +    expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>() | 
|  | 104 | +  }) | 
|  | 105 | + | 
|  | 106 | +  describe('custom injectable', () => { | 
|  | 107 | +    it('should allow custom hooks using UseQueryOptions', () => { | 
|  | 108 | +      type Data = string | 
|  | 109 | + | 
|  | 110 | +      const injectCustomQueries = ( | 
|  | 111 | +        options?: OmitKeyof<CreateQueryOptions<Data>, 'queryKey' | 'queryFn'>, | 
|  | 112 | +      ) => { | 
|  | 113 | +        return injectQueries(() => ({ | 
|  | 114 | +          queries: [ | 
|  | 115 | +            { | 
|  | 116 | +              ...options, | 
|  | 117 | +              queryKey: ['todos-key'], | 
|  | 118 | +              queryFn: () => Promise.resolve('data'), | 
|  | 119 | +            }, | 
|  | 120 | +          ], | 
|  | 121 | +        })) | 
|  | 122 | +      } | 
|  | 123 | + | 
|  | 124 | +      const queryResults = injectCustomQueries() | 
|  | 125 | +      const data = queryResults()[0].data() | 
|  | 126 | + | 
|  | 127 | +      expectTypeOf(data).toEqualTypeOf<Data | undefined>() | 
|  | 128 | +    }) | 
|  | 129 | +  }) | 
|  | 130 | + | 
|  | 131 | +  it('TData should have correct type when conditional skipToken is passed', () => { | 
|  | 132 | +    const queryResults = injectQueries(() => ({ | 
|  | 133 | +      queries: [ | 
|  | 134 | +        { | 
|  | 135 | +          queryKey: ['withSkipToken'], | 
|  | 136 | +          queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5), | 
|  | 137 | +        }, | 
|  | 138 | +      ], | 
|  | 139 | +    })) | 
|  | 140 | + | 
|  | 141 | +    const firstResult = queryResults()[0] | 
|  | 142 | + | 
|  | 143 | +    expectTypeOf(firstResult).toEqualTypeOf<CreateQueryResult<number, Error>>() | 
|  | 144 | +    expectTypeOf(firstResult.data()).toEqualTypeOf<number | undefined>() | 
|  | 145 | +  }) | 
|  | 146 | + | 
|  | 147 | +  it('should return correct data for dynamic queries with mixed result types', () => { | 
|  | 148 | +    const Queries1 = { | 
|  | 149 | +      get: () => | 
|  | 150 | +        queryOptions({ | 
|  | 151 | +          queryKey: ['key1'], | 
|  | 152 | +          queryFn: () => Promise.resolve(1), | 
|  | 153 | +        }), | 
|  | 154 | +    } | 
|  | 155 | +    const Queries2 = { | 
|  | 156 | +      get: () => | 
|  | 157 | +        queryOptions({ | 
|  | 158 | +          queryKey: ['key2'], | 
|  | 159 | +          queryFn: () => Promise.resolve(true), | 
|  | 160 | +        }), | 
|  | 161 | +    } | 
|  | 162 | + | 
|  | 163 | +    const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() })) | 
|  | 164 | +    const result = injectQueries(() => ({ | 
|  | 165 | +      queries: [...queries1List, { ...Queries2.get() }], | 
|  | 166 | +    })) | 
|  | 167 | + | 
|  | 168 | +    expectTypeOf(result).branded.toEqualTypeOf< | 
|  | 169 | +      Signal< | 
|  | 170 | +        [ | 
|  | 171 | +          ...Array<CreateQueryResult<number, Error>>, | 
|  | 172 | +          CreateQueryResult<boolean, Error>, | 
|  | 173 | +        ] | 
|  | 174 | +      > | 
|  | 175 | +    >() | 
|  | 176 | +  }) | 
|  | 177 | +}) | 
0 commit comments