@pyreon/core 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/analysis/index.js.html +1 -1
- package/lib/index.js +33 -5
- package/lib/index.js.map +1 -1
- package/lib/jsx-dev-runtime.js.map +1 -1
- package/lib/jsx-runtime.js.map +1 -1
- package/lib/types/index.d.ts +145 -98
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/jsx-dev-runtime.d.ts +94 -94
- package/lib/types/jsx-runtime.d.ts +94 -94
- package/package.json +11 -11
- package/src/component.ts +2 -2
- package/src/context.ts +75 -4
- package/src/dynamic.ts +4 -4
- package/src/error-boundary.ts +10 -10
- package/src/for.ts +8 -2
- package/src/h.ts +4 -4
- package/src/index.ts +30 -27
- package/src/jsx-dev-runtime.ts +1 -1
- package/src/jsx-runtime.ts +108 -108
- package/src/lazy.ts +4 -4
- package/src/lifecycle.ts +6 -6
- package/src/portal.ts +2 -2
- package/src/show.ts +4 -4
- package/src/style.ts +51 -51
- package/src/suspense.ts +8 -8
- package/src/telemetry.ts +1 -1
- package/src/tests/component.test.ts +60 -60
- package/src/tests/context.test.ts +102 -102
- package/src/tests/core.test.ts +376 -376
- package/src/tests/cx.test.ts +34 -34
- package/src/tests/dynamic.test.ts +28 -28
- package/src/tests/error-boundary.test.ts +51 -51
- package/src/tests/for.test.ts +26 -26
- package/src/tests/h.test.ts +100 -100
- package/src/tests/jsx-compat.test.tsx +41 -41
- package/src/tests/lazy.test.ts +28 -28
- package/src/tests/lifecycle.test.ts +35 -35
- package/src/tests/map-array.test.ts +36 -36
- package/src/tests/portal.test.ts +21 -21
- package/src/tests/props-extended.test.ts +51 -51
- package/src/tests/props.test.ts +62 -62
- package/src/tests/ref.test.ts +20 -20
- package/src/tests/show.test.ts +94 -94
- package/src/tests/style.test.ts +101 -101
- package/src/tests/suspense.test.ts +44 -44
- package/src/tests/telemetry.test.ts +35 -35
|
@@ -5,25 +5,25 @@ import {
|
|
|
5
5
|
onUnmount,
|
|
6
6
|
onUpdate,
|
|
7
7
|
setCurrentHooks,
|
|
8
|
-
} from
|
|
9
|
-
import type { LifecycleHooks } from
|
|
8
|
+
} from '../lifecycle'
|
|
9
|
+
import type { LifecycleHooks } from '../types'
|
|
10
10
|
|
|
11
|
-
describe(
|
|
11
|
+
describe('setCurrentHooks / getCurrentHooks', () => {
|
|
12
12
|
afterEach(() => {
|
|
13
13
|
setCurrentHooks(null)
|
|
14
14
|
})
|
|
15
15
|
|
|
16
|
-
test(
|
|
16
|
+
test('getCurrentHooks returns null by default', () => {
|
|
17
17
|
expect(getCurrentHooks()).toBeNull()
|
|
18
18
|
})
|
|
19
19
|
|
|
20
|
-
test(
|
|
20
|
+
test('setCurrentHooks sets the current hooks context', () => {
|
|
21
21
|
const hooks: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
22
22
|
setCurrentHooks(hooks)
|
|
23
23
|
expect(getCurrentHooks()).toBe(hooks)
|
|
24
24
|
})
|
|
25
25
|
|
|
26
|
-
test(
|
|
26
|
+
test('setCurrentHooks(null) clears the context', () => {
|
|
27
27
|
const hooks: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
28
28
|
setCurrentHooks(hooks)
|
|
29
29
|
expect(getCurrentHooks()).toBe(hooks)
|
|
@@ -32,12 +32,12 @@ describe("setCurrentHooks / getCurrentHooks", () => {
|
|
|
32
32
|
})
|
|
33
33
|
})
|
|
34
34
|
|
|
35
|
-
describe(
|
|
35
|
+
describe('onMount', () => {
|
|
36
36
|
afterEach(() => {
|
|
37
37
|
setCurrentHooks(null)
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
-
test(
|
|
40
|
+
test('registers callback on current hooks', () => {
|
|
41
41
|
const hooks: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
42
42
|
setCurrentHooks(hooks)
|
|
43
43
|
const fn = () => undefined
|
|
@@ -46,7 +46,7 @@ describe("onMount", () => {
|
|
|
46
46
|
expect(hooks.mount[0]).toBe(fn)
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
-
test(
|
|
49
|
+
test('multiple onMount calls accumulate', () => {
|
|
50
50
|
const hooks: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
51
51
|
setCurrentHooks(hooks)
|
|
52
52
|
onMount(() => undefined)
|
|
@@ -55,20 +55,20 @@ describe("onMount", () => {
|
|
|
55
55
|
expect(hooks.mount).toHaveLength(3)
|
|
56
56
|
})
|
|
57
57
|
|
|
58
|
-
test(
|
|
59
|
-
const warnSpy = vi.spyOn(console,
|
|
58
|
+
test('warns when called outside component setup', () => {
|
|
59
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
60
60
|
onMount(() => {})
|
|
61
61
|
expect(warnSpy).toHaveBeenCalledWith(
|
|
62
|
-
expect.stringContaining(
|
|
62
|
+
expect.stringContaining('onMount() called outside component setup'),
|
|
63
63
|
)
|
|
64
64
|
warnSpy.mockRestore()
|
|
65
65
|
})
|
|
66
66
|
|
|
67
|
-
test(
|
|
67
|
+
test('is a no-op outside component setup (no crash)', () => {
|
|
68
68
|
expect(() => onMount(() => {})).not.toThrow()
|
|
69
69
|
})
|
|
70
70
|
|
|
71
|
-
test(
|
|
71
|
+
test('accepts callback returning cleanup function', () => {
|
|
72
72
|
const hooks: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
73
73
|
setCurrentHooks(hooks)
|
|
74
74
|
const cleanup = () => {}
|
|
@@ -77,7 +77,7 @@ describe("onMount", () => {
|
|
|
77
77
|
expect(hooks.mount[0]!()).toBe(cleanup)
|
|
78
78
|
})
|
|
79
79
|
|
|
80
|
-
test(
|
|
80
|
+
test('accepts callback returning void', () => {
|
|
81
81
|
const hooks: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
82
82
|
setCurrentHooks(hooks)
|
|
83
83
|
onMount(() => {})
|
|
@@ -86,12 +86,12 @@ describe("onMount", () => {
|
|
|
86
86
|
})
|
|
87
87
|
})
|
|
88
88
|
|
|
89
|
-
describe(
|
|
89
|
+
describe('onUnmount', () => {
|
|
90
90
|
afterEach(() => {
|
|
91
91
|
setCurrentHooks(null)
|
|
92
92
|
})
|
|
93
93
|
|
|
94
|
-
test(
|
|
94
|
+
test('registers callback on current hooks', () => {
|
|
95
95
|
const hooks: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
96
96
|
setCurrentHooks(hooks)
|
|
97
97
|
const fn = () => {}
|
|
@@ -100,22 +100,22 @@ describe("onUnmount", () => {
|
|
|
100
100
|
expect(hooks.unmount[0]).toBe(fn)
|
|
101
101
|
})
|
|
102
102
|
|
|
103
|
-
test(
|
|
104
|
-
const warnSpy = vi.spyOn(console,
|
|
103
|
+
test('warns when called outside component setup', () => {
|
|
104
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
105
105
|
onUnmount(() => {})
|
|
106
106
|
expect(warnSpy).toHaveBeenCalledWith(
|
|
107
|
-
expect.stringContaining(
|
|
107
|
+
expect.stringContaining('onUnmount() called outside component setup'),
|
|
108
108
|
)
|
|
109
109
|
warnSpy.mockRestore()
|
|
110
110
|
})
|
|
111
111
|
})
|
|
112
112
|
|
|
113
|
-
describe(
|
|
113
|
+
describe('onUpdate', () => {
|
|
114
114
|
afterEach(() => {
|
|
115
115
|
setCurrentHooks(null)
|
|
116
116
|
})
|
|
117
117
|
|
|
118
|
-
test(
|
|
118
|
+
test('registers callback on current hooks', () => {
|
|
119
119
|
const hooks: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
120
120
|
setCurrentHooks(hooks)
|
|
121
121
|
const fn = () => {}
|
|
@@ -124,22 +124,22 @@ describe("onUpdate", () => {
|
|
|
124
124
|
expect(hooks.update[0]).toBe(fn)
|
|
125
125
|
})
|
|
126
126
|
|
|
127
|
-
test(
|
|
128
|
-
const warnSpy = vi.spyOn(console,
|
|
127
|
+
test('warns when called outside component setup', () => {
|
|
128
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
129
129
|
onUpdate(() => {})
|
|
130
130
|
expect(warnSpy).toHaveBeenCalledWith(
|
|
131
|
-
expect.stringContaining(
|
|
131
|
+
expect.stringContaining('onUpdate() called outside component setup'),
|
|
132
132
|
)
|
|
133
133
|
warnSpy.mockRestore()
|
|
134
134
|
})
|
|
135
135
|
})
|
|
136
136
|
|
|
137
|
-
describe(
|
|
137
|
+
describe('onErrorCaptured', () => {
|
|
138
138
|
afterEach(() => {
|
|
139
139
|
setCurrentHooks(null)
|
|
140
140
|
})
|
|
141
141
|
|
|
142
|
-
test(
|
|
142
|
+
test('registers callback on current hooks', () => {
|
|
143
143
|
const hooks: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
144
144
|
setCurrentHooks(hooks)
|
|
145
145
|
const fn = () => true
|
|
@@ -148,16 +148,16 @@ describe("onErrorCaptured", () => {
|
|
|
148
148
|
expect(hooks.error[0]).toBe(fn)
|
|
149
149
|
})
|
|
150
150
|
|
|
151
|
-
test(
|
|
152
|
-
const warnSpy = vi.spyOn(console,
|
|
151
|
+
test('warns when called outside component setup', () => {
|
|
152
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
153
153
|
onErrorCaptured(() => true)
|
|
154
154
|
expect(warnSpy).toHaveBeenCalledWith(
|
|
155
|
-
expect.stringContaining(
|
|
155
|
+
expect.stringContaining('onErrorCaptured() called outside component setup'),
|
|
156
156
|
)
|
|
157
157
|
warnSpy.mockRestore()
|
|
158
158
|
})
|
|
159
159
|
|
|
160
|
-
test(
|
|
160
|
+
test('registered handler receives the error', () => {
|
|
161
161
|
const hooks: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
162
162
|
setCurrentHooks(hooks)
|
|
163
163
|
let captured: unknown = null
|
|
@@ -166,18 +166,18 @@ describe("onErrorCaptured", () => {
|
|
|
166
166
|
return true
|
|
167
167
|
})
|
|
168
168
|
// Simulate calling the handler
|
|
169
|
-
const testError = new Error(
|
|
169
|
+
const testError = new Error('test')
|
|
170
170
|
hooks.error[0]!(testError)
|
|
171
171
|
expect(captured).toBe(testError)
|
|
172
172
|
})
|
|
173
173
|
})
|
|
174
174
|
|
|
175
|
-
describe(
|
|
175
|
+
describe('lifecycle hooks interaction', () => {
|
|
176
176
|
afterEach(() => {
|
|
177
177
|
setCurrentHooks(null)
|
|
178
178
|
})
|
|
179
179
|
|
|
180
|
-
test(
|
|
180
|
+
test('all hook types can be registered in same context', () => {
|
|
181
181
|
const hooks: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
182
182
|
setCurrentHooks(hooks)
|
|
183
183
|
|
|
@@ -192,7 +192,7 @@ describe("lifecycle hooks interaction", () => {
|
|
|
192
192
|
expect(hooks.error).toHaveLength(1)
|
|
193
193
|
})
|
|
194
194
|
|
|
195
|
-
test(
|
|
195
|
+
test('hooks from different setCurrentHooks calls go to different stores', () => {
|
|
196
196
|
const hooks1: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
197
197
|
const hooks2: LifecycleHooks = { mount: [], unmount: [], update: [], error: [] }
|
|
198
198
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { mapArray } from
|
|
1
|
+
import { mapArray } from '../map-array'
|
|
2
2
|
|
|
3
|
-
describe(
|
|
4
|
-
describe(
|
|
5
|
-
test(
|
|
3
|
+
describe('mapArray', () => {
|
|
4
|
+
describe('basic mapping', () => {
|
|
5
|
+
test('maps all items on first call', () => {
|
|
6
6
|
const mapped = mapArray(
|
|
7
7
|
() => [1, 2, 3],
|
|
8
8
|
(item) => item,
|
|
@@ -11,7 +11,7 @@ describe("mapArray", () => {
|
|
|
11
11
|
expect(mapped()).toEqual([10, 20, 30])
|
|
12
12
|
})
|
|
13
13
|
|
|
14
|
-
test(
|
|
14
|
+
test('returns empty array for empty source', () => {
|
|
15
15
|
const mapped = mapArray(
|
|
16
16
|
() => [],
|
|
17
17
|
(item: number) => item,
|
|
@@ -20,18 +20,18 @@ describe("mapArray", () => {
|
|
|
20
20
|
expect(mapped()).toEqual([])
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
-
test(
|
|
23
|
+
test('maps single item', () => {
|
|
24
24
|
const mapped = mapArray(
|
|
25
25
|
() => [42],
|
|
26
26
|
(item) => item,
|
|
27
27
|
(item) => `value-${item}`,
|
|
28
28
|
)
|
|
29
|
-
expect(mapped()).toEqual([
|
|
29
|
+
expect(mapped()).toEqual(['value-42'])
|
|
30
30
|
})
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
-
describe(
|
|
34
|
-
test(
|
|
33
|
+
describe('caching behavior', () => {
|
|
34
|
+
test('caches results — map function called once per key', () => {
|
|
35
35
|
let callCount = 0
|
|
36
36
|
const items = [1, 2, 3]
|
|
37
37
|
const mapped = mapArray(
|
|
@@ -55,7 +55,7 @@ describe("mapArray", () => {
|
|
|
55
55
|
expect(callCount).toBe(3)
|
|
56
56
|
})
|
|
57
57
|
|
|
58
|
-
test(
|
|
58
|
+
test('only maps new keys when items are added', () => {
|
|
59
59
|
let callCount = 0
|
|
60
60
|
let items = [1, 2, 3]
|
|
61
61
|
const mapped = mapArray(
|
|
@@ -75,7 +75,7 @@ describe("mapArray", () => {
|
|
|
75
75
|
expect(callCount).toBe(5) // only 4 and 5 are new
|
|
76
76
|
})
|
|
77
77
|
|
|
78
|
-
test(
|
|
78
|
+
test('does not re-map when items are removed', () => {
|
|
79
79
|
let callCount = 0
|
|
80
80
|
let items = [1, 2, 3, 4, 5]
|
|
81
81
|
const mapped = mapArray(
|
|
@@ -97,8 +97,8 @@ describe("mapArray", () => {
|
|
|
97
97
|
})
|
|
98
98
|
})
|
|
99
99
|
|
|
100
|
-
describe(
|
|
101
|
-
test(
|
|
100
|
+
describe('key eviction', () => {
|
|
101
|
+
test('evicted keys are re-mapped when they return', () => {
|
|
102
102
|
let callCount = 0
|
|
103
103
|
let items = [1, 2, 3]
|
|
104
104
|
const mapped = mapArray(
|
|
@@ -124,7 +124,7 @@ describe("mapArray", () => {
|
|
|
124
124
|
expect(callCount).toBe(4) // key 2 re-mapped
|
|
125
125
|
})
|
|
126
126
|
|
|
127
|
-
test(
|
|
127
|
+
test('evicts all keys when source becomes empty', () => {
|
|
128
128
|
let callCount = 0
|
|
129
129
|
let items: number[] = [1, 2, 3]
|
|
130
130
|
const mapped = mapArray(
|
|
@@ -150,8 +150,8 @@ describe("mapArray", () => {
|
|
|
150
150
|
})
|
|
151
151
|
})
|
|
152
152
|
|
|
153
|
-
describe(
|
|
154
|
-
test(
|
|
153
|
+
describe('reordering', () => {
|
|
154
|
+
test('reordered items use cached values (no re-mapping)', () => {
|
|
155
155
|
let callCount = 0
|
|
156
156
|
let items = [1, 2, 3]
|
|
157
157
|
const mapped = mapArray(
|
|
@@ -172,7 +172,7 @@ describe("mapArray", () => {
|
|
|
172
172
|
expect(callCount).toBe(3) // no new calls
|
|
173
173
|
})
|
|
174
174
|
|
|
175
|
-
test(
|
|
175
|
+
test('reverse order uses cached values', () => {
|
|
176
176
|
let callCount = 0
|
|
177
177
|
let items = [1, 2, 3, 4]
|
|
178
178
|
const mapped = mapArray(
|
|
@@ -187,21 +187,21 @@ describe("mapArray", () => {
|
|
|
187
187
|
mapped()
|
|
188
188
|
items = [4, 3, 2, 1]
|
|
189
189
|
const result = mapped()
|
|
190
|
-
expect(result).toEqual([
|
|
190
|
+
expect(result).toEqual(['item-4', 'item-3', 'item-2', 'item-1'])
|
|
191
191
|
expect(callCount).toBe(4) // initial 4 only
|
|
192
192
|
})
|
|
193
193
|
})
|
|
194
194
|
|
|
195
|
-
describe(
|
|
196
|
-
test(
|
|
195
|
+
describe('string keys', () => {
|
|
196
|
+
test('works with string keys from objects', () => {
|
|
197
197
|
interface User {
|
|
198
198
|
id: string
|
|
199
199
|
name: string
|
|
200
200
|
}
|
|
201
201
|
let callCount = 0
|
|
202
202
|
let users: User[] = [
|
|
203
|
-
{ id:
|
|
204
|
-
{ id:
|
|
203
|
+
{ id: 'a', name: 'Alice' },
|
|
204
|
+
{ id: 'b', name: 'Bob' },
|
|
205
205
|
]
|
|
206
206
|
const mapped = mapArray(
|
|
207
207
|
() => users,
|
|
@@ -212,22 +212,22 @@ describe("mapArray", () => {
|
|
|
212
212
|
},
|
|
213
213
|
)
|
|
214
214
|
|
|
215
|
-
expect(mapped()).toEqual([
|
|
215
|
+
expect(mapped()).toEqual(['ALICE', 'BOB'])
|
|
216
216
|
expect(callCount).toBe(2)
|
|
217
217
|
|
|
218
218
|
// Add new user
|
|
219
219
|
users = [
|
|
220
|
-
{ id:
|
|
221
|
-
{ id:
|
|
222
|
-
{ id:
|
|
220
|
+
{ id: 'a', name: 'Alice' },
|
|
221
|
+
{ id: 'b', name: 'Bob' },
|
|
222
|
+
{ id: 'c', name: 'Charlie' },
|
|
223
223
|
]
|
|
224
|
-
expect(mapped()).toEqual([
|
|
224
|
+
expect(mapped()).toEqual(['ALICE', 'BOB', 'CHARLIE'])
|
|
225
225
|
expect(callCount).toBe(3)
|
|
226
226
|
})
|
|
227
227
|
})
|
|
228
228
|
|
|
229
|
-
describe(
|
|
230
|
-
test(
|
|
229
|
+
describe('mixed additions and removals', () => {
|
|
230
|
+
test('simultaneous add and remove', () => {
|
|
231
231
|
let callCount = 0
|
|
232
232
|
let items = [1, 2, 3]
|
|
233
233
|
const mapped = mapArray(
|
|
@@ -249,7 +249,7 @@ describe("mapArray", () => {
|
|
|
249
249
|
expect(callCount).toBe(4) // only key 4 is new
|
|
250
250
|
})
|
|
251
251
|
|
|
252
|
-
test(
|
|
252
|
+
test('complete replacement of all items', () => {
|
|
253
253
|
let callCount = 0
|
|
254
254
|
let items = [1, 2, 3]
|
|
255
255
|
const mapped = mapArray(
|
|
@@ -271,8 +271,8 @@ describe("mapArray", () => {
|
|
|
271
271
|
})
|
|
272
272
|
})
|
|
273
273
|
|
|
274
|
-
describe(
|
|
275
|
-
test(
|
|
274
|
+
describe('duplicate keys', () => {
|
|
275
|
+
test('duplicate keys in source share the same cached value', () => {
|
|
276
276
|
let callCount = 0
|
|
277
277
|
const mapped = mapArray(
|
|
278
278
|
() => [1, 1, 2],
|
|
@@ -291,12 +291,12 @@ describe("mapArray", () => {
|
|
|
291
291
|
})
|
|
292
292
|
})
|
|
293
293
|
|
|
294
|
-
describe(
|
|
295
|
-
test(
|
|
294
|
+
describe('map function receives correct item', () => {
|
|
295
|
+
test('map receives the item, not the key', () => {
|
|
296
296
|
const received: Array<{ id: number; val: string }> = []
|
|
297
297
|
const items = [
|
|
298
|
-
{ id: 1, val:
|
|
299
|
-
{ id: 2, val:
|
|
298
|
+
{ id: 1, val: 'a' },
|
|
299
|
+
{ id: 2, val: 'b' },
|
|
300
300
|
]
|
|
301
301
|
const mapped = mapArray(
|
|
302
302
|
() => items,
|
package/src/tests/portal.test.ts
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
import { h } from
|
|
2
|
-
import { Portal, PortalSymbol } from
|
|
3
|
-
import type { VNode } from
|
|
1
|
+
import { h } from '../h'
|
|
2
|
+
import { Portal, PortalSymbol } from '../portal'
|
|
3
|
+
import type { VNode } from '../types'
|
|
4
4
|
|
|
5
|
-
describe(
|
|
6
|
-
test(
|
|
5
|
+
describe('Portal', () => {
|
|
6
|
+
test('returns VNode with PortalSymbol type', () => {
|
|
7
7
|
const fakeTarget = {} as Element
|
|
8
|
-
const node = Portal({ target: fakeTarget, children: h(
|
|
8
|
+
const node = Portal({ target: fakeTarget, children: h('div', null) })
|
|
9
9
|
expect(node.type).toBe(PortalSymbol)
|
|
10
10
|
})
|
|
11
11
|
|
|
12
|
-
test(
|
|
13
|
-
const node = Portal({ target: {} as Element, children:
|
|
12
|
+
test('VNode has null key', () => {
|
|
13
|
+
const node = Portal({ target: {} as Element, children: 'content' })
|
|
14
14
|
expect(node.key).toBeNull()
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
test(
|
|
18
|
-
const node = Portal({ target: {} as Element, children:
|
|
17
|
+
test('VNode has empty children array', () => {
|
|
18
|
+
const node = Portal({ target: {} as Element, children: 'content' })
|
|
19
19
|
expect(node.children).toEqual([])
|
|
20
20
|
})
|
|
21
21
|
|
|
22
|
-
test(
|
|
22
|
+
test('props contain target and children', () => {
|
|
23
23
|
const fakeTarget = {} as Element
|
|
24
|
-
const child = h(
|
|
24
|
+
const child = h('span', null, 'content')
|
|
25
25
|
const node = Portal({ target: fakeTarget, children: child })
|
|
26
26
|
const props = node.props as unknown as { target: Element; children: VNode }
|
|
27
27
|
expect(props.target).toBe(fakeTarget)
|
|
28
28
|
expect(props.children).toBe(child)
|
|
29
29
|
})
|
|
30
30
|
|
|
31
|
-
test(
|
|
32
|
-
expect(typeof PortalSymbol).toBe(
|
|
33
|
-
expect(PortalSymbol.toString()).toContain(
|
|
31
|
+
test('PortalSymbol is a unique symbol', () => {
|
|
32
|
+
expect(typeof PortalSymbol).toBe('symbol')
|
|
33
|
+
expect(PortalSymbol.toString()).toContain('pyreon.Portal')
|
|
34
34
|
})
|
|
35
35
|
|
|
36
|
-
test(
|
|
37
|
-
const node = Portal({ target: {} as Element, children:
|
|
36
|
+
test('string children are stored in props', () => {
|
|
37
|
+
const node = Portal({ target: {} as Element, children: 'text content' })
|
|
38
38
|
const props = node.props as unknown as { children: string }
|
|
39
|
-
expect(props.children).toBe(
|
|
39
|
+
expect(props.children).toBe('text content')
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
-
test(
|
|
43
|
-
const children = h(
|
|
42
|
+
test('multiple VNode children via fragment', () => {
|
|
43
|
+
const children = h('div', null, h('span', null, 'a'), h('span', null, 'b'))
|
|
44
44
|
const node = Portal({ target: {} as Element, children })
|
|
45
45
|
const props = node.props as unknown as { children: VNode }
|
|
46
|
-
expect((props.children as VNode).type).toBe(
|
|
46
|
+
expect((props.children as VNode).type).toBe('div')
|
|
47
47
|
})
|
|
48
48
|
})
|