@tanstack/angular-query-experimental 5.103.1 → 5.103.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/dist/create-base-query.d.mts +169 -0
  2. package/dist/create-base-query.d.mts.map +1 -0
  3. package/dist/create-base-query.mjs +91 -0
  4. package/dist/create-base-query.mjs.map +1 -0
  5. package/dist/devtools/index.d.mts +3 -0
  6. package/dist/devtools/index.mjs +2 -0
  7. package/dist/devtools/production/index.d.mts +4 -0
  8. package/dist/devtools/production/index.mjs +2 -0
  9. package/dist/devtools/stub.d.mts +6 -0
  10. package/dist/devtools/stub.d.mts.map +1 -0
  11. package/dist/devtools/stub.mjs +9 -0
  12. package/dist/devtools/stub.mjs.map +1 -0
  13. package/dist/devtools/types.d.mts +107 -0
  14. package/dist/devtools/types.d.mts.map +1 -0
  15. package/dist/devtools/types.mjs +1 -0
  16. package/{devtools/with-devtools.d.ts → dist/devtools/with-devtools.d.mts} +6 -2
  17. package/dist/devtools/with-devtools.d.mts.map +1 -0
  18. package/dist/devtools/with-devtools.mjs +110 -0
  19. package/dist/devtools/with-devtools.mjs.map +1 -0
  20. package/dist/devtools-panel/index.d.mts +3 -0
  21. package/dist/devtools-panel/index.mjs +2 -0
  22. package/{devtools-panel/inject-devtools-panel.d.ts → dist/devtools-panel/inject-devtools-panel.d.mts} +6 -2
  23. package/dist/devtools-panel/inject-devtools-panel.d.mts.map +1 -0
  24. package/dist/devtools-panel/inject-devtools-panel.mjs +67 -0
  25. package/dist/devtools-panel/inject-devtools-panel.mjs.map +1 -0
  26. package/dist/devtools-panel/production/index.d.mts +4 -0
  27. package/dist/devtools-panel/production/index.mjs +2 -0
  28. package/dist/devtools-panel/stub.d.mts +6 -0
  29. package/dist/devtools-panel/stub.d.mts.map +1 -0
  30. package/dist/devtools-panel/stub.mjs +7 -0
  31. package/dist/devtools-panel/stub.mjs.map +1 -0
  32. package/dist/devtools-panel/types.d.mts +52 -0
  33. package/dist/devtools-panel/types.d.mts.map +1 -0
  34. package/dist/devtools-panel/types.mjs +1 -0
  35. package/dist/index.d.mts +16 -0
  36. package/{index.mjs → dist/index.mjs} +8 -21
  37. package/dist/index.mjs.map +1 -0
  38. package/{infinite-query-options.d.ts → dist/infinite-query-options.d.mts} +35 -31
  39. package/dist/infinite-query-options.d.mts.map +1 -0
  40. package/dist/infinite-query-options.mjs +8 -0
  41. package/dist/infinite-query-options.mjs.map +1 -0
  42. package/{inject-infinite-query.d.ts → dist/inject-infinite-query.d.mts} +18 -14
  43. package/dist/inject-infinite-query.d.mts.map +1 -0
  44. package/dist/inject-infinite-query.mjs +13 -0
  45. package/dist/inject-infinite-query.mjs.map +1 -0
  46. package/{inject-is-fetching.d.ts → dist/inject-is-fetching.d.mts} +14 -10
  47. package/dist/inject-is-fetching.d.mts.map +1 -0
  48. package/dist/inject-is-fetching.mjs +69 -0
  49. package/dist/inject-is-fetching.mjs.map +1 -0
  50. package/{inject-is-mutating.d.ts → dist/inject-is-mutating.d.mts} +14 -10
  51. package/dist/inject-is-mutating.d.mts.map +1 -0
  52. package/dist/inject-is-mutating.mjs +52 -0
  53. package/dist/inject-is-mutating.mjs.map +1 -0
  54. package/{inject-is-restoring.d.ts → dist/inject-is-restoring.d.mts} +13 -10
  55. package/dist/inject-is-restoring.d.mts.map +1 -0
  56. package/dist/inject-is-restoring.mjs +35 -0
  57. package/dist/inject-is-restoring.mjs.map +1 -0
  58. package/{inject-mutation-state.d.ts → dist/inject-mutation-state.d.mts} +16 -13
  59. package/dist/inject-mutation-state.d.mts.map +1 -0
  60. package/dist/inject-mutation-state.mjs +103 -0
  61. package/dist/inject-mutation-state.mjs.map +1 -0
  62. package/{inject-mutation.d.ts → dist/inject-mutation.d.mts} +15 -11
  63. package/dist/inject-mutation.d.mts.map +1 -0
  64. package/dist/inject-mutation.mjs +226 -0
  65. package/dist/inject-mutation.mjs.map +1 -0
  66. package/dist/inject-queries-experimental/index.d.mts +2 -0
  67. package/dist/inject-queries-experimental/index.mjs +2 -0
  68. package/{inject-queries.d.ts → dist/inject-queries.d.mts} +36 -55
  69. package/dist/inject-queries.d.mts.map +1 -0
  70. package/dist/inject-queries.mjs +203 -0
  71. package/dist/inject-queries.mjs.map +1 -0
  72. package/{inject-query-client.d.ts → dist/inject-query-client.d.mts} +8 -4
  73. package/dist/inject-query-client.d.mts.map +1 -0
  74. package/dist/inject-query-client.mjs +23 -0
  75. package/dist/inject-query-client.mjs.map +1 -0
  76. package/{inject-query.d.ts → dist/inject-query.d.mts} +18 -14
  77. package/dist/inject-query.d.mts.map +1 -0
  78. package/dist/inject-query.mjs +12 -0
  79. package/dist/inject-query.mjs.map +1 -0
  80. package/{mutation-options.d.ts → dist/mutation-options.d.mts} +8 -4
  81. package/dist/mutation-options.d.mts.map +1 -0
  82. package/dist/mutation-options.mjs +8 -0
  83. package/dist/mutation-options.mjs.map +1 -0
  84. package/dist/pending-tasks-compat.d.mts +10 -0
  85. package/dist/pending-tasks-compat.d.mts.map +1 -0
  86. package/dist/pending-tasks-compat.mjs +13 -0
  87. package/dist/pending-tasks-compat.mjs.map +1 -0
  88. package/{providers.d.ts → dist/providers.d.mts} +16 -13
  89. package/dist/providers.d.mts.map +1 -0
  90. package/dist/providers.mjs +124 -0
  91. package/dist/providers.mjs.map +1 -0
  92. package/{query-options.d.ts → dist/query-options.d.mts} +41 -37
  93. package/dist/query-options.d.mts.map +1 -0
  94. package/dist/query-options.mjs +8 -0
  95. package/dist/query-options.mjs.map +1 -0
  96. package/dist/signal-proxy.d.mts +13 -0
  97. package/dist/signal-proxy.d.mts.map +1 -0
  98. package/dist/signal-proxy.mjs +35 -0
  99. package/dist/signal-proxy.mjs.map +1 -0
  100. package/{types.d.ts → dist/types.d.mts} +36 -37
  101. package/dist/types.d.mts.map +1 -0
  102. package/dist/types.mjs +6 -0
  103. package/dist/types.mjs.map +1 -0
  104. package/package.json +48 -20
  105. package/src/__tests__/infinite-query-options.test-d.ts +314 -0
  106. package/src/__tests__/infinite-query-options.test.ts +19 -0
  107. package/src/__tests__/inject-devtools-panel.test.ts +196 -0
  108. package/src/__tests__/inject-infinite-query.test-d.ts +66 -0
  109. package/src/__tests__/inject-infinite-query.test.ts +227 -0
  110. package/src/__tests__/inject-is-fetching.test.ts +108 -0
  111. package/src/__tests__/inject-is-mutating.test.ts +113 -0
  112. package/src/__tests__/inject-is-restoring.test.ts +93 -0
  113. package/src/__tests__/inject-mutation-state.test-d.ts +22 -0
  114. package/src/__tests__/inject-mutation-state.test.ts +198 -0
  115. package/src/__tests__/inject-mutation.test-d.ts +158 -0
  116. package/src/__tests__/inject-mutation.test.ts +1161 -0
  117. package/src/__tests__/inject-queries.test-d.ts +196 -0
  118. package/src/__tests__/inject-queries.test.ts +240 -0
  119. package/src/__tests__/inject-query.test-d.ts +357 -0
  120. package/src/__tests__/inject-query.test.ts +700 -0
  121. package/src/__tests__/mutation-options.test-d.ts +234 -0
  122. package/src/__tests__/mutation-options.test.ts +344 -0
  123. package/src/__tests__/pending-tasks.test.ts +644 -0
  124. package/src/__tests__/provide-query-client.test.ts +38 -0
  125. package/src/__tests__/provide-tanstack-query.test.ts +38 -0
  126. package/src/__tests__/query-options.test-d.ts +262 -0
  127. package/src/__tests__/query-options.test.ts +14 -0
  128. package/src/__tests__/signal-proxy.test.ts +27 -0
  129. package/src/__tests__/test-utils.ts +77 -0
  130. package/src/__tests__/with-devtools.test.ts +674 -0
  131. package/src/create-base-query.ts +175 -0
  132. package/src/devtools/index.ts +8 -0
  133. package/src/devtools/production/index.ts +1 -0
  134. package/src/devtools/stub.ts +7 -0
  135. package/src/devtools/types.ts +116 -0
  136. package/src/devtools/with-devtools.ts +182 -0
  137. package/src/devtools-panel/index.ts +8 -0
  138. package/src/devtools-panel/inject-devtools-panel.ts +110 -0
  139. package/src/devtools-panel/production/index.ts +1 -0
  140. package/src/devtools-panel/stub.ts +7 -0
  141. package/src/devtools-panel/types.ts +57 -0
  142. package/src/index.ts +60 -0
  143. package/src/infinite-query-options.ts +354 -0
  144. package/src/inject-infinite-query.ts +296 -0
  145. package/src/inject-is-fetching.ts +97 -0
  146. package/src/inject-is-mutating.ts +80 -0
  147. package/src/inject-is-restoring.ts +53 -0
  148. package/src/inject-mutation-state.ts +167 -0
  149. package/src/inject-mutation.ts +328 -0
  150. package/src/inject-queries-experimental/index.ts +1 -0
  151. package/src/inject-queries.ts +479 -0
  152. package/src/inject-query-client.ts +22 -0
  153. package/src/inject-query.ts +208 -0
  154. package/src/mutation-options.ts +121 -0
  155. package/src/pending-tasks-compat.ts +27 -0
  156. package/src/providers.ts +170 -0
  157. package/src/query-options.ts +292 -0
  158. package/src/signal-proxy.ts +46 -0
  159. package/src/types.ts +429 -0
  160. package/create-base-query.d.ts +0 -164
  161. package/create-base-query.mjs +0 -99
  162. package/create-base-query.mjs.map +0 -1
  163. package/devtools/index.d.ts +0 -2
  164. package/devtools/index.mjs +0 -5
  165. package/devtools/index.mjs.map +0 -1
  166. package/devtools/production/index.d.ts +0 -1
  167. package/devtools/stub.d.ts +0 -2
  168. package/devtools/stub.mjs +0 -8
  169. package/devtools/stub.mjs.map +0 -1
  170. package/devtools/types.d.ts +0 -100
  171. package/devtools/with-devtools.mjs +0 -106
  172. package/devtools/with-devtools.mjs.map +0 -1
  173. package/devtools-panel/index.d.ts +0 -2
  174. package/devtools-panel/index.mjs +0 -5
  175. package/devtools-panel/index.mjs.map +0 -1
  176. package/devtools-panel/inject-devtools-panel.mjs +0 -72
  177. package/devtools-panel/inject-devtools-panel.mjs.map +0 -1
  178. package/devtools-panel/production/index.d.ts +0 -1
  179. package/devtools-panel/stub.d.ts +0 -2
  180. package/devtools-panel/stub.mjs +0 -8
  181. package/devtools-panel/stub.mjs.map +0 -1
  182. package/devtools-panel/types.d.ts +0 -48
  183. package/index.d.ts +0 -25
  184. package/index.mjs.map +0 -1
  185. package/infinite-query-options.mjs +0 -7
  186. package/infinite-query-options.mjs.map +0 -1
  187. package/inject-infinite-query.mjs +0 -18
  188. package/inject-infinite-query.mjs.map +0 -1
  189. package/inject-is-fetching.mjs +0 -31
  190. package/inject-is-fetching.mjs.map +0 -1
  191. package/inject-is-mutating.mjs +0 -31
  192. package/inject-is-mutating.mjs.map +0 -1
  193. package/inject-is-restoring.mjs +0 -21
  194. package/inject-is-restoring.mjs.map +0 -1
  195. package/inject-mutation-state.mjs +0 -51
  196. package/inject-mutation-state.mjs.map +0 -1
  197. package/inject-mutation.mjs +0 -94
  198. package/inject-mutation.mjs.map +0 -1
  199. package/inject-queries-experimental/index.d.ts +0 -1
  200. package/inject-queries-experimental/index.mjs +0 -5
  201. package/inject-queries-experimental/index.mjs.map +0 -1
  202. package/inject-queries.mjs +0 -82
  203. package/inject-queries.mjs.map +0 -1
  204. package/inject-query-client.mjs +0 -9
  205. package/inject-query-client.mjs.map +0 -1
  206. package/inject-query.mjs +0 -14
  207. package/inject-query.mjs.map +0 -1
  208. package/mutation-options.mjs +0 -7
  209. package/mutation-options.mjs.map +0 -1
  210. package/pending-tasks-compat.d.ts +0 -7
  211. package/pending-tasks-compat.mjs +0 -19
  212. package/pending-tasks-compat.mjs.map +0 -1
  213. package/providers.mjs +0 -32
  214. package/providers.mjs.map +0 -1
  215. package/query-options.mjs +0 -7
  216. package/query-options.mjs.map +0 -1
  217. package/signal-proxy.d.ts +0 -11
  218. package/signal-proxy.mjs +0 -29
  219. package/signal-proxy.mjs.map +0 -1
