@pyreon/reactivity 0.11.5 → 0.11.6
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/README.md +2 -2
- package/lib/index.js.map +1 -1
- package/package.json +10 -10
- package/src/computed.ts +5 -5
- package/src/createSelector.ts +2 -2
- package/src/debug.ts +8 -8
- package/src/effect.ts +4 -4
- package/src/index.ts +13 -13
- package/src/reconcile.ts +4 -4
- package/src/resource.ts +4 -4
- package/src/scope.ts +1 -1
- package/src/signal.ts +7 -7
- package/src/store.ts +9 -9
- package/src/tests/batch.test.ts +16 -16
- package/src/tests/bind.test.ts +8 -8
- package/src/tests/branches.test.ts +66 -66
- package/src/tests/cell.test.ts +22 -22
- package/src/tests/computed.test.ts +24 -24
- package/src/tests/createSelector.test.ts +17 -17
- package/src/tests/debug.test.ts +29 -29
- package/src/tests/effect.test.ts +59 -59
- package/src/tests/resource.test.ts +39 -39
- package/src/tests/scope.test.ts +20 -20
- package/src/tests/signal.test.ts +39 -39
- package/src/tests/store.test.ts +64 -64
- package/src/tests/tracking.test.ts +17 -17
- package/src/tests/watch.test.ts +32 -32
- package/src/tracking.ts +1 -1
- package/src/watch.ts +3 -3
package/src/tests/cell.test.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { Cell, cell } from
|
|
1
|
+
import { Cell, cell } from '../cell'
|
|
2
2
|
|
|
3
|
-
describe(
|
|
4
|
-
test(
|
|
3
|
+
describe('Cell', () => {
|
|
4
|
+
test('stores and reads initial value', () => {
|
|
5
5
|
const c = cell(42)
|
|
6
6
|
expect(c.peek()).toBe(42)
|
|
7
7
|
})
|
|
8
8
|
|
|
9
|
-
test(
|
|
10
|
-
const c = cell(
|
|
11
|
-
c.set(
|
|
12
|
-
expect(c.peek()).toBe(
|
|
9
|
+
test('set() updates value', () => {
|
|
10
|
+
const c = cell('hello')
|
|
11
|
+
c.set('world')
|
|
12
|
+
expect(c.peek()).toBe('world')
|
|
13
13
|
})
|
|
14
14
|
|
|
15
|
-
test(
|
|
15
|
+
test('set() skips when value is the same (Object.is)', () => {
|
|
16
16
|
const c = cell(1)
|
|
17
17
|
let calls = 0
|
|
18
18
|
c.listen(() => calls++)
|
|
@@ -20,23 +20,23 @@ describe("Cell", () => {
|
|
|
20
20
|
expect(calls).toBe(0)
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
-
test(
|
|
23
|
+
test('update() applies function to current value', () => {
|
|
24
24
|
const c = cell(10)
|
|
25
25
|
c.update((v) => v + 5)
|
|
26
26
|
expect(c.peek()).toBe(15)
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
test(
|
|
30
|
-
const c = cell(
|
|
29
|
+
test('listen() fires on set()', () => {
|
|
30
|
+
const c = cell('a')
|
|
31
31
|
let fired = false
|
|
32
32
|
c.listen(() => {
|
|
33
33
|
fired = true
|
|
34
34
|
})
|
|
35
|
-
c.set(
|
|
35
|
+
c.set('b')
|
|
36
36
|
expect(fired).toBe(true)
|
|
37
37
|
})
|
|
38
38
|
|
|
39
|
-
test(
|
|
39
|
+
test('listen() single-listener fast path (no Set allocated)', () => {
|
|
40
40
|
const c = cell(0)
|
|
41
41
|
let count = 0
|
|
42
42
|
c.listen(() => count++)
|
|
@@ -47,7 +47,7 @@ describe("Cell", () => {
|
|
|
47
47
|
expect(count).toBe(1)
|
|
48
48
|
})
|
|
49
49
|
|
|
50
|
-
test(
|
|
50
|
+
test('listen() promotes to Set with multiple listeners', () => {
|
|
51
51
|
const c = cell(0)
|
|
52
52
|
let a = 0
|
|
53
53
|
let b = 0
|
|
@@ -60,7 +60,7 @@ describe("Cell", () => {
|
|
|
60
60
|
expect(b).toBe(1)
|
|
61
61
|
})
|
|
62
62
|
|
|
63
|
-
test(
|
|
63
|
+
test('subscribe() returns working unsubscribe (single listener)', () => {
|
|
64
64
|
const c = cell(0)
|
|
65
65
|
let count = 0
|
|
66
66
|
const unsub = c.subscribe(() => count++)
|
|
@@ -71,7 +71,7 @@ describe("Cell", () => {
|
|
|
71
71
|
expect(count).toBe(1) // no more notifications
|
|
72
72
|
})
|
|
73
73
|
|
|
74
|
-
test(
|
|
74
|
+
test('subscribe() returns working unsubscribe (multi listener)', () => {
|
|
75
75
|
const c = cell(0)
|
|
76
76
|
let a = 0
|
|
77
77
|
let b = 0
|
|
@@ -86,12 +86,12 @@ describe("Cell", () => {
|
|
|
86
86
|
expect(b).toBe(1) // unsubscribed
|
|
87
87
|
})
|
|
88
88
|
|
|
89
|
-
test(
|
|
90
|
-
const c = cell(
|
|
89
|
+
test('cell() factory returns Cell instance', () => {
|
|
90
|
+
const c = cell('x')
|
|
91
91
|
expect(c).toBeInstanceOf(Cell)
|
|
92
92
|
})
|
|
93
93
|
|
|
94
|
-
test(
|
|
94
|
+
test('multiple rapid updates notify correctly', () => {
|
|
95
95
|
const c = cell(0)
|
|
96
96
|
const values: number[] = []
|
|
97
97
|
c.listen(() => values.push(c.peek()))
|
|
@@ -101,7 +101,7 @@ describe("Cell", () => {
|
|
|
101
101
|
expect(values).toEqual([1, 2, 3])
|
|
102
102
|
})
|
|
103
103
|
|
|
104
|
-
test(
|
|
104
|
+
test('NaN equality (Object.is)', () => {
|
|
105
105
|
const c = cell(Number.NaN)
|
|
106
106
|
let calls = 0
|
|
107
107
|
c.listen(() => calls++)
|
|
@@ -109,7 +109,7 @@ describe("Cell", () => {
|
|
|
109
109
|
expect(calls).toBe(0) // Object.is(NaN, NaN) is true
|
|
110
110
|
})
|
|
111
111
|
|
|
112
|
-
test(
|
|
112
|
+
test('subscribe() unsubscribe works after promotion to Set (regression)', () => {
|
|
113
113
|
// Bug: first subscriber's disposer became stale after second subscriber
|
|
114
114
|
// promoted _l → _s. The disposer checked _l which was now null.
|
|
115
115
|
const c = cell(0)
|
|
@@ -135,7 +135,7 @@ describe("Cell", () => {
|
|
|
135
135
|
expect(count2).toBe(2)
|
|
136
136
|
})
|
|
137
137
|
|
|
138
|
-
test(
|
|
138
|
+
test('subscribe() unsubscribe order: second before first', () => {
|
|
139
139
|
const c = cell(0)
|
|
140
140
|
let count1 = 0
|
|
141
141
|
let count2 = 0
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { computed } from
|
|
2
|
-
import { effect } from
|
|
3
|
-
import { signal } from
|
|
1
|
+
import { computed } from '../computed'
|
|
2
|
+
import { effect } from '../effect'
|
|
3
|
+
import { signal } from '../signal'
|
|
4
4
|
|
|
5
|
-
describe(
|
|
6
|
-
test(
|
|
5
|
+
describe('computed', () => {
|
|
6
|
+
test('computes derived value', () => {
|
|
7
7
|
const s = signal(2)
|
|
8
8
|
const doubled = computed(() => s() * 2)
|
|
9
9
|
expect(doubled()).toBe(4)
|
|
10
10
|
})
|
|
11
11
|
|
|
12
|
-
test(
|
|
12
|
+
test('updates when dependency changes', () => {
|
|
13
13
|
const s = signal(3)
|
|
14
14
|
const tripled = computed(() => s() * 3)
|
|
15
15
|
expect(tripled()).toBe(9)
|
|
@@ -17,7 +17,7 @@ describe("computed", () => {
|
|
|
17
17
|
expect(tripled()).toBe(12)
|
|
18
18
|
})
|
|
19
19
|
|
|
20
|
-
test(
|
|
20
|
+
test('is lazy — does not compute until read', () => {
|
|
21
21
|
let computations = 0
|
|
22
22
|
const s = signal(0)
|
|
23
23
|
const c = computed(() => {
|
|
@@ -29,7 +29,7 @@ describe("computed", () => {
|
|
|
29
29
|
expect(computations).toBe(1)
|
|
30
30
|
})
|
|
31
31
|
|
|
32
|
-
test(
|
|
32
|
+
test('is memoized — does not recompute on repeated reads', () => {
|
|
33
33
|
let computations = 0
|
|
34
34
|
const s = signal(5)
|
|
35
35
|
const c = computed(() => {
|
|
@@ -42,7 +42,7 @@ describe("computed", () => {
|
|
|
42
42
|
expect(computations).toBe(1)
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
-
test(
|
|
45
|
+
test('recomputes only when dirty', () => {
|
|
46
46
|
let computations = 0
|
|
47
47
|
const s = signal(1)
|
|
48
48
|
const c = computed(() => {
|
|
@@ -58,7 +58,7 @@ describe("computed", () => {
|
|
|
58
58
|
expect(computations).toBe(2) // still memoized
|
|
59
59
|
})
|
|
60
60
|
|
|
61
|
-
test(
|
|
61
|
+
test('chains correctly', () => {
|
|
62
62
|
const base = signal(2)
|
|
63
63
|
const doubled = computed(() => base() * 2)
|
|
64
64
|
const quadrupled = computed(() => doubled() * 2)
|
|
@@ -67,7 +67,7 @@ describe("computed", () => {
|
|
|
67
67
|
expect(quadrupled()).toBe(12)
|
|
68
68
|
})
|
|
69
69
|
|
|
70
|
-
test(
|
|
70
|
+
test('dispose stops recomputation', () => {
|
|
71
71
|
const s = signal(1)
|
|
72
72
|
let computations = 0
|
|
73
73
|
const c = computed(() => {
|
|
@@ -82,7 +82,7 @@ describe("computed", () => {
|
|
|
82
82
|
// (the computed is no longer subscribed to s)
|
|
83
83
|
})
|
|
84
84
|
|
|
85
|
-
test(
|
|
85
|
+
test('custom equals skips downstream notification when equal', () => {
|
|
86
86
|
const s = signal(3)
|
|
87
87
|
let downstream = 0
|
|
88
88
|
|
|
@@ -106,7 +106,7 @@ describe("computed", () => {
|
|
|
106
106
|
expect(c()).toBe(1)
|
|
107
107
|
})
|
|
108
108
|
|
|
109
|
-
test(
|
|
109
|
+
test('custom equals with array comparison', () => {
|
|
110
110
|
const items = signal([1, 2, 3])
|
|
111
111
|
let downstream = 0
|
|
112
112
|
|
|
@@ -130,7 +130,7 @@ describe("computed", () => {
|
|
|
130
130
|
expect(downstream).toBe(2)
|
|
131
131
|
})
|
|
132
132
|
|
|
133
|
-
test(
|
|
133
|
+
test('computed used as dependency inside an effect (subscribe path)', () => {
|
|
134
134
|
const s = signal(10)
|
|
135
135
|
const c = computed(() => s() + 1)
|
|
136
136
|
let result = 0
|
|
@@ -144,7 +144,7 @@ describe("computed", () => {
|
|
|
144
144
|
expect(result).toBe(21)
|
|
145
145
|
})
|
|
146
146
|
|
|
147
|
-
test(
|
|
147
|
+
test('._v returns cached value', () => {
|
|
148
148
|
const s = signal(5)
|
|
149
149
|
const doubled = computed(() => s() * 2)
|
|
150
150
|
// First access triggers computation
|
|
@@ -154,7 +154,7 @@ describe("computed", () => {
|
|
|
154
154
|
expect(doubled._v).toBe(14)
|
|
155
155
|
})
|
|
156
156
|
|
|
157
|
-
test(
|
|
157
|
+
test('.direct() fires updater on recompute', () => {
|
|
158
158
|
const s = signal(1)
|
|
159
159
|
const doubled = computed(() => s() * 2)
|
|
160
160
|
doubled() // initialize
|
|
@@ -176,7 +176,7 @@ describe("computed", () => {
|
|
|
176
176
|
expect(called).toBe(2) // disposed, no more calls
|
|
177
177
|
})
|
|
178
178
|
|
|
179
|
-
test(
|
|
179
|
+
test('.direct() works with equals option', () => {
|
|
180
180
|
const s = signal(1)
|
|
181
181
|
const clamped = computed(() => Math.min(s(), 10), {
|
|
182
182
|
equals: (a, b) => a === b,
|
|
@@ -198,8 +198,8 @@ describe("computed", () => {
|
|
|
198
198
|
expect(called).toBe(2) // equals suppresses
|
|
199
199
|
})
|
|
200
200
|
|
|
201
|
-
describe(
|
|
202
|
-
test(
|
|
201
|
+
describe('_v with equals after disposal', () => {
|
|
202
|
+
test('_v returns last cached value after dispose()', () => {
|
|
203
203
|
const s = signal(5)
|
|
204
204
|
const doubled = computed(() => s() * 2)
|
|
205
205
|
expect(doubled._v).toBe(10) // triggers initial computation
|
|
@@ -215,7 +215,7 @@ describe("computed", () => {
|
|
|
215
215
|
expect(doubled._v).toBe(14)
|
|
216
216
|
})
|
|
217
217
|
|
|
218
|
-
test(
|
|
218
|
+
test('computed with equals: _v only updates when equality check fails', () => {
|
|
219
219
|
const s = signal(3)
|
|
220
220
|
const floored = computed(() => Math.floor(s() / 10), {
|
|
221
221
|
equals: (a, b) => a === b,
|
|
@@ -233,7 +233,7 @@ describe("computed", () => {
|
|
|
233
233
|
expect(floored._v).toBe(1)
|
|
234
234
|
})
|
|
235
235
|
|
|
236
|
-
test(
|
|
236
|
+
test('multiple .direct() updaters on computed, dispose one', () => {
|
|
237
237
|
const s = signal(1)
|
|
238
238
|
const doubled = computed(() => s() * 2)
|
|
239
239
|
doubled() // initialize
|
|
@@ -267,8 +267,8 @@ describe("computed", () => {
|
|
|
267
267
|
})
|
|
268
268
|
})
|
|
269
269
|
|
|
270
|
-
describe(
|
|
271
|
-
test(
|
|
270
|
+
describe('diamond pattern cleanup', () => {
|
|
271
|
+
test('a -> b, c -> d diamond: d only recomputes once per a change', () => {
|
|
272
272
|
const a = signal(1)
|
|
273
273
|
const b = computed(() => a() + 1)
|
|
274
274
|
const c = computed(() => a() + 2)
|
|
@@ -288,7 +288,7 @@ describe("computed", () => {
|
|
|
288
288
|
expect(dComputations).toBe(2)
|
|
289
289
|
})
|
|
290
290
|
|
|
291
|
-
test(
|
|
291
|
+
test('dispose middle node in diamond, verify no stale subscriptions', () => {
|
|
292
292
|
const a = signal(1)
|
|
293
293
|
const b = computed(() => a() * 2)
|
|
294
294
|
const c = computed(() => a() * 3)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createSelector } from
|
|
2
|
-
import { effect } from
|
|
3
|
-
import { signal } from
|
|
1
|
+
import { createSelector } from '../createSelector'
|
|
2
|
+
import { effect } from '../effect'
|
|
3
|
+
import { signal } from '../signal'
|
|
4
4
|
|
|
5
|
-
describe(
|
|
6
|
-
test(
|
|
5
|
+
describe('createSelector', () => {
|
|
6
|
+
test('returns true for the currently selected value', () => {
|
|
7
7
|
const selected = signal(1)
|
|
8
8
|
const isSelected = createSelector(() => selected())
|
|
9
9
|
|
|
@@ -14,7 +14,7 @@ describe("createSelector", () => {
|
|
|
14
14
|
expect(result).toBe(true)
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
test(
|
|
17
|
+
test('returns false for non-selected values', () => {
|
|
18
18
|
const selected = signal(1)
|
|
19
19
|
const isSelected = createSelector(() => selected())
|
|
20
20
|
|
|
@@ -25,7 +25,7 @@ describe("createSelector", () => {
|
|
|
25
25
|
expect(result).toBe(false)
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
-
test(
|
|
28
|
+
test('only notifies affected subscribers when selection changes', () => {
|
|
29
29
|
const selected = signal(1)
|
|
30
30
|
const isSelected = createSelector(() => selected())
|
|
31
31
|
|
|
@@ -57,7 +57,7 @@ describe("createSelector", () => {
|
|
|
57
57
|
expect(runs3).toBe(1) // unaffected
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
-
test(
|
|
60
|
+
test('does not notify when source changes to the same value', () => {
|
|
61
61
|
const selected = signal(1)
|
|
62
62
|
const isSelected = createSelector(() => selected())
|
|
63
63
|
|
|
@@ -71,7 +71,7 @@ describe("createSelector", () => {
|
|
|
71
71
|
expect(runs).toBe(1)
|
|
72
72
|
})
|
|
73
73
|
|
|
74
|
-
test(
|
|
74
|
+
test('works when changing to a value with no subscribers', () => {
|
|
75
75
|
const selected = signal(1)
|
|
76
76
|
const isSelected = createSelector(() => selected())
|
|
77
77
|
|
|
@@ -86,7 +86,7 @@ describe("createSelector", () => {
|
|
|
86
86
|
expect(runs).toBe(2) // old bucket (1) notified
|
|
87
87
|
})
|
|
88
88
|
|
|
89
|
-
test(
|
|
89
|
+
test('reuses host objects for the same value', () => {
|
|
90
90
|
const selected = signal(1)
|
|
91
91
|
const isSelected = createSelector(() => selected())
|
|
92
92
|
|
|
@@ -108,7 +108,7 @@ describe("createSelector", () => {
|
|
|
108
108
|
expect(result2).toBe(false)
|
|
109
109
|
})
|
|
110
110
|
|
|
111
|
-
test(
|
|
111
|
+
test('tracks correctly outside an effect (no activeEffect)', () => {
|
|
112
112
|
const selected = signal(1)
|
|
113
113
|
const isSelected = createSelector(() => selected())
|
|
114
114
|
|
|
@@ -117,8 +117,8 @@ describe("createSelector", () => {
|
|
|
117
117
|
expect(isSelected(2)).toBe(false)
|
|
118
118
|
})
|
|
119
119
|
|
|
120
|
-
describe(
|
|
121
|
-
test(
|
|
120
|
+
describe('large subscriber sets', () => {
|
|
121
|
+
test('many subscribers (20+), only affected buckets notified', () => {
|
|
122
122
|
const selected = signal(0)
|
|
123
123
|
const isSelected = createSelector(() => selected())
|
|
124
124
|
|
|
@@ -151,8 +151,8 @@ describe("createSelector", () => {
|
|
|
151
151
|
expect(unaffectedAfterSecond).toBe(true)
|
|
152
152
|
})
|
|
153
153
|
|
|
154
|
-
test(
|
|
155
|
-
const selected = signal<string | null | undefined>(
|
|
154
|
+
test('selector with undefined and null values', () => {
|
|
155
|
+
const selected = signal<string | null | undefined>('a')
|
|
156
156
|
const isSelected = createSelector(() => selected())
|
|
157
157
|
|
|
158
158
|
let nullRuns = 0
|
|
@@ -168,7 +168,7 @@ describe("createSelector", () => {
|
|
|
168
168
|
undefRuns++
|
|
169
169
|
})
|
|
170
170
|
effect(() => {
|
|
171
|
-
isSelected(
|
|
171
|
+
isSelected('a')
|
|
172
172
|
aRuns++
|
|
173
173
|
})
|
|
174
174
|
|
|
@@ -189,7 +189,7 @@ describe("createSelector", () => {
|
|
|
189
189
|
expect(aRuns).toBe(2) // unaffected
|
|
190
190
|
})
|
|
191
191
|
|
|
192
|
-
test(
|
|
192
|
+
test('rapid selector changes', () => {
|
|
193
193
|
const selected = signal(0)
|
|
194
194
|
const isSelected = createSelector(() => selected())
|
|
195
195
|
|
package/src/tests/debug.test.ts
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import { _notifyTraceListeners, inspectSignal, isTracing, onSignalUpdate, why } from
|
|
2
|
-
import { signal } from
|
|
1
|
+
import { _notifyTraceListeners, inspectSignal, isTracing, onSignalUpdate, why } from '../debug'
|
|
2
|
+
import { signal } from '../signal'
|
|
3
3
|
|
|
4
|
-
describe(
|
|
5
|
-
describe(
|
|
6
|
-
test(
|
|
4
|
+
describe('debug', () => {
|
|
5
|
+
describe('onSignalUpdate / isTracing', () => {
|
|
6
|
+
test('isTracing is false by default', () => {
|
|
7
7
|
expect(isTracing()).toBe(false)
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
-
test(
|
|
10
|
+
test('registering a listener enables tracing', () => {
|
|
11
11
|
const dispose = onSignalUpdate(() => {})
|
|
12
12
|
expect(isTracing()).toBe(true)
|
|
13
13
|
dispose()
|
|
14
14
|
expect(isTracing()).toBe(false)
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
test(
|
|
17
|
+
test('listener receives signal update events', () => {
|
|
18
18
|
const events: { name: string | undefined; prev: unknown; next: unknown }[] = []
|
|
19
19
|
const dispose = onSignalUpdate((e) => {
|
|
20
20
|
events.push({ name: e.name, prev: e.prev, next: e.next })
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
-
const s = signal(1, { name:
|
|
23
|
+
const s = signal(1, { name: 'count' })
|
|
24
24
|
s.set(2)
|
|
25
25
|
|
|
26
26
|
expect(events.length).toBe(1)
|
|
27
|
-
expect(events[0]).toEqual({ name:
|
|
27
|
+
expect(events[0]).toEqual({ name: 'count', prev: 1, next: 2 })
|
|
28
28
|
|
|
29
29
|
dispose()
|
|
30
30
|
})
|
|
31
31
|
|
|
32
|
-
test(
|
|
32
|
+
test('dispose removes only the specific listener', () => {
|
|
33
33
|
let calls1 = 0
|
|
34
34
|
let calls2 = 0
|
|
35
35
|
const dispose1 = onSignalUpdate(() => calls1++)
|
|
@@ -50,20 +50,20 @@ describe("debug", () => {
|
|
|
50
50
|
expect(isTracing()).toBe(false)
|
|
51
51
|
})
|
|
52
52
|
|
|
53
|
-
test(
|
|
53
|
+
test('dispose is safe to call when listeners already null', () => {
|
|
54
54
|
const dispose = onSignalUpdate(() => {})
|
|
55
55
|
dispose()
|
|
56
56
|
expect(isTracing()).toBe(false)
|
|
57
57
|
dispose() // should not throw — _traceListeners is null
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
-
test(
|
|
60
|
+
test('_notifyTraceListeners does nothing when no listeners', () => {
|
|
61
61
|
const s = signal(0)
|
|
62
62
|
// Should not throw
|
|
63
63
|
_notifyTraceListeners(s, 0, 1)
|
|
64
64
|
})
|
|
65
65
|
|
|
66
|
-
test(
|
|
66
|
+
test('event includes stack and timestamp', () => {
|
|
67
67
|
let event: { stack: string; timestamp: number } | undefined
|
|
68
68
|
const dispose = onSignalUpdate((e) => {
|
|
69
69
|
event = { stack: e.stack, timestamp: e.timestamp }
|
|
@@ -73,20 +73,20 @@ describe("debug", () => {
|
|
|
73
73
|
s.set(1)
|
|
74
74
|
|
|
75
75
|
expect(event).toBeDefined()
|
|
76
|
-
expect(typeof event?.stack).toBe(
|
|
77
|
-
expect(typeof event?.timestamp).toBe(
|
|
76
|
+
expect(typeof event?.stack).toBe('string')
|
|
77
|
+
expect(typeof event?.timestamp).toBe('number')
|
|
78
78
|
|
|
79
79
|
dispose()
|
|
80
80
|
})
|
|
81
81
|
})
|
|
82
82
|
|
|
83
|
-
describe(
|
|
84
|
-
test(
|
|
83
|
+
describe('why', () => {
|
|
84
|
+
test('logs signal updates to console', async () => {
|
|
85
85
|
const logs: unknown[][] = []
|
|
86
86
|
const origLog = console.log
|
|
87
87
|
console.log = (...args: unknown[]) => logs.push(args)
|
|
88
88
|
|
|
89
|
-
const s = signal(1, { name:
|
|
89
|
+
const s = signal(1, { name: 'test' })
|
|
90
90
|
why()
|
|
91
91
|
s.set(2)
|
|
92
92
|
|
|
@@ -109,21 +109,21 @@ describe("debug", () => {
|
|
|
109
109
|
|
|
110
110
|
const noUpdateLog =
|
|
111
111
|
logs.find((args) =>
|
|
112
|
-
typeof args[0] ===
|
|
112
|
+
typeof args[0] === 'string' ? args[0].includes('No signal') : false,
|
|
113
113
|
) ||
|
|
114
|
-
logs.find((args) => (typeof args[1] ===
|
|
114
|
+
logs.find((args) => (typeof args[1] === 'string' ? args[1].includes('No signal') : false))
|
|
115
115
|
expect(noUpdateLog).toBeDefined()
|
|
116
116
|
console.log = origLog
|
|
117
117
|
})
|
|
118
118
|
|
|
119
|
-
test(
|
|
119
|
+
test('calling why() twice is ignored (already active)', async () => {
|
|
120
120
|
const logs: unknown[][] = []
|
|
121
121
|
const origLog = console.log
|
|
122
122
|
console.log = (...args: unknown[]) => logs.push(args)
|
|
123
123
|
|
|
124
124
|
why()
|
|
125
125
|
why() // should be ignored
|
|
126
|
-
const s = signal(0, { name:
|
|
126
|
+
const s = signal(0, { name: 'x' })
|
|
127
127
|
s.set(1)
|
|
128
128
|
|
|
129
129
|
await new Promise((r) => queueMicrotask(() => r(undefined)))
|
|
@@ -131,7 +131,7 @@ describe("debug", () => {
|
|
|
131
131
|
console.log = origLog
|
|
132
132
|
})
|
|
133
133
|
|
|
134
|
-
test(
|
|
134
|
+
test('logs anonymous signal name when no name is set', async () => {
|
|
135
135
|
const logs: unknown[][] = []
|
|
136
136
|
const origLog = console.log
|
|
137
137
|
console.log = (...args: unknown[]) => logs.push(args)
|
|
@@ -143,15 +143,15 @@ describe("debug", () => {
|
|
|
143
143
|
await new Promise((r) => queueMicrotask(() => r(undefined)))
|
|
144
144
|
|
|
145
145
|
const anonLog = logs.find((args) =>
|
|
146
|
-
args.some((a) => typeof a ===
|
|
146
|
+
args.some((a) => typeof a === 'string' && a.includes('anonymous')),
|
|
147
147
|
)
|
|
148
148
|
expect(anonLog).toBeDefined()
|
|
149
149
|
console.log = origLog
|
|
150
150
|
})
|
|
151
151
|
})
|
|
152
152
|
|
|
153
|
-
describe(
|
|
154
|
-
test(
|
|
153
|
+
describe('inspectSignal', () => {
|
|
154
|
+
test('prints signal info and returns debug info', () => {
|
|
155
155
|
const groupCalls: unknown[][] = []
|
|
156
156
|
const logCalls: unknown[][] = []
|
|
157
157
|
const origGroup = console.group
|
|
@@ -161,10 +161,10 @@ describe("debug", () => {
|
|
|
161
161
|
console.log = (...args: unknown[]) => logCalls.push(args)
|
|
162
162
|
console.groupEnd = () => {}
|
|
163
163
|
|
|
164
|
-
const s = signal(42, { name:
|
|
164
|
+
const s = signal(42, { name: 'count' })
|
|
165
165
|
const info = inspectSignal(s)
|
|
166
166
|
|
|
167
|
-
expect(info.name).toBe(
|
|
167
|
+
expect(info.name).toBe('count')
|
|
168
168
|
expect(info.value).toBe(42)
|
|
169
169
|
expect(info.subscriberCount).toBe(0)
|
|
170
170
|
expect(groupCalls.length).toBe(1)
|
|
@@ -175,7 +175,7 @@ describe("debug", () => {
|
|
|
175
175
|
console.groupEnd = origEnd
|
|
176
176
|
})
|
|
177
177
|
|
|
178
|
-
test(
|
|
178
|
+
test('handles anonymous signal', () => {
|
|
179
179
|
const origGroup = console.group
|
|
180
180
|
const origLog = console.log
|
|
181
181
|
const origEnd = console.groupEnd
|