@codeleap/query 5.8.3 → 5.8.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 +6 -10
- package/package.json.bak +3 -7
- package/src/factors/createQueryManager.ts +38 -0
- package/src/factors/createQueryOperations.ts +37 -0
- package/src/factors/index.ts +2 -0
- package/src/index.ts +2 -8
- package/src/lib/Mutations.ts +280 -0
- package/src/{queryClient.ts → lib/QueryClientEnhanced/index.ts} +24 -72
- package/src/lib/QueryClientEnhanced/types.ts +38 -0
- package/src/lib/QueryKeys.ts +319 -0
- package/src/lib/QueryManager.ts +488 -0
- package/src/lib/QueryOperations/index.ts +351 -0
- package/src/lib/QueryOperations/types.ts +47 -0
- package/src/lib/index.ts +5 -0
- package/src/tests/Mutations.spec.tsx +458 -0
- package/src/tests/QueryManager.spec.tsx +920 -0
- package/src/tests/QueryOperations.spec.tsx +109 -0
- package/src/tests/integration.spec.tsx +551 -0
- package/src/tests/setup.ts +119 -0
- package/src/types/core.ts +33 -0
- package/src/types/create.ts +16 -0
- package/src/types/delete.ts +15 -0
- package/src/types/index.ts +7 -0
- package/src/types/list.ts +24 -0
- package/src/types/retrieve.ts +7 -0
- package/src/types/update.ts +14 -0
- package/src/types/utility.ts +22 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/misc.ts +43 -0
- package/src/QueryManager.ts +0 -954
- package/src/types.ts +0 -199
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, spyOn, mock } from 'bun:test'
|
|
2
|
+
import { Mutations, createMutations } from '../lib/Mutations'
|
|
3
|
+
import { QueryKeys } from '../lib/QueryKeys'
|
|
4
|
+
import { createTestQueryClient, TestUser, TestUserFilters, createMockUsers } from './setup'
|
|
5
|
+
import { InfiniteData } from '@tanstack/react-query'
|
|
6
|
+
|
|
7
|
+
describe('Mutations', () => {
|
|
8
|
+
let queryClient: ReturnType<typeof createTestQueryClient>
|
|
9
|
+
let queryKeys: QueryKeys<TestUser, TestUserFilters>
|
|
10
|
+
let mutations: Mutations<TestUser, TestUserFilters>
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
queryClient = createTestQueryClient()
|
|
14
|
+
queryKeys = new QueryKeys('users', queryClient)
|
|
15
|
+
mutations = new Mutations(queryKeys, queryClient, 'users')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
describe('constructor', () => {
|
|
19
|
+
it('should create Mutations instance with correct parameters', () => {
|
|
20
|
+
expect(mutations).toBeInstanceOf(Mutations)
|
|
21
|
+
expect(mutations['queryKeys']).toBe(queryKeys)
|
|
22
|
+
expect(mutations['queryClient']).toBe(queryClient)
|
|
23
|
+
expect(mutations['queryName']).toBe('users')
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
describe('addItem', () => {
|
|
28
|
+
const mockUsers = createMockUsers(3)
|
|
29
|
+
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
const mockData: InfiniteData<TestUser[], number> = {
|
|
32
|
+
pages: [mockUsers.slice(0, 2), mockUsers.slice(2)],
|
|
33
|
+
pageParams: [0, 2]
|
|
34
|
+
}
|
|
35
|
+
queryClient.setQueryData(['users', 'list'], mockData)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('should add item to start by default', () => {
|
|
39
|
+
const newUser = createMockUsers(1)[0]
|
|
40
|
+
|
|
41
|
+
mutations.addItem(newUser)
|
|
42
|
+
|
|
43
|
+
const data = queryClient.getQueryData(['users', 'list']) as InfiniteData<TestUser[], number>
|
|
44
|
+
expect(data.pages[0][0]).toEqual(newUser)
|
|
45
|
+
expect(data.pages[0]).toHaveLength(3) // original 2 + new 1
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('should add item to start when position is "start"', () => {
|
|
49
|
+
const newUser = createMockUsers(1)[0]
|
|
50
|
+
|
|
51
|
+
mutations.addItem(newUser, 'start')
|
|
52
|
+
|
|
53
|
+
const data = queryClient.getQueryData(['users', 'list']) as InfiniteData<TestUser[], number>
|
|
54
|
+
expect(data.pages[0][0]).toEqual(newUser)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('should add item to end when position is "end"', () => {
|
|
58
|
+
const newUser = createMockUsers(1)[0]
|
|
59
|
+
|
|
60
|
+
mutations.addItem(newUser, 'end')
|
|
61
|
+
|
|
62
|
+
const data = queryClient.getQueryData(['users', 'list']) as InfiniteData<TestUser[], number>
|
|
63
|
+
const lastPage = data.pages[data.pages.length - 1]
|
|
64
|
+
expect(lastPage[lastPage.length - 1]).toEqual(newUser)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('should create new data when no cache exists', () => {
|
|
68
|
+
queryClient.clear()
|
|
69
|
+
const newUser = createMockUsers(1)[0]
|
|
70
|
+
|
|
71
|
+
mutations.addItem(newUser)
|
|
72
|
+
|
|
73
|
+
const data = queryClient.getQueryData(['users', 'list']) as InfiniteData<TestUser[], number>
|
|
74
|
+
expect(data).toEqual({
|
|
75
|
+
pageParams: [0],
|
|
76
|
+
pages: [[newUser]]
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('should add item with specific list filters', () => {
|
|
81
|
+
const filters = { status: 'active' as const }
|
|
82
|
+
const newUser = createMockUsers(1)[0]
|
|
83
|
+
|
|
84
|
+
// Set up filtered cache
|
|
85
|
+
queryClient.setQueryData(['users', 'list', filters], {
|
|
86
|
+
pages: [mockUsers.slice(0, 1)],
|
|
87
|
+
pageParams: [0]
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
mutations.addItem(newUser, 'start', filters)
|
|
91
|
+
|
|
92
|
+
const data = queryClient.getQueryData(['users', 'list', filters]) as InfiniteData<TestUser[], number>
|
|
93
|
+
expect(data.pages[0][0]).toEqual(newUser)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('should handle multiple query keys (RemovedItemMap)', () => {
|
|
97
|
+
const newUser = createMockUsers(1)[0]
|
|
98
|
+
const queryKey1 = ['users', 'list']
|
|
99
|
+
const queryKey2 = ['users', 'list', { status: 'active' }]
|
|
100
|
+
|
|
101
|
+
// Set up multiple caches
|
|
102
|
+
queryClient.setQueryData(queryKey1, {
|
|
103
|
+
pages: [mockUsers.slice(0, 2)],
|
|
104
|
+
pageParams: [0]
|
|
105
|
+
})
|
|
106
|
+
queryClient.setQueryData(queryKey2, {
|
|
107
|
+
pages: [mockUsers.slice(0, 1)],
|
|
108
|
+
pageParams: [0]
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
const removedItemMap = [
|
|
112
|
+
[queryKey1, { pageIndex: 0, itemIndex: 1 }],
|
|
113
|
+
[queryKey2, { pageIndex: 0, itemIndex: 0 }]
|
|
114
|
+
] as any
|
|
115
|
+
|
|
116
|
+
mutations.addItem(newUser, removedItemMap)
|
|
117
|
+
|
|
118
|
+
const data1 = queryClient.getQueryData(queryKey1) as InfiniteData<TestUser[], number>
|
|
119
|
+
const data2 = queryClient.getQueryData(queryKey2) as InfiniteData<TestUser[], number>
|
|
120
|
+
|
|
121
|
+
expect(data1.pages[0][1]).toEqual(newUser)
|
|
122
|
+
expect(data2.pages[0][0]).toEqual(newUser)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it('should handle item position beyond page length', () => {
|
|
126
|
+
const newUser = createMockUsers(1)[0]
|
|
127
|
+
const queryKey = ['users', 'list']
|
|
128
|
+
|
|
129
|
+
queryClient.setQueryData(queryKey, {
|
|
130
|
+
pages: [mockUsers.slice(0, 1)],
|
|
131
|
+
pageParams: [0]
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
const removedItemMap = [
|
|
135
|
+
[queryKey, { pageIndex: 0, itemIndex: 10 }] // Beyond page length
|
|
136
|
+
] as any
|
|
137
|
+
|
|
138
|
+
mutations.addItem(newUser, removedItemMap)
|
|
139
|
+
|
|
140
|
+
const data = queryClient.getQueryData(queryKey) as InfiniteData<TestUser[], number>
|
|
141
|
+
expect(data.pages[0][data.pages[0].length - 1]).toEqual(newUser)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('should handle page index beyond pages length', () => {
|
|
145
|
+
const newUser = createMockUsers(1)[0]
|
|
146
|
+
const queryKey = ['users', 'list']
|
|
147
|
+
|
|
148
|
+
queryClient.setQueryData(queryKey, {
|
|
149
|
+
pages: [mockUsers.slice(0, 1)],
|
|
150
|
+
pageParams: [0]
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
const removedItemMap = [
|
|
154
|
+
[queryKey, { pageIndex: 5, itemIndex: 0 }] // Beyond pages length
|
|
155
|
+
] as any
|
|
156
|
+
|
|
157
|
+
mutations.addItem(newUser, removedItemMap)
|
|
158
|
+
|
|
159
|
+
const data = queryClient.getQueryData(queryKey) as InfiniteData<TestUser[], number>
|
|
160
|
+
const lastPage = data.pages[data.pages.length - 1]
|
|
161
|
+
expect(lastPage[lastPage.length - 1]).toEqual(newUser)
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
it('should handle empty pages array', () => {
|
|
165
|
+
const newUser = createMockUsers(1)[0]
|
|
166
|
+
const queryKey = ['users', 'list']
|
|
167
|
+
|
|
168
|
+
queryClient.setQueryData(queryKey, {
|
|
169
|
+
pages: [],
|
|
170
|
+
pageParams: []
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
const removedItemMap = [
|
|
174
|
+
[queryKey, { pageIndex: 0, itemIndex: 0 }]
|
|
175
|
+
] as any
|
|
176
|
+
|
|
177
|
+
mutations.addItem(newUser, removedItemMap)
|
|
178
|
+
|
|
179
|
+
const data = queryClient.getQueryData(queryKey) as InfiniteData<TestUser[], number>
|
|
180
|
+
expect(data.pages[0]).toEqual([newUser])
|
|
181
|
+
})
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
describe('removeItem', () => {
|
|
185
|
+
const mockUsers = createMockUsers(3)
|
|
186
|
+
|
|
187
|
+
beforeEach(() => {
|
|
188
|
+
// Set up multiple list queries
|
|
189
|
+
queryClient.setQueryData(['users', 'list'], {
|
|
190
|
+
pages: [mockUsers.slice(0, 2), [mockUsers[2]]],
|
|
191
|
+
pageParams: [0, 2]
|
|
192
|
+
})
|
|
193
|
+
queryClient.setQueryData(['users', 'list', { status: 'active' }], {
|
|
194
|
+
pages: [[mockUsers[0]]],
|
|
195
|
+
pageParams: [0]
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
// Set up retrieve cache
|
|
199
|
+
queryClient.setQueryData(['users', 'retrieve', mockUsers[0].id], mockUsers[0])
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
it('should remove item from all list queries and return removal map', () => {
|
|
203
|
+
const getAllListQueriesSpy = spyOn(queryKeys, 'getAllListQueries').mockReturnValue([
|
|
204
|
+
{ queryKey: ['users', 'list'], state: { data: queryClient.getQueryData(['users', 'list']) } },
|
|
205
|
+
{ queryKey: ['users', 'list', { status: 'active' }], state: { data: queryClient.getQueryData(['users', 'list', { status: 'active' }]) } }
|
|
206
|
+
] as any)
|
|
207
|
+
|
|
208
|
+
const removedMap = mutations.removeItem(mockUsers[0].id)
|
|
209
|
+
|
|
210
|
+
expect(removedMap).toHaveLength(2)
|
|
211
|
+
expect(removedMap![0]).toEqual([['users', 'list'], { pageIndex: 0, itemIndex: 0 }])
|
|
212
|
+
expect(removedMap![1]).toEqual([['users', 'list', { status: 'active' }], { pageIndex: 0, itemIndex: 0 }])
|
|
213
|
+
|
|
214
|
+
// Verify item was removed from caches
|
|
215
|
+
const data1 = queryClient.getQueryData(['users', 'list']) as InfiniteData<TestUser[], number>
|
|
216
|
+
const data2 = queryClient.getQueryData(['users', 'list', { status: 'active' }]) as InfiniteData<TestUser[], number>
|
|
217
|
+
|
|
218
|
+
expect(data1.pages[0]).not.toContain(mockUsers[0])
|
|
219
|
+
expect(data2.pages[0]).toHaveLength(0)
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('should remove retrieve query data', () => {
|
|
223
|
+
const removeRetrieveQueryDataSpy = spyOn(queryKeys, 'removeRetrieveQueryData')
|
|
224
|
+
const getAllListQueriesSpy = spyOn(queryKeys, 'getAllListQueries').mockReturnValue([])
|
|
225
|
+
|
|
226
|
+
mutations.removeItem(mockUsers[0].id)
|
|
227
|
+
|
|
228
|
+
expect(removeRetrieveQueryDataSpy).toHaveBeenCalledWith(mockUsers[0].id)
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
it('should return empty array when item not found in any list', () => {
|
|
232
|
+
const getAllListQueriesSpy = spyOn(queryKeys, 'getAllListQueries').mockReturnValue([
|
|
233
|
+
{ queryKey: ['users', 'list'], state: { data: queryClient.getQueryData(['users', 'list']) } }
|
|
234
|
+
] as any)
|
|
235
|
+
|
|
236
|
+
const removedMap = mutations.removeItem('non-existent-id')
|
|
237
|
+
|
|
238
|
+
expect(removedMap).toEqual([])
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
it('should handle empty pages after removal', () => {
|
|
242
|
+
const getAllListQueriesSpy = spyOn(queryKeys, 'getAllListQueries').mockReturnValue([
|
|
243
|
+
{ queryKey: ['users', 'list'], state: { data: { pages: [[mockUsers[0]]], pageParams: [0] } } }
|
|
244
|
+
] as any)
|
|
245
|
+
|
|
246
|
+
mutations.removeItem(mockUsers[0].id)
|
|
247
|
+
|
|
248
|
+
const data = queryClient.getQueryData(['users', 'list']) as InfiniteData<TestUser[], number>
|
|
249
|
+
expect(data.pages).toEqual([[]])
|
|
250
|
+
expect(data.pageParams).toEqual([0])
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
it('should filter out empty pages', () => {
|
|
254
|
+
const getAllListQueriesSpy = spyOn(queryKeys, 'getAllListQueries').mockReturnValue([
|
|
255
|
+
{ queryKey: ['users', 'list'], state: { data: { pages: [[mockUsers[0]], [mockUsers[1]]], pageParams: [0, 1] } } }
|
|
256
|
+
] as any)
|
|
257
|
+
|
|
258
|
+
mutations.removeItem(mockUsers[0].id)
|
|
259
|
+
|
|
260
|
+
const data = queryClient.getQueryData(['users', 'list']) as InfiniteData<TestUser[], number>
|
|
261
|
+
expect(data.pages).toEqual([[mockUsers[1]]])
|
|
262
|
+
expect(data.pageParams).toEqual([0])
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
it('should handle queries with no current data', () => {
|
|
266
|
+
const getAllListQueriesSpy = spyOn(queryKeys, 'getAllListQueries').mockReturnValue([
|
|
267
|
+
{ queryKey: ['users', 'list'], state: { data: null } }
|
|
268
|
+
] as any)
|
|
269
|
+
|
|
270
|
+
const removedMap = mutations.removeItem(mockUsers[0].id)
|
|
271
|
+
|
|
272
|
+
expect(removedMap).toEqual([])
|
|
273
|
+
})
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
describe('updateItems', () => {
|
|
277
|
+
const mockUsers = createMockUsers(3)
|
|
278
|
+
|
|
279
|
+
beforeEach(() => {
|
|
280
|
+
const getAllListQueriesSpy = spyOn(queryKeys, 'getAllListQueries').mockReturnValue([
|
|
281
|
+
{
|
|
282
|
+
queryKey: ['users', 'list'],
|
|
283
|
+
state: {
|
|
284
|
+
data: {
|
|
285
|
+
pages: [mockUsers.slice(0, 2), [mockUsers[2]]],
|
|
286
|
+
pageParams: [0, 2]
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
] as any)
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
it('should update single item by id', () => {
|
|
294
|
+
const updateData = { ...mockUsers[0], name: 'Updated Name' }
|
|
295
|
+
const setQueryDataSpy = spyOn(queryClient, 'setQueryData')
|
|
296
|
+
|
|
297
|
+
mutations.updateItems(updateData)
|
|
298
|
+
|
|
299
|
+
expect(setQueryDataSpy).toHaveBeenCalledWith(
|
|
300
|
+
['users', 'retrieve', updateData.id],
|
|
301
|
+
updateData
|
|
302
|
+
)
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it('should update single item by tempId', () => {
|
|
306
|
+
const updateData = { ...mockUsers[0], name: 'Updated Name', tempId: 'temp-1' }
|
|
307
|
+
const setQueryDataSpy = spyOn(queryClient, 'setQueryData')
|
|
308
|
+
|
|
309
|
+
mutations.updateItems(updateData)
|
|
310
|
+
|
|
311
|
+
const expectedData = { ...updateData }
|
|
312
|
+
// @ts-ignore
|
|
313
|
+
delete expectedData.tempId
|
|
314
|
+
|
|
315
|
+
expect(setQueryDataSpy).toHaveBeenCalledWith(
|
|
316
|
+
['users', 'retrieve', updateData.id],
|
|
317
|
+
expectedData
|
|
318
|
+
)
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
it('should update multiple items', () => {
|
|
322
|
+
const updateData = [
|
|
323
|
+
{ ...mockUsers[0], name: 'Updated Name 1' },
|
|
324
|
+
{ ...mockUsers[1], name: 'Updated Name 2' }
|
|
325
|
+
]
|
|
326
|
+
const setQueryDataSpy = spyOn(queryClient, 'setQueryData')
|
|
327
|
+
|
|
328
|
+
mutations.updateItems(updateData)
|
|
329
|
+
|
|
330
|
+
expect(setQueryDataSpy).toHaveBeenCalledTimes(3) // 2 retrieve + 1 list update
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
it('should not update if data is the same (deep equal)', () => {
|
|
334
|
+
const setQueryDataSpy = spyOn(queryClient, 'setQueryData')
|
|
335
|
+
|
|
336
|
+
// Update with same data
|
|
337
|
+
mutations.updateItems(mockUsers[0])
|
|
338
|
+
|
|
339
|
+
// Should only set retrieve cache, not update list (no changes)
|
|
340
|
+
expect(setQueryDataSpy).toHaveBeenCalledTimes(1)
|
|
341
|
+
expect(setQueryDataSpy).toHaveBeenCalledWith(
|
|
342
|
+
['users', 'retrieve', mockUsers[0].id],
|
|
343
|
+
mockUsers[0]
|
|
344
|
+
)
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
it('should update list cache when item data changes', () => {
|
|
348
|
+
const updateData = { ...mockUsers[0], name: 'Updated Name' }
|
|
349
|
+
const setQueryDataSpy = spyOn(queryClient, 'setQueryData')
|
|
350
|
+
|
|
351
|
+
mutations.updateItems(updateData)
|
|
352
|
+
|
|
353
|
+
// Should update both retrieve and list cache
|
|
354
|
+
expect(setQueryDataSpy).toHaveBeenCalledWith(
|
|
355
|
+
['users', 'retrieve', updateData.id],
|
|
356
|
+
updateData
|
|
357
|
+
)
|
|
358
|
+
expect(setQueryDataSpy).toHaveBeenCalledWith(
|
|
359
|
+
['users', 'list'],
|
|
360
|
+
expect.objectContaining({
|
|
361
|
+
pages: expect.arrayContaining([
|
|
362
|
+
expect.arrayContaining([updateData])
|
|
363
|
+
])
|
|
364
|
+
})
|
|
365
|
+
)
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
it('should handle queries with no data', () => {
|
|
369
|
+
// Override the spy for this test
|
|
370
|
+
spyOn(queryKeys, 'getAllListQueries').mockReturnValue([
|
|
371
|
+
{ queryKey: ['users', 'list'], state: { data: null } }
|
|
372
|
+
] as any)
|
|
373
|
+
|
|
374
|
+
const updateData = { ...mockUsers[0], name: 'Updated Name' }
|
|
375
|
+
const setQueryDataSpy = spyOn(queryClient, 'setQueryData')
|
|
376
|
+
|
|
377
|
+
mutations.updateItems(updateData)
|
|
378
|
+
|
|
379
|
+
// Should only update retrieve cache
|
|
380
|
+
expect(setQueryDataSpy).toHaveBeenCalledTimes(1)
|
|
381
|
+
expect(setQueryDataSpy).toHaveBeenCalledWith(
|
|
382
|
+
['users', 'retrieve', updateData.id],
|
|
383
|
+
updateData
|
|
384
|
+
)
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
it('should preserve page structure when updating items', () => {
|
|
388
|
+
const updateData = { ...mockUsers[2], name: 'Updated Name' } // Item in second page
|
|
389
|
+
const setQueryDataSpy = spyOn(queryClient, 'setQueryData')
|
|
390
|
+
|
|
391
|
+
mutations.updateItems(updateData)
|
|
392
|
+
|
|
393
|
+
expect(setQueryDataSpy).toHaveBeenCalledWith(
|
|
394
|
+
['users', 'list'],
|
|
395
|
+
expect.objectContaining({
|
|
396
|
+
pages: [
|
|
397
|
+
mockUsers.slice(0, 2), // First page unchanged
|
|
398
|
+
[updateData] // Second page with updated item
|
|
399
|
+
],
|
|
400
|
+
pageParams: [0, 2]
|
|
401
|
+
})
|
|
402
|
+
)
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
it('should handle items not found in list', () => {
|
|
406
|
+
const nonExistentItem = { id: 'non-existent', name: 'New Name' } as TestUser
|
|
407
|
+
const setQueryDataSpy = spyOn(queryClient, 'setQueryData')
|
|
408
|
+
|
|
409
|
+
mutations.updateItems(nonExistentItem)
|
|
410
|
+
|
|
411
|
+
// Should only update retrieve cache
|
|
412
|
+
expect(setQueryDataSpy).toHaveBeenCalledTimes(1)
|
|
413
|
+
expect(setQueryDataSpy).toHaveBeenCalledWith(
|
|
414
|
+
['users', 'retrieve', nonExistentItem.id],
|
|
415
|
+
nonExistentItem
|
|
416
|
+
)
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
it('should remove tempId from cached data', () => {
|
|
420
|
+
const updateData = { ...mockUsers[0], name: 'Updated Name', tempId: 'temp-123' }
|
|
421
|
+
const setQueryDataSpy = spyOn(queryClient, 'setQueryData')
|
|
422
|
+
|
|
423
|
+
mutations.updateItems(updateData)
|
|
424
|
+
|
|
425
|
+
// Check retrieve cache call - tempId should be removed
|
|
426
|
+
const retrieveCall = setQueryDataSpy.mock.calls.find(call =>
|
|
427
|
+
Array.isArray(call[0]) && call[0].includes('retrieve')
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
expect(retrieveCall).toBeDefined()
|
|
431
|
+
const cachedData = retrieveCall![1] as any
|
|
432
|
+
expect(cachedData).not.toHaveProperty('tempId')
|
|
433
|
+
expect(cachedData.name).toBe('Updated Name')
|
|
434
|
+
|
|
435
|
+
// Check list cache call - tempId should be removed from items
|
|
436
|
+
const listCall = setQueryDataSpy.mock.calls.find(call =>
|
|
437
|
+
Array.isArray(call[0]) && call[0].includes('list')
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
if (listCall) {
|
|
441
|
+
const updatedListData = listCall[1] as any
|
|
442
|
+
const updatedItem = updatedListData.pages.flat().find((item: any) => item.id === updateData.id)
|
|
443
|
+
expect(updatedItem).not.toHaveProperty('tempId')
|
|
444
|
+
}
|
|
445
|
+
})
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
describe('createMutations factory', () => {
|
|
449
|
+
it('should create Mutations instance', () => {
|
|
450
|
+
const mutations = createMutations(queryKeys, queryClient, 'test')
|
|
451
|
+
|
|
452
|
+
expect(mutations).toBeInstanceOf(Mutations)
|
|
453
|
+
expect(mutations['queryKeys']).toBe(queryKeys)
|
|
454
|
+
expect(mutations['queryClient']).toBe(queryClient)
|
|
455
|
+
expect(mutations['queryName']).toBe('test')
|
|
456
|
+
})
|
|
457
|
+
})
|
|
458
|
+
})
|