@planet-matrix/mobius-model 0.1.4 → 0.3.0

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 (77) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +21 -0
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +2 -2
  6. package/dist/index.js.map +12 -6
  7. package/dist/reactor/index.d.ts +3 -0
  8. package/dist/reactor/index.d.ts.map +1 -0
  9. package/dist/reactor/reactor-core/flags.d.ts.map +1 -0
  10. package/dist/reactor/reactor-core/index.d.ts.map +1 -0
  11. package/dist/reactor/reactor-core/primitive.d.ts +276 -0
  12. package/dist/reactor/reactor-core/primitive.d.ts.map +1 -0
  13. package/dist/{signal/signal-core → reactor/reactor-core}/reactive-system.d.ts +102 -22
  14. package/dist/reactor/reactor-core/reactive-system.d.ts.map +1 -0
  15. package/dist/reactor/reactor-operators/branch.d.ts +19 -0
  16. package/dist/reactor/reactor-operators/branch.d.ts.map +1 -0
  17. package/dist/reactor/reactor-operators/convert.d.ts +30 -0
  18. package/dist/reactor/reactor-operators/convert.d.ts.map +1 -0
  19. package/dist/reactor/reactor-operators/create.d.ts +26 -0
  20. package/dist/reactor/reactor-operators/create.d.ts.map +1 -0
  21. package/dist/reactor/reactor-operators/filter.d.ts +269 -0
  22. package/dist/reactor/reactor-operators/filter.d.ts.map +1 -0
  23. package/dist/reactor/reactor-operators/index.d.ts +8 -0
  24. package/dist/reactor/reactor-operators/index.d.ts.map +1 -0
  25. package/dist/reactor/reactor-operators/join.d.ts +48 -0
  26. package/dist/reactor/reactor-operators/join.d.ts.map +1 -0
  27. package/dist/reactor/reactor-operators/map.d.ts +165 -0
  28. package/dist/reactor/reactor-operators/map.d.ts.map +1 -0
  29. package/dist/reactor/reactor-operators/utility.d.ts +48 -0
  30. package/dist/reactor/reactor-operators/utility.d.ts.map +1 -0
  31. package/package.json +9 -9
  32. package/src/index.ts +1 -1
  33. package/src/reactor/README.md +18 -0
  34. package/src/reactor/index.ts +2 -0
  35. package/src/reactor/reactor-core/primitive.ts +1046 -0
  36. package/src/{signal/signal-core → reactor/reactor-core}/reactive-system.ts +392 -93
  37. package/src/reactor/reactor-operators/branch.ts +66 -0
  38. package/src/reactor/reactor-operators/convert.ts +70 -0
  39. package/src/reactor/reactor-operators/create.ts +66 -0
  40. package/src/reactor/reactor-operators/filter.ts +988 -0
  41. package/src/reactor/reactor-operators/index.ts +7 -0
  42. package/src/reactor/reactor-operators/join.ts +174 -0
  43. package/src/reactor/reactor-operators/map.ts +599 -0
  44. package/src/reactor/reactor-operators/utility.ts +102 -0
  45. package/tests/unit/{signal/computed.spec.ts → reactor/alien-signals-computed.spec.ts} +15 -10
  46. package/tests/unit/reactor/alien-signals-effect-scope.spec.ts +86 -0
  47. package/tests/unit/reactor/alien-signals-effect.spec.ts +395 -0
  48. package/tests/unit/reactor/alien-signals-topology.spec.ts +361 -0
  49. package/tests/unit/reactor/alien-signals-trigger.spec.ts +75 -0
  50. package/tests/unit/reactor/alien-signals-untrack.spec.ts +91 -0
  51. package/tests/unit/reactor/preact-signal.spec.ts +73 -0
  52. package/tests/unit/reactor/reactor-core.spec.ts +219 -0
  53. package/tests/unit/reactor/reactor-operators-branch.spec.ts +33 -0
  54. package/tests/unit/reactor/reactor-operators-convert.spec.ts +31 -0
  55. package/tests/unit/reactor/reactor-operators-create.spec.ts +47 -0
  56. package/tests/unit/reactor/reactor-operators-filter.spec.ts +604 -0
  57. package/tests/unit/reactor/reactor-operators-join.spec.ts +94 -0
  58. package/tests/unit/reactor/reactor-operators-map.spec.ts +327 -0
  59. package/tests/unit/reactor/reactor-operators-utility.spec.ts +55 -0
  60. package/dist/signal/index.d.ts +0 -3
  61. package/dist/signal/index.d.ts.map +0 -1
  62. package/dist/signal/signal-core/flags.d.ts.map +0 -1
  63. package/dist/signal/signal-core/index.d.ts.map +0 -1
  64. package/dist/signal/signal-core/primitive.d.ts +0 -67
  65. package/dist/signal/signal-core/primitive.d.ts.map +0 -1
  66. package/dist/signal/signal-core/reactive-system.d.ts.map +0 -1
  67. package/dist/signal/signal-operators/index.d.ts +0 -4
  68. package/dist/signal/signal-operators/index.d.ts.map +0 -1
  69. package/src/signal/index.ts +0 -2
  70. package/src/signal/signal-core/README.md +0 -4
  71. package/src/signal/signal-core/primitive.ts +0 -275
  72. package/src/signal/signal-operators/index.ts +0 -19
  73. package/tests/unit/signal/effect.spec.ts +0 -108
  74. /package/dist/{signal/signal-core → reactor/reactor-core}/flags.d.ts +0 -0
  75. /package/dist/{signal/signal-core → reactor/reactor-core}/index.d.ts +0 -0
  76. /package/src/{signal/signal-core → reactor/reactor-core}/flags.ts +0 -0
  77. /package/src/{signal/signal-core → reactor/reactor-core}/index.ts +0 -0
