@pyreon/query 0.11.3 → 0.11.4
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/query",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.4",
|
|
4
4
|
"description": "Pyreon adapter for TanStack Query",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -44,13 +44,13 @@
|
|
|
44
44
|
"@tanstack/query-core": "^5.0.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@pyreon/core": "^0.11.
|
|
48
|
-
"@pyreon/reactivity": "^0.11.
|
|
47
|
+
"@pyreon/core": "^0.11.4",
|
|
48
|
+
"@pyreon/reactivity": "^0.11.4"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@happy-dom/global-registrator": "^20.8.3",
|
|
52
|
-
"@pyreon/core": "^0.11.
|
|
53
|
-
"@pyreon/reactivity": "^0.11.
|
|
54
|
-
"@pyreon/runtime-dom": "^0.11.
|
|
52
|
+
"@pyreon/core": "^0.11.4",
|
|
53
|
+
"@pyreon/reactivity": "^0.11.4",
|
|
54
|
+
"@pyreon/runtime-dom": "^0.11.4"
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import { mount } from "@pyreon/runtime-dom"
|
|
2
|
+
import { QueryClient } from "@tanstack/query-core"
|
|
3
|
+
import {
|
|
4
|
+
QueryClientProvider,
|
|
5
|
+
QuerySuspense,
|
|
6
|
+
useInfiniteQuery,
|
|
7
|
+
useIsFetching,
|
|
8
|
+
useIsMutating,
|
|
9
|
+
useMutation,
|
|
10
|
+
useQuery,
|
|
11
|
+
useQueryClient,
|
|
12
|
+
useSuspenseQuery,
|
|
13
|
+
} from "../index"
|
|
14
|
+
|
|
15
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
function makeClient() {
|
|
18
|
+
return new QueryClient({
|
|
19
|
+
defaultOptions: { queries: { retry: false, gcTime: Infinity } },
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function deferred<T>() {
|
|
24
|
+
let resolve!: (v: T) => void
|
|
25
|
+
let reject!: (e: unknown) => void
|
|
26
|
+
const promise = new Promise<T>((res, rej) => {
|
|
27
|
+
resolve = res
|
|
28
|
+
reject = rej
|
|
29
|
+
})
|
|
30
|
+
return { promise, resolve, reject }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ─── useInfiniteQuery — additional ───────────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
describe("useInfiniteQuery — additional", () => {
|
|
36
|
+
let client: QueryClient
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
client = makeClient()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it("isFetchingNextPage is true during fetchNextPage", async () => {
|
|
42
|
+
const { promise: pagePromise, resolve: resolveNextPage } = deferred<string>()
|
|
43
|
+
let callCount = 0
|
|
44
|
+
let query: ReturnType<typeof useInfiniteQuery<string>> | undefined
|
|
45
|
+
|
|
46
|
+
const el = document.createElement("div")
|
|
47
|
+
document.body.appendChild(el)
|
|
48
|
+
const unmount = mount(
|
|
49
|
+
<QueryClientProvider client={client}>
|
|
50
|
+
{() => {
|
|
51
|
+
query = useInfiniteQuery(() => ({
|
|
52
|
+
queryKey: ["inf-fetching-next"],
|
|
53
|
+
queryFn: ({ pageParam }: { pageParam: number }) => {
|
|
54
|
+
callCount++
|
|
55
|
+
if (callCount === 1) return Promise.resolve("page-0")
|
|
56
|
+
return pagePromise
|
|
57
|
+
},
|
|
58
|
+
initialPageParam: 0,
|
|
59
|
+
getNextPageParam: (_last: string, _all: string[], lastParam: number) =>
|
|
60
|
+
lastParam < 2 ? lastParam + 1 : undefined,
|
|
61
|
+
}))
|
|
62
|
+
return null
|
|
63
|
+
}}
|
|
64
|
+
</QueryClientProvider>,
|
|
65
|
+
el,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
// Wait for first page
|
|
69
|
+
await new Promise((r) => setTimeout(r, 20))
|
|
70
|
+
expect(query!.isSuccess()).toBe(true)
|
|
71
|
+
expect(query!.isFetchingNextPage()).toBe(false)
|
|
72
|
+
|
|
73
|
+
// Start fetching next page
|
|
74
|
+
const nextPromise = query!.fetchNextPage()
|
|
75
|
+
await new Promise((r) => setTimeout(r, 0))
|
|
76
|
+
expect(query!.isFetchingNextPage()).toBe(true)
|
|
77
|
+
expect(query!.isFetching()).toBe(true)
|
|
78
|
+
|
|
79
|
+
// Resolve and verify
|
|
80
|
+
resolveNextPage("page-1")
|
|
81
|
+
await nextPromise
|
|
82
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
83
|
+
expect(query!.isFetchingNextPage()).toBe(false)
|
|
84
|
+
expect(query!.data()?.pages).toEqual(["page-0", "page-1"])
|
|
85
|
+
|
|
86
|
+
unmount()
|
|
87
|
+
el.remove()
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it("hasNextPage is false when getNextPageParam returns undefined", async () => {
|
|
91
|
+
let query: ReturnType<typeof useInfiniteQuery<string>> | undefined
|
|
92
|
+
const el = document.createElement("div")
|
|
93
|
+
document.body.appendChild(el)
|
|
94
|
+
const unmount = mount(
|
|
95
|
+
<QueryClientProvider client={client}>
|
|
96
|
+
{() => {
|
|
97
|
+
query = useInfiniteQuery(() => ({
|
|
98
|
+
queryKey: ["inf-no-next"],
|
|
99
|
+
queryFn: () => Promise.resolve("only-page"),
|
|
100
|
+
initialPageParam: 0,
|
|
101
|
+
getNextPageParam: () => undefined, // No more pages
|
|
102
|
+
}))
|
|
103
|
+
return null
|
|
104
|
+
}}
|
|
105
|
+
</QueryClientProvider>,
|
|
106
|
+
el,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
await new Promise((r) => setTimeout(r, 20))
|
|
110
|
+
expect(query!.hasNextPage()).toBe(false)
|
|
111
|
+
expect(query!.data()?.pages).toEqual(["only-page"])
|
|
112
|
+
unmount()
|
|
113
|
+
el.remove()
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it("multiple fetchNextPage calls accumulate pages", async () => {
|
|
117
|
+
let query: ReturnType<typeof useInfiniteQuery<string>> | undefined
|
|
118
|
+
const el = document.createElement("div")
|
|
119
|
+
document.body.appendChild(el)
|
|
120
|
+
const unmount = mount(
|
|
121
|
+
<QueryClientProvider client={client}>
|
|
122
|
+
{() => {
|
|
123
|
+
query = useInfiniteQuery(() => ({
|
|
124
|
+
queryKey: ["inf-multi-fetch"],
|
|
125
|
+
queryFn: ({ pageParam }: { pageParam: number }) => Promise.resolve(`p${pageParam}`),
|
|
126
|
+
initialPageParam: 0,
|
|
127
|
+
getNextPageParam: (_last: string, _all: string[], lastParam: number) =>
|
|
128
|
+
lastParam < 4 ? lastParam + 1 : undefined,
|
|
129
|
+
}))
|
|
130
|
+
return null
|
|
131
|
+
}}
|
|
132
|
+
</QueryClientProvider>,
|
|
133
|
+
el,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
await new Promise((r) => setTimeout(r, 20))
|
|
137
|
+
expect(query!.data()?.pages).toEqual(["p0"])
|
|
138
|
+
|
|
139
|
+
// Fetch pages 1, 2, 3 sequentially
|
|
140
|
+
for (let i = 1; i <= 3; i++) {
|
|
141
|
+
await query!.fetchNextPage()
|
|
142
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
expect(query!.data()?.pages).toEqual(["p0", "p1", "p2", "p3"])
|
|
146
|
+
expect(query!.hasNextPage()).toBe(true) // page 4 is available
|
|
147
|
+
|
|
148
|
+
await query!.fetchNextPage()
|
|
149
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
150
|
+
expect(query!.data()?.pages).toEqual(["p0", "p1", "p2", "p3", "p4"])
|
|
151
|
+
expect(query!.hasNextPage()).toBe(false) // No more pages
|
|
152
|
+
unmount()
|
|
153
|
+
el.remove()
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
// ─── useSuspenseQuery — additional ───────────────────────────────────────────
|
|
158
|
+
|
|
159
|
+
describe("useSuspenseQuery — suspense behavior", () => {
|
|
160
|
+
let client: QueryClient
|
|
161
|
+
beforeEach(() => {
|
|
162
|
+
client = makeClient()
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it("isPending is true while query is loading", async () => {
|
|
166
|
+
const { promise, resolve } = deferred<string>()
|
|
167
|
+
let query: ReturnType<typeof useSuspenseQuery<string>> | undefined
|
|
168
|
+
|
|
169
|
+
const el = document.createElement("div")
|
|
170
|
+
document.body.appendChild(el)
|
|
171
|
+
const unmount = mount(
|
|
172
|
+
<QueryClientProvider client={client}>
|
|
173
|
+
{() => {
|
|
174
|
+
query = useSuspenseQuery(() => ({
|
|
175
|
+
queryKey: ["suspense-pending"],
|
|
176
|
+
queryFn: () => promise,
|
|
177
|
+
}))
|
|
178
|
+
return null
|
|
179
|
+
}}
|
|
180
|
+
</QueryClientProvider>,
|
|
181
|
+
el,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
expect(query!.isPending()).toBe(true)
|
|
185
|
+
expect(query!.isSuccess()).toBe(false)
|
|
186
|
+
|
|
187
|
+
resolve("loaded")
|
|
188
|
+
await promise
|
|
189
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
190
|
+
|
|
191
|
+
expect(query!.isPending()).toBe(false)
|
|
192
|
+
expect(query!.isSuccess()).toBe(true)
|
|
193
|
+
expect(query!.data()).toBe("loaded")
|
|
194
|
+
unmount()
|
|
195
|
+
el.remove()
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it("QuerySuspense with multiple queries waits for all", async () => {
|
|
199
|
+
const d1 = deferred<string>()
|
|
200
|
+
const d2 = deferred<number>()
|
|
201
|
+
let childCalled = false
|
|
202
|
+
|
|
203
|
+
const el = document.createElement("div")
|
|
204
|
+
document.body.appendChild(el)
|
|
205
|
+
const unmount = mount(
|
|
206
|
+
<QueryClientProvider client={client}>
|
|
207
|
+
{() => {
|
|
208
|
+
const q1 = useSuspenseQuery(() => ({
|
|
209
|
+
queryKey: ["multi-s1"],
|
|
210
|
+
queryFn: () => d1.promise,
|
|
211
|
+
}))
|
|
212
|
+
const q2 = useSuspenseQuery(() => ({
|
|
213
|
+
queryKey: ["multi-s2"],
|
|
214
|
+
queryFn: () => d2.promise,
|
|
215
|
+
}))
|
|
216
|
+
return (
|
|
217
|
+
<QuerySuspense query={[q1, q2]} fallback="loading...">
|
|
218
|
+
{() => {
|
|
219
|
+
childCalled = true
|
|
220
|
+
return null
|
|
221
|
+
}}
|
|
222
|
+
</QuerySuspense>
|
|
223
|
+
)
|
|
224
|
+
}}
|
|
225
|
+
</QueryClientProvider>,
|
|
226
|
+
el,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
// Only first resolves — children should not render
|
|
230
|
+
d1.resolve("first")
|
|
231
|
+
await d1.promise
|
|
232
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
233
|
+
expect(childCalled).toBe(false)
|
|
234
|
+
|
|
235
|
+
// Both resolved — children should render
|
|
236
|
+
d2.resolve(42)
|
|
237
|
+
await d2.promise
|
|
238
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
239
|
+
expect(childCalled).toBe(true)
|
|
240
|
+
unmount()
|
|
241
|
+
el.remove()
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
it("QuerySuspense renders null fallback when not provided", async () => {
|
|
245
|
+
let query: ReturnType<typeof useSuspenseQuery<string>> | undefined
|
|
246
|
+
|
|
247
|
+
const el = document.createElement("div")
|
|
248
|
+
document.body.appendChild(el)
|
|
249
|
+
const unmount = mount(
|
|
250
|
+
<QueryClientProvider client={client}>
|
|
251
|
+
{() => {
|
|
252
|
+
query = useSuspenseQuery(() => ({
|
|
253
|
+
queryKey: ["suspense-no-fallback"],
|
|
254
|
+
queryFn: () =>
|
|
255
|
+
new Promise(() => {
|
|
256
|
+
/* never resolves */
|
|
257
|
+
}),
|
|
258
|
+
}))
|
|
259
|
+
return <QuerySuspense query={query!}>{() => null}</QuerySuspense>
|
|
260
|
+
}}
|
|
261
|
+
</QueryClientProvider>,
|
|
262
|
+
el,
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
expect(query!.isPending()).toBe(true)
|
|
266
|
+
unmount()
|
|
267
|
+
el.remove()
|
|
268
|
+
})
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
// ─── QueryClientProvider context ─────────────────────────────────────────────
|
|
272
|
+
|
|
273
|
+
describe("QueryClientProvider — context behavior", () => {
|
|
274
|
+
it("useQueryClient returns the provided client", () => {
|
|
275
|
+
const client = makeClient()
|
|
276
|
+
let received: QueryClient | null = null
|
|
277
|
+
|
|
278
|
+
const el = document.createElement("div")
|
|
279
|
+
document.body.appendChild(el)
|
|
280
|
+
const unmount = mount(
|
|
281
|
+
<QueryClientProvider client={client}>
|
|
282
|
+
{() => {
|
|
283
|
+
received = useQueryClient()
|
|
284
|
+
return null
|
|
285
|
+
}}
|
|
286
|
+
</QueryClientProvider>,
|
|
287
|
+
el,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
expect(received).toBe(client)
|
|
291
|
+
unmount()
|
|
292
|
+
el.remove()
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it("nested providers override outer client", () => {
|
|
296
|
+
const outerClient = makeClient()
|
|
297
|
+
const innerClient = makeClient()
|
|
298
|
+
let outerReceived: QueryClient | null = null
|
|
299
|
+
let innerReceived: QueryClient | null = null
|
|
300
|
+
|
|
301
|
+
const el = document.createElement("div")
|
|
302
|
+
document.body.appendChild(el)
|
|
303
|
+
const unmount = mount(
|
|
304
|
+
<QueryClientProvider client={outerClient}>
|
|
305
|
+
{() => {
|
|
306
|
+
outerReceived = useQueryClient()
|
|
307
|
+
return (
|
|
308
|
+
<QueryClientProvider client={innerClient}>
|
|
309
|
+
{() => {
|
|
310
|
+
innerReceived = useQueryClient()
|
|
311
|
+
return null
|
|
312
|
+
}}
|
|
313
|
+
</QueryClientProvider>
|
|
314
|
+
)
|
|
315
|
+
}}
|
|
316
|
+
</QueryClientProvider>,
|
|
317
|
+
el,
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
expect(outerReceived).toBe(outerClient)
|
|
321
|
+
expect(innerReceived).toBe(innerClient)
|
|
322
|
+
expect(outerReceived).not.toBe(innerReceived)
|
|
323
|
+
unmount()
|
|
324
|
+
el.remove()
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
it("useQueryClient throws descriptive error without provider", () => {
|
|
328
|
+
expect(() => useQueryClient()).toThrow("No QueryClient found")
|
|
329
|
+
})
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
// ─── useIsFetching / useIsMutating — additional ──────────────────────────────
|
|
333
|
+
|
|
334
|
+
describe("useIsFetching — additional", () => {
|
|
335
|
+
it("counts multiple concurrent queries", async () => {
|
|
336
|
+
const client = makeClient()
|
|
337
|
+
const d1 = deferred<string>()
|
|
338
|
+
const d2 = deferred<string>()
|
|
339
|
+
let isFetching: (() => number) | undefined
|
|
340
|
+
|
|
341
|
+
const el = document.createElement("div")
|
|
342
|
+
document.body.appendChild(el)
|
|
343
|
+
const unmount = mount(
|
|
344
|
+
<QueryClientProvider client={client}>
|
|
345
|
+
{() => {
|
|
346
|
+
isFetching = useIsFetching()
|
|
347
|
+
useQuery(() => ({
|
|
348
|
+
queryKey: ["concurrent-1"],
|
|
349
|
+
queryFn: () => d1.promise,
|
|
350
|
+
}))
|
|
351
|
+
useQuery(() => ({
|
|
352
|
+
queryKey: ["concurrent-2"],
|
|
353
|
+
queryFn: () => d2.promise,
|
|
354
|
+
}))
|
|
355
|
+
return null
|
|
356
|
+
}}
|
|
357
|
+
</QueryClientProvider>,
|
|
358
|
+
el,
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
await new Promise((r) => setTimeout(r, 0))
|
|
362
|
+
// Both queries should be fetching
|
|
363
|
+
expect(isFetching!()).toBeGreaterThanOrEqual(2)
|
|
364
|
+
|
|
365
|
+
d1.resolve("done1")
|
|
366
|
+
await d1.promise
|
|
367
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
368
|
+
// One still fetching
|
|
369
|
+
expect(isFetching!()).toBeGreaterThanOrEqual(1)
|
|
370
|
+
|
|
371
|
+
d2.resolve("done2")
|
|
372
|
+
await d2.promise
|
|
373
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
374
|
+
expect(isFetching!()).toBe(0)
|
|
375
|
+
|
|
376
|
+
unmount()
|
|
377
|
+
el.remove()
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
it("useIsFetching with query key filter", async () => {
|
|
381
|
+
const client = makeClient()
|
|
382
|
+
const d1 = deferred<string>()
|
|
383
|
+
const d2 = deferred<string>()
|
|
384
|
+
let allFetching: (() => number) | undefined
|
|
385
|
+
let userFetching: (() => number) | undefined
|
|
386
|
+
|
|
387
|
+
const el = document.createElement("div")
|
|
388
|
+
document.body.appendChild(el)
|
|
389
|
+
const unmount = mount(
|
|
390
|
+
<QueryClientProvider client={client}>
|
|
391
|
+
{() => {
|
|
392
|
+
allFetching = useIsFetching()
|
|
393
|
+
userFetching = useIsFetching({ queryKey: ["user"] })
|
|
394
|
+
useQuery(() => ({
|
|
395
|
+
queryKey: ["user", "1"],
|
|
396
|
+
queryFn: () => d1.promise,
|
|
397
|
+
}))
|
|
398
|
+
useQuery(() => ({
|
|
399
|
+
queryKey: ["posts"],
|
|
400
|
+
queryFn: () => d2.promise,
|
|
401
|
+
}))
|
|
402
|
+
return null
|
|
403
|
+
}}
|
|
404
|
+
</QueryClientProvider>,
|
|
405
|
+
el,
|
|
406
|
+
)
|
|
407
|
+
|
|
408
|
+
await new Promise((r) => setTimeout(r, 0))
|
|
409
|
+
expect(allFetching!()).toBeGreaterThanOrEqual(2)
|
|
410
|
+
expect(userFetching!()).toBe(1) // Only the user query
|
|
411
|
+
|
|
412
|
+
d1.resolve("user-data")
|
|
413
|
+
await d1.promise
|
|
414
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
415
|
+
expect(userFetching!()).toBe(0)
|
|
416
|
+
expect(allFetching!()).toBeGreaterThanOrEqual(1) // posts still fetching
|
|
417
|
+
|
|
418
|
+
d2.resolve("posts-data")
|
|
419
|
+
await d2.promise
|
|
420
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
421
|
+
expect(allFetching!()).toBe(0)
|
|
422
|
+
|
|
423
|
+
unmount()
|
|
424
|
+
el.remove()
|
|
425
|
+
})
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
describe("useIsMutating — additional", () => {
|
|
429
|
+
it("counts multiple concurrent mutations", async () => {
|
|
430
|
+
const client = makeClient()
|
|
431
|
+
const d1 = deferred<void>()
|
|
432
|
+
const d2 = deferred<void>()
|
|
433
|
+
let isMutating: (() => number) | undefined
|
|
434
|
+
let mut1: ReturnType<typeof useMutation<void, Error, void>> | undefined
|
|
435
|
+
let mut2: ReturnType<typeof useMutation<void, Error, void>> | undefined
|
|
436
|
+
|
|
437
|
+
const el = document.createElement("div")
|
|
438
|
+
document.body.appendChild(el)
|
|
439
|
+
const unmount = mount(
|
|
440
|
+
<QueryClientProvider client={client}>
|
|
441
|
+
{() => {
|
|
442
|
+
isMutating = useIsMutating()
|
|
443
|
+
mut1 = useMutation<void, Error, void>({ mutationFn: () => d1.promise })
|
|
444
|
+
mut2 = useMutation<void, Error, void>({ mutationFn: () => d2.promise })
|
|
445
|
+
return null
|
|
446
|
+
}}
|
|
447
|
+
</QueryClientProvider>,
|
|
448
|
+
el,
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
expect(isMutating!()).toBe(0)
|
|
452
|
+
|
|
453
|
+
mut1!.mutate(undefined)
|
|
454
|
+
mut2!.mutate(undefined)
|
|
455
|
+
await new Promise((r) => setTimeout(r, 0))
|
|
456
|
+
expect(isMutating!()).toBe(2)
|
|
457
|
+
|
|
458
|
+
d1.resolve()
|
|
459
|
+
await d1.promise
|
|
460
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
461
|
+
expect(isMutating!()).toBe(1)
|
|
462
|
+
|
|
463
|
+
d2.resolve()
|
|
464
|
+
await d2.promise
|
|
465
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
466
|
+
expect(isMutating!()).toBe(0)
|
|
467
|
+
|
|
468
|
+
unmount()
|
|
469
|
+
el.remove()
|
|
470
|
+
})
|
|
471
|
+
})
|
|
472
|
+
|
|
473
|
+
// ─── useSSE — lastEventId and readyState (already covered in sse.test.tsx,
|
|
474
|
+
// ─── but we add a few integration tests here) ────────────────────────────────
|
|
475
|
+
|
|
476
|
+
// Note: useSSE lastEventId and readyState are thoroughly tested in sse.test.tsx.
|
|
477
|
+
// This file focuses on query/mutation/infinite/suspense/provider scenarios.
|