mutts 1.0.0 → 1.0.1

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 (53) hide show
  1. package/dist/chunks/{decorator-BXsign4Z.js → decorator-8qjFb7dw.js} +2 -2
  2. package/dist/chunks/decorator-8qjFb7dw.js.map +1 -0
  3. package/dist/chunks/{decorator-CPbZNnsX.esm.js → decorator-AbRkXM5O.esm.js} +2 -2
  4. package/dist/chunks/decorator-AbRkXM5O.esm.js.map +1 -0
  5. package/dist/decorator.d.ts +1 -1
  6. package/dist/decorator.esm.js +1 -1
  7. package/dist/decorator.js +1 -1
  8. package/dist/destroyable.esm.js +1 -1
  9. package/dist/destroyable.js +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.esm.js +2 -2
  12. package/dist/index.js +2 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/mutts.umd.js +1 -1
  15. package/dist/mutts.umd.js.map +1 -1
  16. package/dist/mutts.umd.min.js +1 -1
  17. package/dist/mutts.umd.min.js.map +1 -1
  18. package/dist/reactive.d.ts +4 -3
  19. package/dist/reactive.esm.js +61 -57
  20. package/dist/reactive.esm.js.map +1 -1
  21. package/dist/reactive.js +61 -56
  22. package/dist/reactive.js.map +1 -1
  23. package/dist/std-decorators.esm.js +1 -1
  24. package/dist/std-decorators.js +1 -1
  25. package/docs/reactive.md +616 -0
  26. package/package.json +1 -2
  27. package/dist/chunks/decorator-BXsign4Z.js.map +0 -1
  28. package/dist/chunks/decorator-CPbZNnsX.esm.js.map +0 -1
  29. package/src/decorator.test.ts +0 -495
  30. package/src/decorator.ts +0 -205
  31. package/src/destroyable.test.ts +0 -155
  32. package/src/destroyable.ts +0 -158
  33. package/src/eventful.test.ts +0 -380
  34. package/src/eventful.ts +0 -69
  35. package/src/index.ts +0 -7
  36. package/src/indexable.test.ts +0 -388
  37. package/src/indexable.ts +0 -124
  38. package/src/promiseChain.test.ts +0 -201
  39. package/src/promiseChain.ts +0 -99
  40. package/src/reactive/array.test.ts +0 -923
  41. package/src/reactive/array.ts +0 -352
  42. package/src/reactive/core.test.ts +0 -1663
  43. package/src/reactive/core.ts +0 -866
  44. package/src/reactive/index.ts +0 -28
  45. package/src/reactive/interface.test.ts +0 -1477
  46. package/src/reactive/interface.ts +0 -231
  47. package/src/reactive/map.test.ts +0 -866
  48. package/src/reactive/map.ts +0 -162
  49. package/src/reactive/set.test.ts +0 -289
  50. package/src/reactive/set.ts +0 -142
  51. package/src/std-decorators.test.ts +0 -679
  52. package/src/std-decorators.ts +0 -182
  53. package/src/utils.ts +0 -52
