@pyreon/reactivity 0.24.5 → 0.24.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/package.json +1 -4
- package/src/batch.ts +0 -196
- package/src/cell.ts +0 -72
- package/src/computed.ts +0 -313
- package/src/createSelector.ts +0 -109
- package/src/debug.ts +0 -134
- package/src/effect.ts +0 -467
- package/src/env.d.ts +0 -6
- package/src/index.ts +0 -60
- package/src/lpih.ts +0 -227
- package/src/manifest.ts +0 -660
- package/src/reactive-devtools.ts +0 -494
- package/src/reactive-trace.ts +0 -142
- package/src/reconcile.ts +0 -118
- package/src/resource.ts +0 -84
- package/src/scope.ts +0 -123
- package/src/signal.ts +0 -261
- package/src/store.ts +0 -250
- package/src/tests/batch.test.ts +0 -751
- package/src/tests/bind.test.ts +0 -84
- package/src/tests/branches.test.ts +0 -343
- package/src/tests/cell.test.ts +0 -159
- package/src/tests/computed.test.ts +0 -436
- package/src/tests/coverage-hardening.test.ts +0 -471
- package/src/tests/createSelector.test.ts +0 -291
- package/src/tests/debug.test.ts +0 -196
- package/src/tests/effect.test.ts +0 -464
- package/src/tests/fanout-repro.test.ts +0 -179
- package/src/tests/lpih-source-location.test.ts +0 -277
- package/src/tests/lpih.test.ts +0 -351
- package/src/tests/manifest-snapshot.test.ts +0 -96
- package/src/tests/reactive-devtools-treeshake.test.ts +0 -48
- package/src/tests/reactive-devtools.test.ts +0 -296
- package/src/tests/reactive-trace.test.ts +0 -102
- package/src/tests/reconcile-security.test.ts +0 -45
- package/src/tests/resource.test.ts +0 -326
- package/src/tests/scope.test.ts +0 -231
- package/src/tests/signal.test.ts +0 -368
- package/src/tests/store.test.ts +0 -286
- package/src/tests/tracking.test.ts +0 -158
- package/src/tests/vue-parity.test.ts +0 -191
- package/src/tests/watch.test.ts +0 -246
- package/src/tracking.ts +0 -139
- package/src/watch.ts +0 -68
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
import { createSelector } from '../createSelector'
|
|
2
|
-
import { effect } from '../effect'
|
|
3
|
-
import { signal } from '../signal'
|
|
4
|
-
|
|
5
|
-
describe('createSelector', () => {
|
|
6
|
-
test('returns true for the currently selected value', () => {
|
|
7
|
-
const selected = signal(1)
|
|
8
|
-
const isSelected = createSelector(() => selected())
|
|
9
|
-
|
|
10
|
-
let result = false
|
|
11
|
-
effect(() => {
|
|
12
|
-
result = isSelected(1)
|
|
13
|
-
})
|
|
14
|
-
expect(result).toBe(true)
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
test('returns false for non-selected values', () => {
|
|
18
|
-
const selected = signal(1)
|
|
19
|
-
const isSelected = createSelector(() => selected())
|
|
20
|
-
|
|
21
|
-
let result = true
|
|
22
|
-
effect(() => {
|
|
23
|
-
result = isSelected(2)
|
|
24
|
-
})
|
|
25
|
-
expect(result).toBe(false)
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
test('only notifies affected subscribers when selection changes', () => {
|
|
29
|
-
const selected = signal(1)
|
|
30
|
-
const isSelected = createSelector(() => selected())
|
|
31
|
-
|
|
32
|
-
let runs1 = 0
|
|
33
|
-
let runs2 = 0
|
|
34
|
-
let runs3 = 0
|
|
35
|
-
|
|
36
|
-
effect(() => {
|
|
37
|
-
isSelected(1)
|
|
38
|
-
runs1++
|
|
39
|
-
})
|
|
40
|
-
effect(() => {
|
|
41
|
-
isSelected(2)
|
|
42
|
-
runs2++
|
|
43
|
-
})
|
|
44
|
-
effect(() => {
|
|
45
|
-
isSelected(3)
|
|
46
|
-
runs3++
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
expect(runs1).toBe(1)
|
|
50
|
-
expect(runs2).toBe(1)
|
|
51
|
-
expect(runs3).toBe(1)
|
|
52
|
-
|
|
53
|
-
// Change selection from 1 to 2: only buckets 1 (deselected) and 2 (newly selected) should fire
|
|
54
|
-
selected.set(2)
|
|
55
|
-
expect(runs1).toBe(2) // deselected
|
|
56
|
-
expect(runs2).toBe(2) // newly selected
|
|
57
|
-
expect(runs3).toBe(1) // unaffected
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
test('does not notify when source changes to the same value', () => {
|
|
61
|
-
const selected = signal(1)
|
|
62
|
-
const isSelected = createSelector(() => selected())
|
|
63
|
-
|
|
64
|
-
let runs = 0
|
|
65
|
-
effect(() => {
|
|
66
|
-
isSelected(1)
|
|
67
|
-
runs++
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
selected.set(1) // same value
|
|
71
|
-
expect(runs).toBe(1)
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
test('works when changing to a value with no subscribers', () => {
|
|
75
|
-
const selected = signal(1)
|
|
76
|
-
const isSelected = createSelector(() => selected())
|
|
77
|
-
|
|
78
|
-
let runs = 0
|
|
79
|
-
effect(() => {
|
|
80
|
-
isSelected(1)
|
|
81
|
-
runs++
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
// Change to value 99 which has no subscriber bucket
|
|
85
|
-
selected.set(99)
|
|
86
|
-
expect(runs).toBe(2) // old bucket (1) notified
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
test('reuses host objects for the same value', () => {
|
|
90
|
-
const selected = signal(1)
|
|
91
|
-
const isSelected = createSelector(() => selected())
|
|
92
|
-
|
|
93
|
-
let result1 = false
|
|
94
|
-
let result2 = false
|
|
95
|
-
effect(() => {
|
|
96
|
-
result1 = isSelected(1)
|
|
97
|
-
})
|
|
98
|
-
// Second call with same value should reuse the host
|
|
99
|
-
effect(() => {
|
|
100
|
-
result2 = isSelected(1)
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
expect(result1).toBe(true)
|
|
104
|
-
expect(result2).toBe(true)
|
|
105
|
-
|
|
106
|
-
selected.set(2)
|
|
107
|
-
expect(result1).toBe(false)
|
|
108
|
-
expect(result2).toBe(false)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
test('tracks correctly outside an effect (no activeEffect)', () => {
|
|
112
|
-
const selected = signal(1)
|
|
113
|
-
const isSelected = createSelector(() => selected())
|
|
114
|
-
|
|
115
|
-
// Calling outside an effect should still return the correct boolean
|
|
116
|
-
expect(isSelected(1)).toBe(true)
|
|
117
|
-
expect(isSelected(2)).toBe(false)
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
describe('large subscriber sets', () => {
|
|
121
|
-
test('many subscribers (20+), only affected buckets notified', () => {
|
|
122
|
-
const selected = signal(0)
|
|
123
|
-
const isSelected = createSelector(() => selected())
|
|
124
|
-
|
|
125
|
-
const runCounts: number[] = []
|
|
126
|
-
for (let i = 0; i < 25; i++) {
|
|
127
|
-
const idx = i
|
|
128
|
-
runCounts.push(0)
|
|
129
|
-
effect(() => {
|
|
130
|
-
isSelected(idx)
|
|
131
|
-
runCounts[idx] = (runCounts[idx] ?? 0) + 1
|
|
132
|
-
})
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// All effects ran once
|
|
136
|
-
const allOnes = runCounts.every((c) => c === 1)
|
|
137
|
-
expect(allOnes).toBe(true)
|
|
138
|
-
|
|
139
|
-
// Change from 0 to 5: only buckets 0 and 5 should re-run
|
|
140
|
-
selected.set(5)
|
|
141
|
-
expect(runCounts[0]).toBe(2) // deselected
|
|
142
|
-
expect(runCounts[5]).toBe(2) // newly selected
|
|
143
|
-
const unaffectedAfterFirst = runCounts.every((c, i) => i === 0 || i === 5 || c === 1)
|
|
144
|
-
expect(unaffectedAfterFirst).toBe(true)
|
|
145
|
-
|
|
146
|
-
// Change from 5 to 24: only buckets 5 and 24 re-run
|
|
147
|
-
selected.set(24)
|
|
148
|
-
expect(runCounts[5]).toBe(3)
|
|
149
|
-
expect(runCounts[24]).toBe(2)
|
|
150
|
-
const unaffectedAfterSecond = runCounts.every((c, i) => [0, 5, 24].includes(i) || c === 1)
|
|
151
|
-
expect(unaffectedAfterSecond).toBe(true)
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
test('selector with undefined and null values', () => {
|
|
155
|
-
const selected = signal<string | null | undefined>('a')
|
|
156
|
-
const isSelected = createSelector(() => selected())
|
|
157
|
-
|
|
158
|
-
let nullRuns = 0
|
|
159
|
-
let undefRuns = 0
|
|
160
|
-
let aRuns = 0
|
|
161
|
-
|
|
162
|
-
effect(() => {
|
|
163
|
-
isSelected(null)
|
|
164
|
-
nullRuns++
|
|
165
|
-
})
|
|
166
|
-
effect(() => {
|
|
167
|
-
isSelected(undefined)
|
|
168
|
-
undefRuns++
|
|
169
|
-
})
|
|
170
|
-
effect(() => {
|
|
171
|
-
isSelected('a')
|
|
172
|
-
aRuns++
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
expect(nullRuns).toBe(1)
|
|
176
|
-
expect(undefRuns).toBe(1)
|
|
177
|
-
expect(aRuns).toBe(1)
|
|
178
|
-
|
|
179
|
-
// Switch to null
|
|
180
|
-
selected.set(null)
|
|
181
|
-
expect(aRuns).toBe(2) // deselected
|
|
182
|
-
expect(nullRuns).toBe(2) // newly selected
|
|
183
|
-
expect(undefRuns).toBe(1) // unaffected
|
|
184
|
-
|
|
185
|
-
// Switch to undefined
|
|
186
|
-
selected.set(undefined)
|
|
187
|
-
expect(nullRuns).toBe(3) // deselected
|
|
188
|
-
expect(undefRuns).toBe(2) // newly selected
|
|
189
|
-
expect(aRuns).toBe(2) // unaffected
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
test('rapid selector changes', () => {
|
|
193
|
-
const selected = signal(0)
|
|
194
|
-
const isSelected = createSelector(() => selected())
|
|
195
|
-
|
|
196
|
-
let runs0 = 0
|
|
197
|
-
let runs1 = 0
|
|
198
|
-
let runs2 = 0
|
|
199
|
-
|
|
200
|
-
effect(() => {
|
|
201
|
-
isSelected(0)
|
|
202
|
-
runs0++
|
|
203
|
-
})
|
|
204
|
-
effect(() => {
|
|
205
|
-
isSelected(1)
|
|
206
|
-
runs1++
|
|
207
|
-
})
|
|
208
|
-
effect(() => {
|
|
209
|
-
isSelected(2)
|
|
210
|
-
runs2++
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
// Rapid changes: 0 -> 1 -> 2 -> 0
|
|
214
|
-
selected.set(1)
|
|
215
|
-
selected.set(2)
|
|
216
|
-
selected.set(0)
|
|
217
|
-
|
|
218
|
-
// Each affected bucket should have been notified for each change
|
|
219
|
-
// 0->1: runs0+1, runs1+1
|
|
220
|
-
// 1->2: runs1+1, runs2+1
|
|
221
|
-
// 2->0: runs2+1, runs0+1
|
|
222
|
-
expect(runs0).toBe(3) // initial + deselected + reselected
|
|
223
|
-
expect(runs1).toBe(3) // initial + selected + deselected
|
|
224
|
-
expect(runs2).toBe(3) // initial + selected + deselected
|
|
225
|
-
|
|
226
|
-
// Final state
|
|
227
|
-
expect(isSelected(0)).toBe(true)
|
|
228
|
-
expect(isSelected(1)).toBe(false)
|
|
229
|
-
expect(isSelected(2)).toBe(false)
|
|
230
|
-
})
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
// Regression: pre-fix, the source-tracking effect ran forever AND the
|
|
234
|
-
// per-value subs/hosts Maps grew unboundedly. With dynamic value spaces
|
|
235
|
-
// (UUIDs, ephemeral IDs) this leaked memory for the lifetime of the
|
|
236
|
-
// program. dispose() now stops the effect AND clears both Maps.
|
|
237
|
-
describe('dispose', () => {
|
|
238
|
-
test('stops source-tracking after dispose', () => {
|
|
239
|
-
const selected = signal(0)
|
|
240
|
-
const isSelected = createSelector(() => selected())
|
|
241
|
-
const runs: number[] = []
|
|
242
|
-
effect(() => {
|
|
243
|
-
runs.push(isSelected(1) ? 1 : 0)
|
|
244
|
-
})
|
|
245
|
-
expect(runs).toEqual([0])
|
|
246
|
-
selected.set(1)
|
|
247
|
-
expect(runs).toEqual([0, 1])
|
|
248
|
-
|
|
249
|
-
isSelected.dispose()
|
|
250
|
-
// Source change after dispose — the effect that tracks `isSelected(1)`
|
|
251
|
-
// should NOT re-run because the selector's internal effect was stopped.
|
|
252
|
-
selected.set(2)
|
|
253
|
-
expect(runs).toEqual([0, 1])
|
|
254
|
-
})
|
|
255
|
-
|
|
256
|
-
test('post-dispose calls return last-known result without tracking', () => {
|
|
257
|
-
const selected = signal(0)
|
|
258
|
-
const isSelected = createSelector(() => selected())
|
|
259
|
-
isSelected.dispose()
|
|
260
|
-
// Last known value was 0 — calls return its match against the query.
|
|
261
|
-
expect(isSelected(0)).toBe(true)
|
|
262
|
-
expect(isSelected(1)).toBe(false)
|
|
263
|
-
})
|
|
264
|
-
|
|
265
|
-
test('dispose is idempotent', () => {
|
|
266
|
-
const selected = signal(0)
|
|
267
|
-
const isSelected = createSelector(() => selected())
|
|
268
|
-
expect(() => {
|
|
269
|
-
isSelected.dispose()
|
|
270
|
-
isSelected.dispose()
|
|
271
|
-
isSelected.dispose()
|
|
272
|
-
}).not.toThrow()
|
|
273
|
-
})
|
|
274
|
-
|
|
275
|
-
test('post-dispose: source no longer propagates to selector', () => {
|
|
276
|
-
// Observable consequence of stopping the internal effect — proves
|
|
277
|
-
// the per-value Maps are no longer being populated either (because
|
|
278
|
-
// the tracking path is bypassed entirely after dispose).
|
|
279
|
-
const selected = signal('initial')
|
|
280
|
-
const isSelected = createSelector(() => selected())
|
|
281
|
-
// Build up the cache by querying many unique values.
|
|
282
|
-
for (let i = 0; i < 100; i++) isSelected(`uuid-${i}`)
|
|
283
|
-
isSelected.dispose()
|
|
284
|
-
// After dispose, the source is no longer tracked — changing it
|
|
285
|
-
// doesn't propagate to the selector's internal `current` value.
|
|
286
|
-
selected.set('changed')
|
|
287
|
-
expect(isSelected('initial')).toBe(true) // last-known wins
|
|
288
|
-
expect(isSelected('changed')).toBe(false) // never propagated
|
|
289
|
-
})
|
|
290
|
-
})
|
|
291
|
-
})
|
package/src/tests/debug.test.ts
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import { _notifyTraceListeners, inspectSignal, isTracing, onSignalUpdate, why } from '../debug'
|
|
2
|
-
import { signal } from '../signal'
|
|
3
|
-
|
|
4
|
-
describe('debug', () => {
|
|
5
|
-
describe('onSignalUpdate / isTracing', () => {
|
|
6
|
-
test('isTracing is false by default', () => {
|
|
7
|
-
expect(isTracing()).toBe(false)
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
test('registering a listener enables tracing', () => {
|
|
11
|
-
const dispose = onSignalUpdate(() => {})
|
|
12
|
-
expect(isTracing()).toBe(true)
|
|
13
|
-
dispose()
|
|
14
|
-
expect(isTracing()).toBe(false)
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
test('listener receives signal update events', () => {
|
|
18
|
-
const events: { name: string | undefined; prev: unknown; next: unknown }[] = []
|
|
19
|
-
const dispose = onSignalUpdate((e) => {
|
|
20
|
-
events.push({ name: e.name, prev: e.prev, next: e.next })
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
const s = signal(1, { name: 'count' })
|
|
24
|
-
s.set(2)
|
|
25
|
-
|
|
26
|
-
expect(events.length).toBe(1)
|
|
27
|
-
expect(events[0]).toEqual({ name: 'count', prev: 1, next: 2 })
|
|
28
|
-
|
|
29
|
-
dispose()
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
test('dispose removes only the specific listener', () => {
|
|
33
|
-
let calls1 = 0
|
|
34
|
-
let calls2 = 0
|
|
35
|
-
const dispose1 = onSignalUpdate(() => calls1++)
|
|
36
|
-
const dispose2 = onSignalUpdate(() => calls2++)
|
|
37
|
-
|
|
38
|
-
const s = signal(0)
|
|
39
|
-
s.set(1)
|
|
40
|
-
expect(calls1).toBe(1)
|
|
41
|
-
expect(calls2).toBe(1)
|
|
42
|
-
|
|
43
|
-
dispose1()
|
|
44
|
-
|
|
45
|
-
s.set(2)
|
|
46
|
-
expect(calls1).toBe(1) // removed
|
|
47
|
-
expect(calls2).toBe(2) // still active
|
|
48
|
-
|
|
49
|
-
dispose2()
|
|
50
|
-
expect(isTracing()).toBe(false)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
test('dispose is safe to call when listeners already null', () => {
|
|
54
|
-
const dispose = onSignalUpdate(() => {})
|
|
55
|
-
dispose()
|
|
56
|
-
expect(isTracing()).toBe(false)
|
|
57
|
-
dispose() // should not throw — _traceListeners is null
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
test('_notifyTraceListeners does nothing when no listeners', () => {
|
|
61
|
-
const s = signal(0)
|
|
62
|
-
// Should not throw
|
|
63
|
-
_notifyTraceListeners(s, 0, 1)
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
test('event includes stack and timestamp', () => {
|
|
67
|
-
let event: { stack: string; timestamp: number } | undefined
|
|
68
|
-
const dispose = onSignalUpdate((e) => {
|
|
69
|
-
event = { stack: e.stack, timestamp: e.timestamp }
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
const s = signal(0)
|
|
73
|
-
s.set(1)
|
|
74
|
-
|
|
75
|
-
expect(event).toBeDefined()
|
|
76
|
-
expect(typeof event?.stack).toBe('string')
|
|
77
|
-
expect(typeof event?.timestamp).toBe('number')
|
|
78
|
-
|
|
79
|
-
dispose()
|
|
80
|
-
})
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
describe('why', () => {
|
|
84
|
-
test('logs signal updates to console', async () => {
|
|
85
|
-
const logs: unknown[][] = []
|
|
86
|
-
const origLog = console.log
|
|
87
|
-
console.log = (...args: unknown[]) => logs.push(args)
|
|
88
|
-
|
|
89
|
-
const s = signal(1, { name: 'test' })
|
|
90
|
-
why()
|
|
91
|
-
s.set(2)
|
|
92
|
-
|
|
93
|
-
// Wait for microtask (auto-dispose)
|
|
94
|
-
await new Promise((r) => queueMicrotask(() => r(undefined)))
|
|
95
|
-
|
|
96
|
-
expect(logs.length).toBeGreaterThan(0)
|
|
97
|
-
console.log = origLog
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
test("logs 'no updates' when nothing changes", async () => {
|
|
101
|
-
const logs: unknown[][] = []
|
|
102
|
-
const origLog = console.log
|
|
103
|
-
console.log = (...args: unknown[]) => logs.push(args)
|
|
104
|
-
|
|
105
|
-
why()
|
|
106
|
-
// No signal updates
|
|
107
|
-
|
|
108
|
-
await new Promise((r) => queueMicrotask(() => r(undefined)))
|
|
109
|
-
|
|
110
|
-
const noUpdateLog =
|
|
111
|
-
logs.find((args) =>
|
|
112
|
-
typeof args[0] === 'string' ? args[0].includes('No signal') : false,
|
|
113
|
-
) ||
|
|
114
|
-
logs.find((args) => (typeof args[1] === 'string' ? args[1].includes('No signal') : false))
|
|
115
|
-
expect(noUpdateLog).toBeDefined()
|
|
116
|
-
console.log = origLog
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
test('calling why() twice is ignored (already active)', async () => {
|
|
120
|
-
const logs: unknown[][] = []
|
|
121
|
-
const origLog = console.log
|
|
122
|
-
console.log = (...args: unknown[]) => logs.push(args)
|
|
123
|
-
|
|
124
|
-
why()
|
|
125
|
-
why() // should be ignored
|
|
126
|
-
const s = signal(0, { name: 'x' })
|
|
127
|
-
s.set(1)
|
|
128
|
-
|
|
129
|
-
await new Promise((r) => queueMicrotask(() => r(undefined)))
|
|
130
|
-
// Should not throw or double-log
|
|
131
|
-
console.log = origLog
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
test('logs anonymous signal name when no name is set', async () => {
|
|
135
|
-
const logs: unknown[][] = []
|
|
136
|
-
const origLog = console.log
|
|
137
|
-
console.log = (...args: unknown[]) => logs.push(args)
|
|
138
|
-
|
|
139
|
-
const s = signal(0) // no name
|
|
140
|
-
why()
|
|
141
|
-
s.set(1)
|
|
142
|
-
|
|
143
|
-
await new Promise((r) => queueMicrotask(() => r(undefined)))
|
|
144
|
-
|
|
145
|
-
const anonLog = logs.find((args) =>
|
|
146
|
-
args.some((a) => typeof a === 'string' && a.includes('anonymous')),
|
|
147
|
-
)
|
|
148
|
-
expect(anonLog).toBeDefined()
|
|
149
|
-
console.log = origLog
|
|
150
|
-
})
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
describe('inspectSignal', () => {
|
|
154
|
-
test('prints signal info and returns debug info', () => {
|
|
155
|
-
const groupCalls: unknown[][] = []
|
|
156
|
-
const logCalls: unknown[][] = []
|
|
157
|
-
const origGroup = console.group
|
|
158
|
-
const origLog = console.log
|
|
159
|
-
const origEnd = console.groupEnd
|
|
160
|
-
console.group = (...args: unknown[]) => groupCalls.push(args)
|
|
161
|
-
console.log = (...args: unknown[]) => logCalls.push(args)
|
|
162
|
-
console.groupEnd = () => {}
|
|
163
|
-
|
|
164
|
-
const s = signal(42, { name: 'count' })
|
|
165
|
-
const info = inspectSignal(s)
|
|
166
|
-
|
|
167
|
-
expect(info.name).toBe('count')
|
|
168
|
-
expect(info.value).toBe(42)
|
|
169
|
-
expect(info.subscriberCount).toBe(0)
|
|
170
|
-
expect(groupCalls.length).toBe(1)
|
|
171
|
-
expect(logCalls.length).toBe(2) // value + subscribers
|
|
172
|
-
|
|
173
|
-
console.group = origGroup
|
|
174
|
-
console.log = origLog
|
|
175
|
-
console.groupEnd = origEnd
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
test('handles anonymous signal', () => {
|
|
179
|
-
const origGroup = console.group
|
|
180
|
-
const origLog = console.log
|
|
181
|
-
const origEnd = console.groupEnd
|
|
182
|
-
console.group = () => {}
|
|
183
|
-
console.log = () => {}
|
|
184
|
-
console.groupEnd = () => {}
|
|
185
|
-
|
|
186
|
-
const s = signal(0)
|
|
187
|
-
const info = inspectSignal(s)
|
|
188
|
-
|
|
189
|
-
expect(info.name).toBeUndefined()
|
|
190
|
-
|
|
191
|
-
console.group = origGroup
|
|
192
|
-
console.log = origLog
|
|
193
|
-
console.groupEnd = origEnd
|
|
194
|
-
})
|
|
195
|
-
})
|
|
196
|
-
})
|