@@ -0,0 +1,604 @@
1
+ import { expect, test } from 'vitest';
2
+
3
+ import type { Signal } from '#Source/reactor/index.ts';
4
+ import {
5
+ auditByCount, auditByDynamic, auditByTime, auditByToggle, auditByTrigger,
6
+ current, debounceByCount, debounceByDynamic, debounceByTime, debounceByToggle,
7
+ debounceByTrigger, distinct,
8
+ distinctUntilChanged, filter, interval, next, signal,
9
+ takeByCount, takeByPredicate, takeByTime, takeByToggle, takeByTrigger, takeUntilTrigger,
10
+ throttleByCount, throttleByDynamic, throttleByTime, throttleByToggle, throttleByTrigger
11
+ } from '#Source/reactor/index.ts';
12
+
13
+ test("current operator should work correctly", () => {
14
+ const a = signal(() => 0);
15
+
16
+ const currentA = current({ target: a });
17
+ expect(currentA.get()).toBe(0);
18
+
19
+ a.set(1);
20
+ expect(currentA.get()).toBe(0);
21
+
22
+ a.set(2);
23
+ expect(currentA.get()).toBe(0);
24
+ });
25
+
26
+ test("next operator should get next value after initial", () => {
27
+ const a = signal(() => 0);
28
+
29
+ const nextA = next({ target: a, valueInitializer: () => -1 });
30
+ expect(nextA.get()).toBe(-1);
31
+
32
+ a.set(1);
33
+ expect(nextA.get()).toBe(1);
34
+
35
+ a.set(2);
36
+ expect(nextA.get()).toBe(1);
37
+ });
38
+
39
+ test("filter operator should work correctly", () => {
40
+ const source = signal(() => 1);
41
+ const filtered = filter({
42
+ target: source,
43
+ truthyPredicate: (value) => value % 2 === 0,
44
+ falsyValueGetter: (context) => {
45
+ if (context.isInitializingRun) {
46
+ return 0
47
+ } else {
48
+ return context.previousValue
49
+ }
50
+ }
51
+ });
52
+
53
+ expect(filtered.get()).toBe(0);
54
+
55
+ source.set(2);
56
+ expect(filtered.get()).toBe(2);
57
+
58
+ source.set(3);
59
+ expect(filtered.get()).toBe(2);
60
+
61
+ source.set(4);
62
+ expect(filtered.get()).toBe(4);
63
+ });
64
+
65
+ test("auditByCount operator should work correctly", () => {
66
+ const source = signal(() => 0);
67
+ const audited = auditByCount({ target: source, count: 3 });
68
+
69
+ expect(audited.get()).toBe(0);
70
+
71
+ source.set(1);
72
+ expect(audited.get()).toBe(0);
73
+
74
+ source.set(2);
75
+ expect(audited.get()).toBe(0);
76
+
77
+ source.set(3);
78
+ expect(audited.get()).toBe(3);
79
+
80
+ source.set(4);
81
+ source.set(5);
82
+ source.set(6);
83
+ expect(audited.get()).toBe(6);
84
+ });
85
+
86
+ test("auditByTime operator should work correctly", async () => {
87
+ const source = signal(() => 1);
88
+ const audited = auditByTime({ target: source, time: 100 });
89
+
90
+ expect(audited.get()).toBe(1);
91
+
92
+ source.set(2);
93
+ source.set(3);
94
+ expect(audited.get()).toBe(1);
95
+
96
+ await new Promise((resolve) => {
97
+ setTimeout(resolve, 120);
98
+ });
99
+ expect(audited.get()).toBe(3);
100
+
101
+ source.set(4);
102
+ source.set(5);
103
+ source.set(6);
104
+ expect(audited.get()).toBe(3);
105
+
106
+ await new Promise((resolve) => {
107
+ setTimeout(resolve, 110);
108
+ });
109
+ expect(audited.get()).toBe(6);
110
+ });
111
+
112
+ test("auditByTrigger operator should work correctly", () => {
113
+ const source = signal(() => 1);
114
+ const trigger = signal(() => 0);
115
+ const audited = auditByTrigger({ target: source, trigger });
116
+
117
+ expect(audited.get()).toBe(1);
118
+
119
+ source.set(2);
120
+ source.set(3);
121
+ expect(audited.get()).toBe(1);
122
+
123
+ trigger.set(1);
124
+ expect(audited.get()).toBe(3);
125
+
126
+ source.set(4);
127
+ source.set(5);
128
+ expect(audited.get()).toBe(3);
129
+
130
+ trigger.set(2);
131
+ expect(audited.get()).toBe(5);
132
+ });
133
+
134
+ test("auditByToggle operator should work correctly", () => {
135
+ const source = signal(() => 1);
136
+ const open = signal(() => []);
137
+ const close = signal(() => []);
138
+ const audited = auditByToggle({ target: source, open, close });
139
+
140
+ expect(audited.get()).toBe(1);
141
+
142
+ source.set(2);
143
+ expect(audited.get()).toBe(1);
144
+
145
+ open.set([]);
146
+ source.set(3);
147
+ source.set(4);
148
+ expect(audited.get()).toBe(1);
149
+
150
+ close.set([]);
151
+ expect(audited.get()).toBe(4);
152
+
153
+ source.set(5);
154
+ expect(audited.get()).toBe(4);
155
+
156
+ open.set([]);
157
+ source.set(6);
158
+ source.set(7);
159
+ expect(audited.get()).toBe(4);
160
+
161
+ close.set([]);
162
+ expect(audited.get()).toBe(7);
163
+ });
164
+
165
+ test("auditByDynamic operator should work correctly", async () => {
166
+ const source = signal(() => 1);
167
+ const dynamic = (): Signal<number> => interval({ interval: 100 });
168
+ const audited = auditByDynamic({ target: source, dynamic });
169
+
170
+ expect(audited.get()).toBe(1);
171
+
172
+ source.set(2);
173
+ source.set(3);
174
+ expect(audited.get()).toBe(1);
175
+
176
+ await new Promise((resolve) => {
177
+ setTimeout(resolve, 120);
178
+ });
179
+ expect(audited.get()).toBe(3);
180
+
181
+ source.set(4);
182
+ source.set(5);
183
+ source.set(6);
184
+ expect(audited.get()).toBe(3);
185
+
186
+ await new Promise((resolve) => {
187
+ setTimeout(resolve, 110);
188
+ });
189
+ expect(audited.get()).toBe(6);
190
+ });
191
+
192
+ test("debounceByCount operator should work correctly", () => {
193
+ const source = signal(() => 0);
194
+ const debounced = debounceByCount({ target: source, count: 3 });
195
+
196
+ expect(debounced.get()).toBe(0);
197
+
198
+ source.set(1);
199
+ expect(debounced.get()).toBe(0);
200
+
201
+ source.set(2);
202
+ expect(debounced.get()).toBe(0);
203
+
204
+ source.set(3);
205
+ expect(debounced.get()).toBe(3);
206
+
207
+ source.set(4);
208
+ source.set(5);
209
+ source.set(6);
210
+ expect(debounced.get()).toBe(6);
211
+ });
212
+
213
+ test("debounceByTime operator should work correctly", async () => {
214
+ const source = signal(() => 1);
215
+ const debounced = debounceByTime({ target: source, time: 100 });
216
+
217
+ expect(debounced.get()).toBe(1);
218
+
219
+ source.set(2);
220
+ source.set(3);
221
+ expect(debounced.get()).toBe(1);
222
+
223
+ await new Promise((resolve) => {
224
+ setTimeout(resolve, 120);
225
+ });
226
+ expect(debounced.get()).toBe(3);
227
+
228
+ source.set(4);
229
+ source.set(5);
230
+ source.set(6);
231
+ expect(debounced.get()).toBe(3);
232
+
233
+ await new Promise((resolve) => {
234
+ setTimeout(resolve, 110);
235
+ });
236
+ expect(debounced.get()).toBe(6);
237
+ });
238
+
239
+ test("debounceByTrigger operator should work correctly", () => {
240
+ const source = signal(() => 1);
241
+ const trigger = signal(() => 0);
242
+ const debounced = debounceByTrigger({ target: source, trigger });
243
+
244
+ expect(debounced.get()).toBe(1);
245
+
246
+ source.set(2);
247
+ source.set(3);
248
+ expect(debounced.get()).toBe(1);
249
+
250
+ trigger.set(1);
251
+ expect(debounced.get()).toBe(3);
252
+
253
+ source.set(4);
254
+ source.set(5);
255
+ expect(debounced.get()).toBe(3);
256
+
257
+ trigger.set(2);
258
+ expect(debounced.get()).toBe(5);
259
+ });
260
+
261
+ test("debounceByToggle operator should work correctly", () => {
262
+ const source = signal(() => 1);
263
+ const open = signal(() => []);
264
+ const close = signal(() => []);
265
+ const debounced = debounceByToggle({ target: source, open, close });
266
+
267
+ expect(debounced.get()).toBe(1);
268
+
269
+ source.set(2);
270
+ expect(debounced.get()).toBe(1);
271
+
272
+ open.set([]);
273
+ source.set(3);
274
+ source.set(4);
275
+ expect(debounced.get()).toBe(1);
276
+
277
+ close.set([]);
278
+ expect(debounced.get()).toBe(4);
279
+
280
+ source.set(5);
281
+ expect(debounced.get()).toBe(4);
282
+
283
+ open.set([]);
284
+ source.set(6);
285
+ source.set(7);
286
+ expect(debounced.get()).toBe(4);
287
+
288
+ close.set([]);
289
+ expect(debounced.get()).toBe(7);
290
+ });
291
+
292
+ test("debounceByDynamic operator should work correctly", async () => {
293
+ const source = signal(() => 1);
294
+ const dynamic = (): Signal<number> => interval({ interval: 100 });
295
+ const debounced = debounceByDynamic({ target: source, dynamic });
296
+
297
+ expect(debounced.get()).toBe(1);
298
+
299
+ source.set(2);
300
+ source.set(3);
301
+ expect(debounced.get()).toBe(1);
302
+
303
+ await new Promise((resolve) => {
304
+ setTimeout(resolve, 120);
305
+ });
306
+ expect(debounced.get()).toBe(3);
307
+
308
+ source.set(4);
309
+ source.set(5);
310
+ source.set(6);
311
+ expect(debounced.get()).toBe(3);
312
+
313
+ await new Promise((resolve) => {
314
+ setTimeout(resolve, 110);
315
+ });
316
+ expect(debounced.get()).toBe(6);
317
+ });
318
+
319
+ test("throttleByCount operator should work correctly", () => {
320
+ const source = signal(() => 0);
321
+ const throttled = throttleByCount({ target: source, count: 3 });
322
+
323
+ expect(throttled.get()).toBe(0);
324
+
325
+ source.set(1);
326
+ expect(throttled.get()).toBe(0);
327
+
328
+ source.set(2);
329
+ expect(throttled.get()).toBe(0);
330
+
331
+ source.set(3);
332
+ expect(throttled.get()).toBe(3);
333
+
334
+ source.set(4);
335
+ source.set(5);
336
+ source.set(6);
337
+ expect(throttled.get()).toBe(6);
338
+ });
339
+
340
+
341
+ test("throttleByTime operator should work correctly", async () => {
342
+ const source = signal(() => 1);
343
+ const throttled = throttleByTime({ target: source, time: 100 });
344
+
345
+ expect(throttled.get()).toBe(1);
346
+
347
+ source.set(2);
348
+ source.set(3);
349
+ expect(throttled.get()).toBe(1);
350
+
351
+ await new Promise((resolve) => {
352
+ setTimeout(resolve, 120);
353
+ });
354
+ expect(throttled.get()).toBe(1);
355
+
356
+ source.set(4);
357
+ source.set(5);
358
+ source.set(6);
359
+ expect(throttled.get()).toBe(4);
360
+
361
+ await new Promise((resolve) => {
362
+ setTimeout(resolve, 110);
363
+ });
364
+ source.set(7);
365
+ expect(throttled.get()).toBe(7);
366
+ });
367
+
368
+ test("throttleByTrigger operator should work correctly", () => {
369
+ const source = signal(() => 1);
370
+ const trigger = signal(() => 0);
371
+ const throttled = throttleByTrigger({ target: source, trigger });
372
+
373
+ expect(throttled.get()).toBe(1);
374
+
375
+ source.set(2);
376
+ source.set(3);
377
+ expect(throttled.get()).toBe(1);
378
+
379
+ trigger.set(1);
380
+ expect(throttled.get()).toBe(1);
381
+
382
+ source.set(4);
383
+ source.set(5);
384
+ expect(throttled.get()).toBe(4);
385
+
386
+ trigger.set(2);
387
+ expect(throttled.get()).toBe(4);
388
+ });
389
+
390
+ test("throttleByToggle operator should work correctly", () => {
391
+ const source = signal(() => 1);
392
+ const open = signal(() => []);
393
+ const close = signal(() => []);
394
+ const throttled = throttleByToggle({ target: source, open, close });
395
+
396
+ expect(throttled.get()).toBe(1);
397
+
398
+ source.set(2);
399
+ expect(throttled.get()).toBe(1);
400
+
401
+ open.set([]);
402
+ source.set(3);
403
+ source.set(4);
404
+ expect(throttled.get()).toBe(3);
405
+
406
+ close.set([]);
407
+ expect(throttled.get()).toBe(3);
408
+
409
+ source.set(5);
410
+ expect(throttled.get()).toBe(3);
411
+
412
+ open.set([]);
413
+ source.set(6);
414
+ source.set(7);
415
+ expect(throttled.get()).toBe(6);
416
+
417
+ close.set([]);
418
+ expect(throttled.get()).toBe(6);
419
+ });
420
+
421
+ test("throttleByDynamic operator should work correctly", async () => {
422
+ const source = signal(() => 1);
423
+ const dynamic = (): Signal<number> => interval({ interval: 100 });
424
+ const throttled = throttleByDynamic({ target: source, dynamic });
425
+
426
+ expect(throttled.get()).toBe(1);
427
+
428
+ source.set(2);
429
+ source.set(3);
430
+ expect(throttled.get()).toBe(1);
431
+
432
+ await new Promise((resolve) => {
433
+ setTimeout(resolve, 120);
434
+ });
435
+ expect(throttled.get()).toBe(1);
436
+
437
+ source.set(4);
438
+ source.set(5);
439
+ source.set(6);
440
+ expect(throttled.get()).toBe(4);
441
+
442
+ await new Promise((resolve) => {
443
+ setTimeout(resolve, 110);
444
+ });
445
+ expect(throttled.get()).toBe(4);
446
+
447
+ source.set(7);
448
+ expect(throttled.get()).toBe(7);
449
+ });
450
+
451
+ test("distinct operator should work correctly", () => {
452
+ const source = signal(() => 1);
453
+ const distinctSignal = distinct({ target: source });
454
+
455
+ expect(distinctSignal.get()).toBe(1);
456
+
457
+ source.set(1);
458
+ expect(distinctSignal.get()).toBe(1);
459
+
460
+ source.set(2);
461
+ expect(distinctSignal.get()).toBe(2);
462
+
463
+ source.set(2);
464
+ expect(distinctSignal.get()).toBe(2);
465
+
466
+ source.set(3);
467
+ expect(distinctSignal.get()).toBe(3);
468
+ });
469
+
470
+ test("distinctUntilChanged operator should work correctly", () => {
471
+ const source = signal(() => 1);
472
+ const distinctSignal = distinctUntilChanged({ target: source });
473
+
474
+ expect(distinctSignal.get()).toBe(1);
475
+
476
+ source.set(1);
477
+ expect(distinctSignal.get()).toBe(1);
478
+
479
+ source.set(2);
480
+ expect(distinctSignal.get()).toBe(2);
481
+
482
+ source.set(2);
483
+ expect(distinctSignal.get()).toBe(2);
484
+
485
+ source.set(3);
486
+ expect(distinctSignal.get()).toBe(3);
487
+ });
488
+
489
+ test("takeByPredicate operator should work correctly", () => {
490
+ const source = signal(() => 1);
491
+ const takeSignal = takeByPredicate({ target: source, predicate: (value) => value < 3 });
492
+
493
+ expect(takeSignal.get()).toBe(1);
494
+
495
+ source.set(2);
496
+ expect(takeSignal.get()).toBe(2);
497
+
498
+ source.set(3);
499
+ expect(takeSignal.get()).toBe(2);
500
+
501
+ source.set(4);
502
+ expect(takeSignal.get()).toBe(2);
503
+ });
504
+
505
+ test("takeByCount operator should work correctly", () => {
506
+ const source = signal(() => 1);
507
+ const takeSignal = takeByCount({ target: source, count: 3 });
508
+
509
+ expect(takeSignal.get()).toBe(1);
510
+
511
+ source.set(2);
512
+ expect(takeSignal.get()).toBe(2);
513
+
514
+ source.set(3);
515
+ expect(takeSignal.get()).toBe(3);
516
+
517
+ source.set(4);
518
+ expect(takeSignal.get()).toBe(3);
519
+ });
520
+
521
+ test("takeByTime operator should work correctly", async () => {
522
+ const source = signal(() => 1);
523
+ const takeSignal = takeByTime({ target: source, time: 200 });
524
+
525
+ expect(takeSignal.get()).toBe(1);
526
+
527
+ source.set(2);
528
+ expect(takeSignal.get()).toBe(2);
529
+
530
+ await new Promise((resolve) => {
531
+ setTimeout(resolve, 150);
532
+ });
533
+ source.set(3);
534
+ expect(takeSignal.get()).toBe(3);
535
+
536
+ await new Promise((resolve) => {
537
+ setTimeout(resolve, 100);
538
+ });
539
+ source.set(4);
540
+ expect(takeSignal.get()).toBe(3);
541
+ });
542
+
543
+ test("takeByTrigger operator should work correctly", () => {
544
+ const source = signal(() => 1);
545
+ const trigger = signal(() => 0);
546
+ const takeSignal = takeByTrigger({ target: source, trigger });
547
+
548
+ expect(takeSignal.get()).toBe(1);
549
+
550
+ source.set(2);
551
+ expect(takeSignal.get()).toBe(1);
552
+
553
+ trigger.set(1);
554
+ expect(takeSignal.get()).toBe(2);
555
+
556
+ source.set(3);
557
+ expect(takeSignal.get()).toBe(2);
558
+
559
+ trigger.set(2);
560
+ expect(takeSignal.get()).toBe(3);
561
+ });
562
+
563
+ test("takeByToggle operator should work correctly", () => {
564
+ const source = signal(() => 1);
565
+ const open = signal(() => []);
566
+ const close = signal(() => []);
567
+ const takeSignal = takeByToggle({ target: source, open, close });
568
+
569
+ expect(takeSignal.get()).toBe(1);
570
+
571
+ source.set(2);
572
+ expect(takeSignal.get()).toBe(1);
573
+
574
+ open.set([]);
575
+ source.set(3);
576
+ expect(takeSignal.get()).toBe(3);
577
+
578
+ close.set([]);
579
+ source.set(4);
580
+ expect(takeSignal.get()).toBe(3);
581
+
582
+ open.set([]);
583
+ source.set(5);
584
+ expect(takeSignal.get()).toBe(5);
585
+
586
+ close.set([]);
587
+ source.set(6);
588
+ expect(takeSignal.get()).toBe(5);
589
+ });
590
+
591
+ test("takeUntilTrigger operator should work correctly", () => {
592
+ const source = signal(() => 1);
593
+ const trigger = signal(() => 0);
594
+ const takeSignal = takeUntilTrigger({ target: source, trigger });
595
+
596
+ expect(takeSignal.get()).toBe(1);
597
+
598
+ source.set(2);
599
+ expect(takeSignal.get()).toBe(2);
600
+
601
+ trigger.set(1);
602
+ source.set(3);
603
+ expect(takeSignal.get()).toBe(2);
604
+ });
@@ -0,0 +1,94 @@
1
+ import { expect, test } from 'vitest';
2
+
3
+ import {
4
+ combineLatestArray, combineLatestObject,
5
+ computed, derived,
6
+ mergeArray,
7
+ signal,
8
+ withLatestFrom, zip
9
+ } from '#Source/reactor/index.ts';
10
+
11
+ test("combineLatestArray operator should work correctly", () => {
12
+ const a = signal(() => 1);
13
+ const b = signal(() => 2);
14
+ const c = derived(() => {
15
+ return a.get() * 2;
16
+ });
17
+ const d = computed(() => {
18
+ return a.get() + b.get() + c.get();
19
+ });
20
+ const combined = combineLatestArray({ target: [a, b, c, d] });
21
+
22
+ expect(combined.get()).toEqual([1, 2, 2, 5]);
23
+
24
+ a.set(3);
25
+ expect(combined.get()).toEqual([3, 2, 6, 11]);
26
+
27
+ b.set(4);
28
+ expect(combined.get()).toEqual([3, 4, 6, 13]);
29
+ });
30
+
31
+ test("combineLatestObject operator should work correctly", () => {
32
+ const a = signal(() => 1);
33
+ const b = signal(() => 2);
34
+ const c = derived(() => {
35
+ return a.get() * 2;
36
+ });
37
+ const d = computed(() => {
38
+ return a.get() + b.get() + c.get();
39
+ });
40
+ const combined = combineLatestObject({ target: { a, b, c, d } });
41
+
42
+ expect(combined.get()).toEqual({ a: 1, b: 2, c: 2, d: 5 });
43
+
44
+ a.set(3);
45
+ expect(combined.get()).toEqual({ a: 3, b: 2, c: 6, d: 11 });
46
+
47
+ b.set(4);
48
+ expect(combined.get()).toEqual({ a: 3, b: 4, c: 6, d: 13 });
49
+ });
50
+
51
+ test("mergeArray operator should work correctly", () => {
52
+ const a = signal(() => 1);
53
+ const b = signal(() => 2);
54
+ const c = mergeArray({ target: [a, b] });
55
+
56
+ expect(c.get()).toBe(2);
57
+
58
+ a.set(3);
59
+ expect(c.get()).toBe(3);
60
+
61
+ b.set(4);
62
+ expect(c.get()).toBe(4);
63
+ });
64
+
65
+ test("withLatestFrom operator should work correctly", () => {
66
+ const a = signal(() => 1);
67
+ const b = signal(() => 2);
68
+ const c = withLatestFrom({ target: a, other: b });
69
+
70
+ expect(c.get()).toEqual([1, 2]);
71
+
72
+ a.set(3);
73
+ expect(c.get()).toEqual([3, 2]);
74
+
75
+ b.set(4);
76
+ expect(c.get()).toEqual([3, 2]);
77
+
78
+ a.set(5);
79
+ expect(c.get()).toEqual([5, 4]);
80
+ });
81
+
82
+ test("zip operator should work correctly", () => {
83
+ const a = signal(() => 1);
84
+ const b = signal(() => 2);
85
+ const c = zip({ a: a, b: b });
86
+
87
+ expect(c.get()).toEqual([1, 2]);
88
+
89
+ a.set(3);
90
+ expect(c.get()).toEqual([1, 2]);
91
+
92
+ b.set(4);
93
+ expect(c.get()).toEqual([3, 4]);
94
+ });