@@ -1,866 +0,0 @@
1
- import { effect, reactive } from './index'
2
-
3
- describe('ReactiveWeakMap', () => {
4
- describe('basic functionality', () => {
5
- it('should create a reactive WeakMap wrapper', () => {
6
- const weakMap = new WeakMap<object, string>()
7
- const reactiveWeakMap = reactive(weakMap)
8
- expect(reactiveWeakMap).toBeInstanceOf(Object)
9
- // ReactiveWeakMap is a wrapper, not a native WeakMap instance
10
- expect(reactiveWeakMap).toBeInstanceOf(WeakMap)
11
- })
12
-
13
- it('should work with reactive() function', () => {
14
- const weakMap = new WeakMap<object, string>()
15
- const reactiveWeakMap = reactive(weakMap)
16
-
17
- // The reactive wrapper should behave like a WeakMap
18
- expect(reactiveWeakMap).toBeInstanceOf(WeakMap)
19
- })
20
-
21
- it('should wrap existing WeakMap with entries', () => {
22
- const key1 = { id: 1 }
23
- const key2 = { id: 2 }
24
- const originalWeakMap = new WeakMap<object, string>([
25
- [key1, 'value1'],
26
- [key2, 'value2'],
27
- ])
28
- const reactiveWeakMap = reactive(originalWeakMap)
29
-
30
- expect(reactiveWeakMap.get(key1)).toBe('value1')
31
- expect(reactiveWeakMap.get(key2)).toBe('value2')
32
- })
33
- })
34
-
35
- describe('reactive operations', () => {
36
- it('should track dependencies when getting values', () => {
37
- const weakMap = new WeakMap<object, string>()
38
- const reactiveWeakMap = reactive(weakMap)
39
- const key = { id: 1 }
40
- reactiveWeakMap.set(key, 'test')
41
-
42
- let effectCount = 0
43
- effect(() => {
44
- effectCount++
45
- reactiveWeakMap.get(key)
46
- })
47
-
48
- expect(effectCount).toBe(1)
49
-
50
- // Changing the value should trigger the effect
51
- reactiveWeakMap.set(key, 'new value')
52
- expect(effectCount).toBe(2)
53
- })
54
-
55
- it('should track dependencies when checking existence', () => {
56
- const weakMap = new WeakMap<object, string>()
57
- const reactiveWeakMap = reactive(weakMap)
58
- const key = { id: 1 }
59
- reactiveWeakMap.set(key, 'test')
60
-
61
- let effectCount = 0
62
- effect(() => {
63
- effectCount++
64
- reactiveWeakMap.has(key)
65
- })
66
-
67
- expect(effectCount).toBe(1)
68
-
69
- // Deleting the key should trigger the effect
70
- reactiveWeakMap.delete(key)
71
- expect(effectCount).toBe(2)
72
- })
73
-
74
- it('should trigger effects when setting new values', () => {
75
- const weakMap = new WeakMap<object, string>()
76
- const reactiveWeakMap = reactive(weakMap)
77
- const key = { id: 1 }
78
-
79
- let effectCount = 0
80
- effect(() => {
81
- effectCount++
82
- reactiveWeakMap.get(key)
83
- })
84
-
85
- expect(effectCount).toBe(1)
86
-
87
- // Setting a new value should trigger the effect
88
- reactiveWeakMap.set(key, 'new value')
89
- expect(effectCount).toBe(2)
90
- })
91
-
92
- it('should trigger effects when updating existing values', () => {
93
- const weakMap = new WeakMap<object, string>()
94
- const reactiveWeakMap = reactive(weakMap)
95
- const key = { id: 1 }
96
- reactiveWeakMap.set(key, 'old value')
97
-
98
- let effectCount = 0
99
- effect(() => {
100
- effectCount++
101
- reactiveWeakMap.get(key)
102
- })
103
-
104
- expect(effectCount).toBe(1)
105
-
106
- // Updating the value should trigger the effect
107
- reactiveWeakMap.set(key, 'new value')
108
- expect(effectCount).toBe(2)
109
- })
110
-
111
- it('should trigger effects when deleting keys', () => {
112
- const weakMap = new WeakMap<object, string>()
113
- const reactiveWeakMap = reactive(weakMap)
114
- const key = { id: 1 }
115
- reactiveWeakMap.set(key, 'test')
116
-
117
- let effectCount = 0
118
- effect(() => {
119
- effectCount++
120
- reactiveWeakMap.has(key)
121
- })
122
-
123
- expect(effectCount).toBe(1)
124
-
125
- // Deleting the key should trigger the effect
126
- reactiveWeakMap.delete(key)
127
- expect(effectCount).toBe(2)
128
- })
129
-
130
- it('should not trigger effects when deleting non-existent keys', () => {
131
- const weakMap = new WeakMap<object, string>()
132
- const reactiveWeakMap = reactive(weakMap)
133
- const key = { id: 1 }
134
-
135
- let effectCount = 0
136
- effect(() => {
137
- effectCount++
138
- reactiveWeakMap.has(key)
139
- })
140
-
141
- expect(effectCount).toBe(1)
142
-
143
- // Deleting a non-existent key should not trigger the effect
144
- reactiveWeakMap.delete(key)
145
- expect(effectCount).toBe(1)
146
- })
147
- })
148
-
149
- describe('allProps reactivity', () => {
150
- it('should trigger allProps effects when setting values', () => {
151
- const weakMap = new WeakMap<object, string>()
152
- const reactiveWeakMap = reactive(weakMap)
153
- const key1 = { id: 1 }
154
- const key2 = { id: 2 }
155
-
156
- let allPropsEffectCount = 0
157
- effect(() => {
158
- allPropsEffectCount++
159
- // Access allProps by using a method that iterates
160
- reactiveWeakMap.has(key1)
161
- reactiveWeakMap.has(key2)
162
- })
163
-
164
- expect(allPropsEffectCount).toBe(1)
165
-
166
- // Setting a new value should trigger allProps effects
167
- reactiveWeakMap.set(key1, 'value1')
168
- expect(allPropsEffectCount).toBe(2)
169
-
170
- // Setting another value should trigger allProps effects
171
- reactiveWeakMap.set(key2, 'value2')
172
- expect(allPropsEffectCount).toBe(3)
173
- })
174
-
175
- it('should trigger allProps effects when deleting values', () => {
176
- const weakMap = new WeakMap<object, string>()
177
- const reactiveWeakMap = reactive(weakMap)
178
- const key1 = { id: 1 }
179
- const key2 = { id: 2 }
180
-
181
- reactiveWeakMap.set(key1, 'value1')
182
- reactiveWeakMap.set(key2, 'value2')
183
-
184
- let allPropsEffectCount = 0
185
- effect(() => {
186
- allPropsEffectCount++
187
- // Access allProps by using a method that iterates
188
- reactiveWeakMap.has(key1)
189
- reactiveWeakMap.has(key2)
190
- })
191
-
192
- expect(allPropsEffectCount).toBe(1)
193
-
194
- // Deleting a value should trigger allProps effects
195
- reactiveWeakMap.delete(key1)
196
- expect(allPropsEffectCount).toBe(2)
197
-
198
- // Deleting another value should trigger allProps effects
199
- reactiveWeakMap.delete(key2)
200
- expect(allPropsEffectCount).toBe(3)
201
- })
202
- })
203
-
204
- describe('WeakMap constraints', () => {
205
- it('should only accept objects as keys', () => {
206
- const weakMap = new WeakMap<object, string>()
207
- const reactiveWeakMap = reactive(weakMap)
208
-
209
- // These should work
210
- const objKey = { id: 1 }
211
- const arrKey = [1, 2, 3]
212
- const funcKey = () => {}
213
-
214
- reactiveWeakMap.set(objKey, 'obj value')
215
- reactiveWeakMap.set(arrKey, 'arr value')
216
- reactiveWeakMap.set(funcKey, 'func value')
217
-
218
- expect(reactiveWeakMap.get(objKey)).toBe('obj value')
219
- expect(reactiveWeakMap.get(arrKey)).toBe('arr value')
220
- expect(reactiveWeakMap.get(funcKey)).toBe('func value')
221
- })
222
-
223
- it('should not have size property', () => {
224
- const weakMap = new WeakMap<object, string>()
225
- const reactiveWeakMap = reactive(weakMap)
226
-
227
- // WeakMap should not have a size property
228
- expect('size' in reactiveWeakMap).toBe(false)
229
- expect((reactiveWeakMap as any).size).toBeUndefined()
230
- })
231
-
232
- it('should not have clear method', () => {
233
- const weakMap = new WeakMap<object, string>()
234
- const reactiveWeakMap = reactive(weakMap)
235
-
236
- // WeakMap should not have a clear method
237
- expect(typeof (reactiveWeakMap as any).clear).toBe('undefined')
238
- })
239
- })
240
-
241
- describe('toStringTag', () => {
242
- it('should have correct toStringTag', () => {
243
- const weakMap = new WeakMap<object, string>()
244
- const reactiveWeakMap = reactive(weakMap)
245
- expect(reactiveWeakMap[Symbol.toStringTag]).toBe('ReactiveWeakMap')
246
- })
247
- })
248
- })
249
-
250
- describe('ReactiveMap', () => {
251
- describe('basic functionality', () => {
252
- it('should create a reactive Map wrapper', () => {
253
- const map = new Map<string, number>()
254
- const reactiveMap = reactive(map)
255
- expect(reactiveMap).toBeInstanceOf(Object)
256
- // ReactiveMap is a wrapper, not a native Map instance
257
- expect(reactiveMap).toBeInstanceOf(Map)
258
- })
259
-
260
- it('should work with reactive() function', () => {
261
- const map = new Map<string, number>()
262
- const reactiveMap = reactive(map)
263
-
264
- // The reactive wrapper should behave like a Map
265
- expect(reactiveMap).toBeInstanceOf(Map)
266
- })
267
-
268
- it('should wrap existing Map with entries', () => {
269
- const originalMap = new Map<string, number>([
270
- ['key1', 1],
271
- ['key2', 2],
272
- ])
273
- const reactiveMap = reactive(originalMap)
274
-
275
- expect(reactiveMap.get('key1')).toBe(1)
276
- expect(reactiveMap.get('key2')).toBe(2)
277
- expect(reactiveMap.size).toBe(2)
278
- })
279
-
280
- it('should accept Map instance', () => {
281
- const originalMap = new Map([
282
- ['key1', 1],
283
- ['key2', 2],
284
- ])
285
- const reactiveMap = reactive(originalMap)
286
-
287
- expect(reactiveMap.get('key1')).toBe(1)
288
- expect(reactiveMap.get('key2')).toBe(2)
289
- expect(reactiveMap.size).toBe(2)
290
- })
291
- })
292
-
293
- describe('reactive operations', () => {
294
- it('should track size dependencies', () => {
295
- const map = new Map<string, number>()
296
- const reactiveMap = reactive(map)
297
-
298
- let effectCount = 0
299
- effect(() => {
300
- effectCount++
301
- reactiveMap.size
302
- })
303
-
304
- expect(effectCount).toBe(1)
305
-
306
- // Adding a key should trigger the effect
307
- reactiveMap.set('test', 42)
308
- expect(effectCount).toBe(2)
309
- })
310
-
311
- it('should track dependencies when getting values', () => {
312
- const map = new Map<string, number>()
313
- const reactiveMap = reactive(map)
314
- reactiveMap.set('test', 42)
315
-
316
- let effectCount = 0
317
- effect(() => {
318
- effectCount++
319
- reactiveMap.get('test')
320
- })
321
-
322
- expect(effectCount).toBe(1)
323
-
324
- // Changing the value should trigger the effect
325
- reactiveMap.set('test', 100)
326
- expect(effectCount).toBe(2)
327
- })
328
-
329
- it('should track dependencies when checking existence', () => {
330
- const map = new Map<string, number>()
331
- const reactiveMap = reactive(map)
332
- reactiveMap.set('test', 42)
333
-
334
- let effectCount = 0
335
- effect(() => {
336
- effectCount++
337
- reactiveMap.has('test')
338
- })
339
-
340
- expect(effectCount).toBe(1)
341
-
342
- // Deleting the key should trigger the effect
343
- reactiveMap.delete('test')
344
- expect(effectCount).toBe(2)
345
- })
346
-
347
- it('should trigger effects when setting new values', () => {
348
- const map = new Map<string, number>()
349
- const reactiveMap = reactive(map)
350
-
351
- let effectCount = 0
352
- effect(() => {
353
- effectCount++
354
- reactiveMap.get('test')
355
- })
356
-
357
- expect(effectCount).toBe(1)
358
-
359
- // Setting a new value should trigger the effect
360
- reactiveMap.set('test', 42)
361
- expect(effectCount).toBe(2)
362
- })
363
-
364
- it('should trigger effects when updating existing values', () => {
365
- const map = new Map<string, number>()
366
- const reactiveMap = reactive(map)
367
- reactiveMap.set('test', 42)
368
-
369
- let effectCount = 0
370
- effect(() => {
371
- effectCount++
372
- reactiveMap.get('test')
373
- })
374
-
375
- expect(effectCount).toBe(1)
376
-
377
- // Updating the value should trigger the effect
378
- reactiveMap.set('test', 100)
379
- expect(effectCount).toBe(2)
380
- })
381
-
382
- it('should trigger effects when deleting keys', () => {
383
- const map = new Map<string, number>()
384
- const reactiveMap = reactive(map)
385
- reactiveMap.set('test', 42)
386
-
387
- let effectCount = 0
388
- effect(() => {
389
- effectCount++
390
- reactiveMap.has('test')
391
- })
392
-
393
- expect(effectCount).toBe(1)
394
-
395
- // Deleting the key should trigger the effect
396
- reactiveMap.delete('test')
397
- expect(effectCount).toBe(2)
398
- })
399
-
400
- it('should not trigger effects when deleting non-existent keys', () => {
401
- const map = new Map<string, number>()
402
- const reactiveMap = reactive(map)
403
-
404
- let effectCount = 0
405
- effect(() => {
406
- effectCount++
407
- reactiveMap.has('test')
408
- })
409
-
410
- expect(effectCount).toBe(1)
411
-
412
- // Deleting a non-existent key should not trigger the effect
413
- reactiveMap.delete('test')
414
- expect(effectCount).toBe(1)
415
- })
416
- })
417
-
418
- describe('allProps reactivity', () => {
419
- it('should trigger allProps effects when setting values', () => {
420
- const map = new Map<string, number>()
421
- const reactiveMap = reactive(map)
422
-
423
- let allPropsEffectCount = 0
424
- effect(() => {
425
- allPropsEffectCount++
426
- // Access allProps by using iteration methods
427
- reactiveMap.entries()
428
- })
429
-
430
- expect(allPropsEffectCount).toBe(1)
431
-
432
- // Setting a new value should trigger allProps effects
433
- reactiveMap.set('key1', 1)
434
- expect(allPropsEffectCount).toBe(2)
435
-
436
- // Setting another value should trigger allProps effects
437
- reactiveMap.set('key2', 2)
438
- expect(allPropsEffectCount).toBe(3)
439
- })
440
-
441
- it('should trigger allProps effects when deleting values', () => {
442
- const map = new Map<string, number>()
443
- const reactiveMap = reactive(map)
444
- reactiveMap.set('key1', 1)
445
- reactiveMap.set('key2', 2)
446
-
447
- let allPropsEffectCount = 0
448
- effect(() => {
449
- allPropsEffectCount++
450
- // Access allProps by using iteration methods
451
- reactiveMap.keys()
452
- })
453
-
454
- expect(allPropsEffectCount).toBe(1)
455
-
456
- // Deleting a value should trigger allProps effects
457
- reactiveMap.delete('key1')
458
- expect(allPropsEffectCount).toBe(2)
459
-
460
- // Deleting another value should trigger allProps effects
461
- reactiveMap.delete('key2')
462
- expect(allPropsEffectCount).toBe(3)
463
- })
464
-
465
- it('should trigger allProps effects when clearing', () => {
466
- const map = new Map<string, number>()
467
- const reactiveMap = reactive(map)
468
- reactiveMap.set('key1', 1)
469
- reactiveMap.set('key2', 2)
470
-
471
- let allPropsEffectCount = 0
472
- effect(() => {
473
- allPropsEffectCount++
474
- // Access allProps by using iteration methods
475
- reactiveMap.values()
476
- })
477
-
478
- expect(allPropsEffectCount).toBe(1)
479
-
480
- // Clearing should trigger allProps effects
481
- reactiveMap.clear()
482
- expect(allPropsEffectCount).toBe(2)
483
- })
484
- })
485
-
486
- describe('iteration methods', () => {
487
- it('should track allProps for entries()', () => {
488
- const map = new Map<string, number>()
489
- const reactiveMap = reactive(map)
490
-
491
- let effectCount = 0
492
- effect(() => {
493
- effectCount++
494
- reactiveMap.entries()
495
- })
496
-
497
- expect(effectCount).toBe(1)
498
-
499
- // Any map change should trigger the effect
500
- reactiveMap.set('test', 42)
501
- expect(effectCount).toBe(2)
502
- })
503
-
504
- it('should track allProps for forEach()', () => {
505
- const map = new Map<string, number>()
506
- const reactiveMap = reactive(map)
507
-
508
- let effectCount = 0
509
- effect(() => {
510
- effectCount++
511
- reactiveMap.forEach(() => {})
512
- })
513
-
514
- expect(effectCount).toBe(1)
515
-
516
- // Any map change should trigger the effect
517
- reactiveMap.set('test', 42)
518
- expect(effectCount).toBe(2)
519
- })
520
-
521
- it('should track allProps for keys()', () => {
522
- const map = new Map<string, number>()
523
- const reactiveMap = reactive(map)
524
-
525
- let effectCount = 0
526
- effect(() => {
527
- effectCount++
528
- reactiveMap.keys()
529
- })
530
-
531
- expect(effectCount).toBe(1)
532
-
533
- // Any map change should trigger the effect
534
- reactiveMap.set('test', 42)
535
- expect(effectCount).toBe(2)
536
- })
537
-
538
- it('should track allProps for values()', () => {
539
- const map = new Map<string, number>()
540
- const reactiveMap = reactive(map)
541
-
542
- let effectCount = 0
543
- effect(() => {
544
- effectCount++
545
- reactiveMap.values()
546
- })
547
-
548
- expect(effectCount).toBe(1)
549
-
550
- // Any map change should trigger the effect
551
- reactiveMap.set('test', 42)
552
- expect(effectCount).toBe(2)
553
- })
554
-
555
- it('should track allProps for Symbol.iterator', () => {
556
- const map = new Map<string, number>()
557
- const reactiveMap = reactive(map)
558
-
559
- let effectCount = 0
560
- effect(() => {
561
- effectCount++
562
- for (const [_key, _value] of reactiveMap) {
563
- // Just iterate to trigger allProps dependency
564
- }
565
- })
566
-
567
- expect(effectCount).toBe(1)
568
-
569
- // Any map change should trigger the effect
570
- reactiveMap.set('test', 42)
571
- expect(effectCount).toBe(2)
572
- })
573
- })
574
-
575
- describe('clear method', () => {
576
- it('should trigger size and allProps effects when clearing', () => {
577
- const map = new Map<string, number>()
578
- const reactiveMap = reactive(map)
579
- reactiveMap.set('key1', 1)
580
- reactiveMap.set('key2', 2)
581
-
582
- let sizeEffectCount = 0
583
- let allPropsEffectCount = 0
584
-
585
- effect(() => {
586
- sizeEffectCount++
587
- reactiveMap.size
588
- })
589
-
590
- effect(() => {
591
- allPropsEffectCount++
592
- reactiveMap.entries()
593
- })
594
-
595
- expect(sizeEffectCount).toBe(1)
596
- expect(allPropsEffectCount).toBe(1)
597
-
598
- // Clearing should trigger both effects
599
- reactiveMap.clear()
600
- expect(sizeEffectCount).toBe(2)
601
- expect(allPropsEffectCount).toBe(2)
602
- })
603
-
604
- it('should not trigger effects when clearing empty map', () => {
605
- const map = new Map<string, number>()
606
- const reactiveMap = reactive(map)
607
-
608
- let sizeEffectCount = 0
609
- let allPropsEffectCount = 0
610
-
611
- effect(() => {
612
- sizeEffectCount++
613
- reactiveMap.size
614
- })
615
-
616
- effect(() => {
617
- allPropsEffectCount++
618
- reactiveMap.entries()
619
- })
620
-
621
- expect(sizeEffectCount).toBe(1)
622
- expect(allPropsEffectCount).toBe(1)
623
-
624
- // Clearing empty map should not trigger effects
625
- reactiveMap.clear()
626
- expect(sizeEffectCount).toBe(1)
627
- expect(allPropsEffectCount).toBe(1)
628
- })
629
- })
630
-
631
- describe('static methods', () => {
632
- it('should create ReactiveMap from existing Map', () => {
633
- const originalMap = new Map([
634
- ['key1', 1],
635
- ['key2', 2],
636
- ])
637
- const reactiveMap = reactive(originalMap)
638
- expect(reactiveMap.size).toBe(2)
639
- expect(reactiveMap.get('key1')).toBe(1)
640
- expect(reactiveMap.get('key2')).toBe(2)
641
- })
642
-
643
- it('should work with reactive() function on existing Map', () => {
644
- const originalMap = new Map([
645
- ['key1', 1],
646
- ['key2', 2],
647
- ])
648
- const reactiveMap = reactive(originalMap)
649
- expect(reactiveMap.size).toBe(2)
650
- expect(reactiveMap.get('key1')).toBe(1)
651
- expect(reactiveMap.get('key2')).toBe(2)
652
- })
653
- })
654
-
655
- describe('toStringTag', () => {
656
- it('should have correct toStringTag', () => {
657
- const map = new Map<string, number>()
658
- const reactiveMap = reactive(map)
659
- expect(reactiveMap[Symbol.toStringTag]).toBe('ReactiveMap')
660
- })
661
- })
662
-
663
- describe('seamless reactive integration', () => {
664
- describe('native Map integration', () => {
665
- it('should automatically create ReactiveMap when using reactive() on native Map', () => {
666
- const nativeMap = new Map([
667
- ['key1', 1],
668
- ['key2', 2],
669
- ])
670
- const reactiveMap = reactive(nativeMap)
671
-
672
- // Should still behave like a Map
673
- expect(reactiveMap.get('key1')).toBe(1)
674
- expect(reactiveMap.get('key2')).toBe(2)
675
- expect(reactiveMap.size).toBe(2)
676
- })
677
-
678
- it('should track dependencies when accessing reactive native Map', () => {
679
- const nativeMap = new Map([['key1', 1]])
680
- const reactiveMap = reactive(nativeMap)
681
-
682
- let effectCount = 0
683
- effect(() => {
684
- effectCount++
685
- reactiveMap.get('key1')
686
- })
687
-
688
- expect(effectCount).toBe(1)
689
-
690
- // Modifying the reactive map should trigger effects
691
- reactiveMap.set('key1', 100)
692
- expect(effectCount).toBe(2)
693
- })
694
-
695
- it('should track size dependencies on reactive native Map', () => {
696
- const nativeMap = new Map([['key1', 1]])
697
- const reactiveMap = reactive(nativeMap)
698
-
699
- let effectCount = 0
700
- effect(() => {
701
- effectCount++
702
- reactiveMap.size
703
- })
704
-
705
- expect(effectCount).toBe(1)
706
-
707
- // Adding a key should trigger size effect
708
- reactiveMap.set('key2', 2)
709
- expect(effectCount).toBe(2)
710
- })
711
-
712
- it('should track allProps dependencies on reactive native Map', () => {
713
- const nativeMap = new Map([['key1', 1]])
714
- const reactiveMap = reactive(nativeMap)
715
-
716
- let effectCount = 0
717
- effect(() => {
718
- effectCount++
719
- reactiveMap.entries()
720
- })
721
-
722
- expect(effectCount).toBe(1)
723
-
724
- // Any map change should trigger allProps effect
725
- reactiveMap.set('key2', 2)
726
- expect(effectCount).toBe(2)
727
- })
728
-
729
- it('should handle clear operations on reactive native Map', () => {
730
- const nativeMap = new Map([
731
- ['key1', 1],
732
- ['key2', 2],
733
- ])
734
- const reactiveMap = reactive(nativeMap)
735
-
736
- let sizeEffectCount = 0
737
- let allPropsEffectCount = 0
738
-
739
- effect(() => {
740
- sizeEffectCount++
741
- reactiveMap.size
742
- })
743
-
744
- effect(() => {
745
- allPropsEffectCount++
746
- reactiveMap.keys()
747
- })
748
-
749
- expect(sizeEffectCount).toBe(1)
750
- expect(allPropsEffectCount).toBe(1)
751
-
752
- // Clearing should trigger both effects
753
- reactiveMap.clear()
754
- expect(sizeEffectCount).toBe(2)
755
- expect(allPropsEffectCount).toBe(2)
756
- })
757
- })
758
-
759
- describe('native WeakMap integration', () => {
760
- it('should automatically create ReactiveWeakMap when using reactive() on native WeakMap', () => {
761
- const key1 = { id: 1 }
762
- const key2 = { id: 2 }
763
- const nativeWeakMap = new WeakMap([
764
- [key1, 'value1'],
765
- [key2, 'value2'],
766
- ])
767
- const reactiveWeakMap = reactive(nativeWeakMap)
768
- // Should still behave like a WeakMap
769
- expect(reactiveWeakMap.get(key1)).toBe('value1')
770
- expect(reactiveWeakMap.get(key2)).toBe('value2')
771
- })
772
-
773
- it('should track dependencies when accessing reactive native WeakMap', () => {
774
- const key = { id: 1 }
775
- const nativeWeakMap = new WeakMap([[key, 'value']])
776
- const reactiveWeakMap = reactive(nativeWeakMap)
777
-
778
- let effectCount = 0
779
- effect(() => {
780
- effectCount++
781
- reactiveWeakMap.get(key)
782
- })
783
-
784
- expect(effectCount).toBe(1)
785
-
786
- // Modifying the reactive weak map should trigger effects
787
- reactiveWeakMap.set(key, 'new value')
788
- expect(effectCount).toBe(2)
789
- })
790
-
791
- it('should handle delete operations on reactive native WeakMap', () => {
792
- const key = { id: 1 }
793
- const nativeWeakMap = new WeakMap([[key, 'value']])
794
- const reactiveWeakMap = reactive(nativeWeakMap)
795
-
796
- let effectCount = 0
797
- effect(() => {
798
- effectCount++
799
- reactiveWeakMap.has(key)
800
- })
801
-
802
- expect(effectCount).toBe(1)
803
-
804
- // Deleting the key should trigger effects
805
- reactiveWeakMap.delete(key)
806
- expect(effectCount).toBe(2)
807
- })
808
- })
809
-
810
- describe('mixed usage scenarios', () => {
811
- it('should work with both reactive Map and WeakMap in same effect', () => {
812
- const nativeMap = new Map([['key1', 1]])
813
- const key = { id: 1 }
814
- const nativeWeakMap = new WeakMap([[key, 'value']])
815
-
816
- const reactiveMap = reactive(nativeMap)
817
- const reactiveWeakMap = reactive(nativeWeakMap)
818
-
819
- let effectCount = 0
820
- effect(() => {
821
- effectCount++
822
- reactiveMap.get('key1')
823
- reactiveWeakMap.get(key)
824
- })
825
-
826
- expect(effectCount).toBe(1)
827
-
828
- // Modifying either should trigger the effect
829
- reactiveMap.set('key1', 100)
830
- expect(effectCount).toBe(2)
831
-
832
- reactiveWeakMap.set(key, 'new value')
833
- expect(effectCount).toBe(3)
834
- })
835
-
836
- it('should handle nested reactive structures', () => {
837
- const nativeMap = new Map([['config', { enabled: true }]])
838
- const reactiveMap = reactive(nativeMap)
839
-
840
- let effectCount = 0
841
- effect(() => {
842
- effectCount++
843
- const config = reactiveMap.get('config')
844
- if (config?.enabled) {
845
- // Access nested property
846
- }
847
- })
848
-
849
- expect(effectCount).toBe(1)
850
-
851
- // Modifying the map should trigger effects
852
- reactiveMap.set('config', { enabled: false })
853
- expect(effectCount).toBe(2)
854
- })
855
-
856
- it('should work with reactive() called multiple times', () => {
857
- const nativeMap = new Map([['key1', 1]])
858
- const reactiveMap1 = reactive(nativeMap)
859
- const reactiveMap2 = reactive(nativeMap)
860
-
861
- // Should return the same reactive instance
862
- expect(reactiveMap1).toBe(reactiveMap2)
863
- })
864
- })
865
- })
866
- })