@@ -0,0 +1,38 @@
1
+ import { TestBed } from '@angular/core/testing'
2
+ import { describe, expect, it } from 'vitest'
3
+ import { InjectionToken, provideZonelessChangeDetection } from '@angular/core'
4
+ import { QueryClient } from '@tanstack/query-core'
5
+ import { provideTanStackQuery } from '../providers'
6
+
7
+ describe('provideTanStackQuery', () => {
8
+ it('should provide a QueryClient instance directly', () => {
9
+ const queryClient = new QueryClient()
10
+
11
+ TestBed.configureTestingModule({
12
+ providers: [
13
+ provideZonelessChangeDetection(),
14
+ provideTanStackQuery(queryClient),
15
+ ],
16
+ })
17
+
18
+ const providedQueryClient = TestBed.inject(QueryClient)
19
+ expect(providedQueryClient).toBe(queryClient)
20
+ })
21
+
22
+ it('should provide a QueryClient instance using an InjectionToken', () => {
23
+ const queryClient = new QueryClient()
24
+ const CUSTOM_QUERY_CLIENT = new InjectionToken<QueryClient>('', {
25
+ factory: () => queryClient,
26
+ })
27
+
28
+ TestBed.configureTestingModule({
29
+ providers: [
30
+ provideZonelessChangeDetection(),
31
+ provideTanStackQuery(CUSTOM_QUERY_CLIENT),
32
+ ],
33
+ })
34
+
35
+ const providedQueryClient = TestBed.inject(QueryClient)
36
+ expect(providedQueryClient).toBe(queryClient)
37
+ })
38
+ })
@@ -0,0 +1,262 @@
1
+ import { assertType, describe, expectTypeOf, it } from 'vitest'
2
+ import { queryKey } from '@tanstack/query-test-utils'
3
+ import {
4
+ QueryClient,
5
+ dataTagSymbol,
6
+ injectQuery,
7
+ queryOptions,
8
+ skipToken,
9
+ } from '..'
10
+ import type { Signal } from '@angular/core'
11
+ import type { InitialDataFunction } from '@tanstack/query-core'
12
+
13
+ // Regression test for exported queryOptions inference under declaration emit.
14
+ // TypeScript should be able to name the return type without expanding the
15
+ // internal data tag symbols into the consumer's .d.ts output.
16
+ export const exportedQueryOptions = queryOptions({
17
+ queryKey: ['invalid'],
18
+ })
19
+
20
+ describe('queryOptions', () => {
21
+ it('should not allow excess properties', () => {
22
+ expectTypeOf(queryOptions).parameter(0).not.toHaveProperty('stallTime')
23
+ })
24
+
25
+ it('should infer types for callbacks', () => {
26
+ const key = queryKey()
27
+ queryOptions({
28
+ queryKey: key,
29
+ queryFn: () => Promise.resolve(5),
30
+ staleTime: 1000,
31
+ select: (data) => {
32
+ expectTypeOf(data).toEqualTypeOf<number>()
33
+ },
34
+ })
35
+ })
36
+
37
+ it('should allow undefined response in initialData', () => {
38
+ const key = queryKey()
39
+ const options = (id: string | null) =>
40
+ queryOptions({
41
+ queryKey: [...key, id],
42
+ queryFn: () =>
43
+ Promise.resolve({
44
+ id: '1',
45
+ title: 'Do Laundry',
46
+ }),
47
+ initialData: () =>
48
+ !id
49
+ ? undefined
50
+ : {
51
+ id,
52
+ title: 'Initial Data',
53
+ },
54
+ })
55
+
56
+ expectTypeOf(options(null).initialData).returns.toEqualTypeOf<
57
+ { id: string; title: string } | undefined
58
+ >()
59
+ })
60
+
61
+ it('should allow optional initialData object', () => {
62
+ const options = queryOptions({
63
+ queryKey: queryKey(),
64
+ queryFn: () => Promise.resolve('something string'),
65
+ initialData: Math.random() > 0.5 ? 'initial string' : undefined,
66
+ })
67
+
68
+ expectTypeOf(options.initialData).toExtend<
69
+ InitialDataFunction<string> | string | undefined
70
+ >()
71
+ })
72
+ })
73
+
74
+ it('should work when passed to injectQuery', () => {
75
+ const key = queryKey()
76
+ const options = queryOptions({
77
+ queryKey: key,
78
+ queryFn: () => Promise.resolve(5),
79
+ })
80
+
81
+ const { data } = injectQuery(() => options)
82
+ expectTypeOf(data).toEqualTypeOf<Signal<number | undefined>>()
83
+ })
84
+
85
+ it('should work when passed to fetchQuery', () => {
86
+ const key = queryKey()
87
+ const options = queryOptions({
88
+ queryKey: key,
89
+ queryFn: () => Promise.resolve(5),
90
+ })
91
+
92
+ // eslint-disable-next-line no-restricted-syntax -- grandfathered direct test
93
+ const data = new QueryClient().fetchQuery(options)
94
+ assertType<Promise<number>>(data)
95
+ })
96
+
97
+ it('should work when passed to query', () => {
98
+ const options = queryOptions({
99
+ queryKey: ['key'],
100
+ queryFn: () => Promise.resolve(5),
101
+ })
102
+
103
+ const data = new QueryClient().query(options)
104
+ assertType<Promise<number>>(data)
105
+ })
106
+
107
+ it('should work when passed to query with select', () => {
108
+ const options = queryOptions({
109
+ queryKey: ['key'],
110
+ queryFn: () => Promise.resolve(5),
111
+ select: (data) => data.toString(),
112
+ })
113
+
114
+ const data = new QueryClient().query(options)
115
+ assertType<Promise<string>>(data)
116
+ })
117
+
118
+ it('should work when passed to query with enabled: false', () => {
119
+ const options = queryOptions({
120
+ queryKey: ['key'],
121
+ queryFn: () => Promise.resolve(5),
122
+ enabled: false,
123
+ })
124
+
125
+ const data = new QueryClient().query(options)
126
+ assertType<Promise<number>>(data)
127
+ })
128
+
129
+ it('should work when passed to query with skipToken', () => {
130
+ const options = queryOptions({
131
+ queryKey: ['key'],
132
+ queryFn: skipToken,
133
+ })
134
+
135
+ const data = new QueryClient().query(options)
136
+ assertType<Promise<unknown>>(data)
137
+ })
138
+
139
+ it('should tag the queryKey with the result type of the QueryFn', () => {
140
+ const key = queryKey()
141
+ const { queryKey: tagged } = queryOptions({
142
+ queryKey: key,
143
+ queryFn: () => Promise.resolve(5),
144
+ })
145
+ assertType<number>(tagged[dataTagSymbol])
146
+ })
147
+
148
+ it('should tag the queryKey even if no promise is returned', () => {
149
+ const key = queryKey()
150
+ const { queryKey: tagged } = queryOptions({
151
+ queryKey: key,
152
+ queryFn: () => 5,
153
+ })
154
+ assertType<number>(tagged[dataTagSymbol])
155
+ })
156
+
157
+ it('should tag the queryKey with unknown if there is no queryFn', () => {
158
+ const key = queryKey()
159
+ const { queryKey: tagged } = queryOptions({
160
+ queryKey: key,
161
+ })
162
+
163
+ assertType<unknown>(tagged[dataTagSymbol])
164
+ })
165
+
166
+ it('should tag the queryKey with the result type of the QueryFn if select is used', () => {
167
+ const key = queryKey()
168
+ const { queryKey: tagged } = queryOptions({
169
+ queryKey: key,
170
+ queryFn: () => Promise.resolve(5),
171
+ select: (data) => data.toString(),
172
+ })
173
+
174
+ assertType<number>(tagged[dataTagSymbol])
175
+ })
176
+
177
+ it('should return the proper type when passed to getQueryData', () => {
178
+ const key = queryKey()
179
+ const { queryKey: tagged } = queryOptions({
180
+ queryKey: key,
181
+ queryFn: () => Promise.resolve(5),
182
+ })
183
+
184
+ const queryClient = new QueryClient()
185
+ const data = queryClient.getQueryData(tagged)
186
+
187
+ expectTypeOf(data).toEqualTypeOf<number | undefined>()
188
+ })
189
+
190
+ it('should return the proper type when passed to getQueryState', () => {
191
+ const key = queryKey()
192
+ const { queryKey: tagged } = queryOptions({
193
+ queryKey: key,
194
+ queryFn: () => Promise.resolve(5),
195
+ })
196
+
197
+ const queryClient = new QueryClient()
198
+ const state = queryClient.getQueryState(tagged)
199
+
200
+ expectTypeOf(state?.data).toEqualTypeOf<number | undefined>()
201
+ })
202
+
203
+ it('should properly type updaterFn when passed to setQueryData', () => {
204
+ const key = queryKey()
205
+ const { queryKey: tagged } = queryOptions({
206
+ queryKey: key,
207
+ queryFn: () => Promise.resolve(5),
208
+ })
209
+
210
+ const queryClient = new QueryClient()
211
+ const data = queryClient.setQueryData(tagged, (prev) => {
212
+ expectTypeOf(prev).toEqualTypeOf<number | undefined>()
213
+ return prev
214
+ })
215
+
216
+ expectTypeOf(data).toEqualTypeOf<number | undefined>()
217
+ })
218
+
219
+ it('should properly type value when passed to setQueryData', () => {
220
+ const key = queryKey()
221
+ const { queryKey: tagged } = queryOptions({
222
+ queryKey: key,
223
+ queryFn: () => Promise.resolve(5),
224
+ })
225
+
226
+ const queryClient = new QueryClient()
227
+
228
+ // @ts-expect-error value should be a number
229
+ queryClient.setQueryData(tagged, '5')
230
+ // @ts-expect-error value should be a number
231
+ queryClient.setQueryData(tagged, () => '5')
232
+
233
+ const data = queryClient.setQueryData(tagged, 5)
234
+
235
+ expectTypeOf(data).toEqualTypeOf<number | undefined>()
236
+ })
237
+
238
+ it('should infer even if there is a conditional skipToken', () => {
239
+ const key = queryKey()
240
+ const options = queryOptions({
241
+ queryKey: key,
242
+ queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),
243
+ })
244
+
245
+ const queryClient = new QueryClient()
246
+ const data = queryClient.getQueryData(options.queryKey)
247
+
248
+ expectTypeOf(data).toEqualTypeOf<number | undefined>()
249
+ })
250
+
251
+ it('should infer to unknown if we disable a query with just a skipToken', () => {
252
+ const key = queryKey()
253
+ const options = queryOptions({
254
+ queryKey: key,
255
+ queryFn: skipToken,
256
+ })
257
+
258
+ const queryClient = new QueryClient()
259
+ const data = queryClient.getQueryData(options.queryKey)
260
+
261
+ expectTypeOf(data).toEqualTypeOf<unknown>()
262
+ })
@@ -0,0 +1,14 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { queryOptions } from '../query-options'
3
+ import type { CreateQueryOptions } from '../types'
4
+
5
+ describe('queryOptions', () => {
6
+ it('should return the object received as a parameter without any modification.', () => {
7
+ const object: CreateQueryOptions = {
8
+ queryKey: ['key'],
9
+ queryFn: () => Promise.resolve(5),
10
+ } as const
11
+
12
+ expect(queryOptions(object)).toBe(object)
13
+ })
14
+ })
@@ -0,0 +1,27 @@
1
+ import { isSignal, signal } from '@angular/core'
2
+ import { describe, expect, it } from 'vitest'
3
+ import { signalProxy } from '../signal-proxy'
4
+
5
+ describe('signalProxy', () => {
6
+ const inputSignal = signal({ fn: () => 'bar', baz: 'qux' })
7
+ const proxy = signalProxy(inputSignal)
8
+
9
+ it('should have computed fields', () => {
10
+ expect(proxy.baz()).toEqual('qux')
11
+ expect(isSignal(proxy.baz)).toBe(true)
12
+ })
13
+
14
+ it('should pass through functions as-is', () => {
15
+ expect(proxy.fn()).toEqual('bar')
16
+ expect(isSignal(proxy.fn)).toBe(false)
17
+ })
18
+
19
+ it('should support "in" operator', () => {
20
+ expect('baz' in proxy).toBe(true)
21
+ expect('foo' in proxy).toBe(false)
22
+ })
23
+
24
+ it('should support "Object.keys"', () => {
25
+ expect(Object.keys(proxy)).toEqual(['fn', 'baz'])
26
+ })
27
+ })
@@ -0,0 +1,77 @@
1
+ import { isSignal, untracked } from '@angular/core'
2
+ import { SIGNAL, signalSetFn } from '@angular/core/primitives/signals'
3
+ import { expect } from 'vitest'
4
+ import type { InputSignal, Signal } from '@angular/core'
5
+ import type { ComponentFixture } from '@angular/core/testing'
6
+
7
+ // Evaluate all signals on an object and return the result
8
+ function evaluateSignals<T extends Record<string, any>>(
9
+ obj: T,
10
+ ): { [K in keyof T]: ReturnType<T[K]> } {
11
+ const result: Partial<{ [K in keyof T]: ReturnType<T[K]> }> = {}
12
+
13
+ untracked(() => {
14
+ for (const key in obj) {
15
+ if (
16
+ Object.prototype.hasOwnProperty.call(obj, key) &&
17
+ // Only evaluate signals, not normal functions
18
+ isSignal(obj[key])
19
+ ) {
20
+ const func = obj[key]
21
+ result[key] = func()
22
+ }
23
+ }
24
+ })
25
+
26
+ return result as { [K in keyof T]: ReturnType<T[K]> }
27
+ }
28
+
29
+ export const expectSignals = <T extends Record<string, any>>(
30
+ obj: T,
31
+ expected: Partial<{
32
+ [K in keyof T]: T[K] extends Signal<any> ? ReturnType<T[K]> : never
33
+ }>,
34
+ ): void => {
35
+ expect(evaluateSignals(obj)).toMatchObject(expected)
36
+ }
37
+
38
+ type ToSignalInputUpdatableMap<T> = {
39
+ [
40
+ K in keyof T as T[K] extends InputSignal<any> ? K : never
41
+ ]: T[K] extends InputSignal<infer Value> ? Value : never
42
+ }
43
+
44
+ function componentHasSignalInputProperty<TProperty extends string>(
45
+ component: object,
46
+ property: TProperty,
47
+ ): component is { [key in TProperty]: InputSignal<unknown> } {
48
+ return (
49
+ component.hasOwnProperty(property) && (component as any)[property][SIGNAL]
50
+ )
51
+ }
52
+
53
+ /**
54
+ * Set required signal input value to component fixture
55
+ * @see https://github.com/angular/angular/issues/54013
56
+ */
57
+ export function setSignalInputs<T extends NonNullable<unknown>>(
58
+ component: T,
59
+ inputs: ToSignalInputUpdatableMap<T>,
60
+ ) {
61
+ for (const inputKey in inputs) {
62
+ if (componentHasSignalInputProperty(component, inputKey)) {
63
+ signalSetFn(component[inputKey][SIGNAL], inputs[inputKey])
64
+ }
65
+ }
66
+ }
67
+
68
+ export function setFixtureSignalInputs<T extends NonNullable<unknown>>(
69
+ componentFixture: ComponentFixture<T>,
70
+ inputs: ToSignalInputUpdatableMap<T>,
71
+ options: { detectChanges: boolean } = { detectChanges: true },
72
+ ) {
73
+ setSignalInputs(componentFixture.componentInstance, inputs)
74
+ if (options.detectChanges) {
75
+ componentFixture.detectChanges()
76
+ }
77
+ }