@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
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { _resetIdCounter, createUniqueId, mergeProps, splitProps } from
|
|
1
|
+
import { _resetIdCounter, createUniqueId, mergeProps, splitProps } from '../props'
|
|
2
2
|
|
|
3
|
-
describe(
|
|
4
|
-
test(
|
|
3
|
+
describe('createUniqueId — extended', () => {
|
|
4
|
+
test('returns pyreon- prefixed string', () => {
|
|
5
5
|
const id = createUniqueId()
|
|
6
6
|
expect(id).toMatch(/^pyreon-\d+$/)
|
|
7
7
|
})
|
|
8
8
|
|
|
9
|
-
test(
|
|
9
|
+
test('returns incrementing values', () => {
|
|
10
10
|
const id1 = createUniqueId()
|
|
11
11
|
const id2 = createUniqueId()
|
|
12
12
|
const id3 = createUniqueId()
|
|
13
|
-
const num1 = Number.parseInt(id1.replace(
|
|
14
|
-
const num2 = Number.parseInt(id2.replace(
|
|
15
|
-
const num3 = Number.parseInt(id3.replace(
|
|
13
|
+
const num1 = Number.parseInt(id1.replace('pyreon-', ''), 10)
|
|
14
|
+
const num2 = Number.parseInt(id2.replace('pyreon-', ''), 10)
|
|
15
|
+
const num3 = Number.parseInt(id3.replace('pyreon-', ''), 10)
|
|
16
16
|
expect(num2).toBe(num1 + 1)
|
|
17
17
|
expect(num3).toBe(num2 + 1)
|
|
18
18
|
})
|
|
19
19
|
|
|
20
|
-
test(
|
|
20
|
+
test('all IDs are unique', () => {
|
|
21
21
|
const ids = new Set<string>()
|
|
22
22
|
for (let i = 0; i < 100; i++) {
|
|
23
23
|
ids.add(createUniqueId())
|
|
@@ -26,8 +26,8 @@ describe("createUniqueId — extended", () => {
|
|
|
26
26
|
})
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
describe(
|
|
30
|
-
test(
|
|
29
|
+
describe('_resetIdCounter', () => {
|
|
30
|
+
test('resets the counter so IDs restart', () => {
|
|
31
31
|
// Generate some IDs to advance counter
|
|
32
32
|
createUniqueId()
|
|
33
33
|
createUniqueId()
|
|
@@ -35,121 +35,121 @@ describe("_resetIdCounter", () => {
|
|
|
35
35
|
_resetIdCounter()
|
|
36
36
|
|
|
37
37
|
const id = createUniqueId()
|
|
38
|
-
expect(id).toBe(
|
|
38
|
+
expect(id).toBe('pyreon-1')
|
|
39
39
|
})
|
|
40
40
|
|
|
41
|
-
test(
|
|
41
|
+
test('subsequent calls after reset increment from 1', () => {
|
|
42
42
|
_resetIdCounter()
|
|
43
|
-
expect(createUniqueId()).toBe(
|
|
44
|
-
expect(createUniqueId()).toBe(
|
|
45
|
-
expect(createUniqueId()).toBe(
|
|
43
|
+
expect(createUniqueId()).toBe('pyreon-1')
|
|
44
|
+
expect(createUniqueId()).toBe('pyreon-2')
|
|
45
|
+
expect(createUniqueId()).toBe('pyreon-3')
|
|
46
46
|
})
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
-
describe(
|
|
50
|
-
test(
|
|
49
|
+
describe('splitProps — extended', () => {
|
|
50
|
+
test('non-existent keys produce empty picked object', () => {
|
|
51
51
|
const props = { a: 1, b: 2 }
|
|
52
|
-
const [own, rest] = splitProps(props, [
|
|
52
|
+
const [own, rest] = splitProps(props, ['c' as keyof typeof props])
|
|
53
53
|
expect(Object.keys(own)).toEqual([])
|
|
54
54
|
expect(rest).toEqual({ a: 1, b: 2 })
|
|
55
55
|
})
|
|
56
56
|
|
|
57
|
-
test(
|
|
57
|
+
test('all keys in picked leaves rest empty', () => {
|
|
58
58
|
const props = { x: 10, y: 20 }
|
|
59
|
-
const [own, rest] = splitProps(props, [
|
|
59
|
+
const [own, rest] = splitProps(props, ['x', 'y'])
|
|
60
60
|
expect(own).toEqual({ x: 10, y: 20 })
|
|
61
61
|
expect(Object.keys(rest)).toEqual([])
|
|
62
62
|
})
|
|
63
63
|
|
|
64
|
-
test(
|
|
64
|
+
test('preserves getter on rest side', () => {
|
|
65
65
|
let count = 0
|
|
66
66
|
const props = {} as Record<string, unknown>
|
|
67
|
-
Object.defineProperty(props,
|
|
67
|
+
Object.defineProperty(props, 'reactive', {
|
|
68
68
|
get: () => ++count,
|
|
69
69
|
enumerable: true,
|
|
70
70
|
configurable: true,
|
|
71
71
|
})
|
|
72
|
-
Object.defineProperty(props,
|
|
73
|
-
value:
|
|
72
|
+
Object.defineProperty(props, 'other', {
|
|
73
|
+
value: 'static',
|
|
74
74
|
enumerable: true,
|
|
75
75
|
configurable: true,
|
|
76
76
|
})
|
|
77
77
|
|
|
78
|
-
const [_own, rest] = splitProps(props, [
|
|
78
|
+
const [_own, rest] = splitProps(props, ['other'])
|
|
79
79
|
expect((rest as Record<string, unknown>).reactive).toBe(1)
|
|
80
80
|
expect((rest as Record<string, unknown>).reactive).toBe(2) // getter called again
|
|
81
81
|
})
|
|
82
82
|
|
|
83
|
-
test(
|
|
84
|
-
const props = { a: undefined, b:
|
|
85
|
-
const [own, rest] = splitProps(props, [
|
|
83
|
+
test('handles object with undefined values', () => {
|
|
84
|
+
const props = { a: undefined, b: 'defined' }
|
|
85
|
+
const [own, rest] = splitProps(props, ['a'])
|
|
86
86
|
expect(own.a).toBeUndefined()
|
|
87
|
-
expect((rest as Record<string, unknown>).b).toBe(
|
|
87
|
+
expect((rest as Record<string, unknown>).b).toBe('defined')
|
|
88
88
|
})
|
|
89
89
|
})
|
|
90
90
|
|
|
91
|
-
describe(
|
|
92
|
-
test(
|
|
91
|
+
describe('mergeProps — extended', () => {
|
|
92
|
+
test('single source returns copy', () => {
|
|
93
93
|
const src = { a: 1, b: 2 }
|
|
94
94
|
const result = mergeProps(src)
|
|
95
95
|
expect(result).toEqual({ a: 1, b: 2 })
|
|
96
96
|
expect(result).not.toBe(src) // should be a new object
|
|
97
97
|
})
|
|
98
98
|
|
|
99
|
-
test(
|
|
99
|
+
test('three sources merge correctly', () => {
|
|
100
100
|
const result = mergeProps({ a: 1 }, { b: 2 }, { c: 3 })
|
|
101
101
|
expect(result).toEqual({ a: 1, b: 2, c: 3 })
|
|
102
102
|
})
|
|
103
103
|
|
|
104
|
-
test(
|
|
105
|
-
const result = mergeProps({ x:
|
|
106
|
-
expect(result.x).toBe(
|
|
104
|
+
test('later defined value overrides earlier', () => {
|
|
105
|
+
const result = mergeProps({ x: 'first' }, { x: 'second' }, { x: 'third' })
|
|
106
|
+
expect(result.x).toBe('third')
|
|
107
107
|
})
|
|
108
108
|
|
|
109
|
-
test(
|
|
110
|
-
const result = mergeProps({ x:
|
|
111
|
-
expect(result.x).toBe(
|
|
109
|
+
test('undefined in later source does not override earlier defined value', () => {
|
|
110
|
+
const result = mergeProps({ x: 'keep' }, { x: undefined as string | undefined })
|
|
111
|
+
expect(result.x).toBe('keep')
|
|
112
112
|
})
|
|
113
113
|
|
|
114
|
-
test(
|
|
115
|
-
let dynamic: string | undefined =
|
|
114
|
+
test('getter merging: later getter overrides earlier static when defined', () => {
|
|
115
|
+
let dynamic: string | undefined = 'from-getter'
|
|
116
116
|
const getterSrc = {} as Record<string, unknown>
|
|
117
|
-
Object.defineProperty(getterSrc,
|
|
117
|
+
Object.defineProperty(getterSrc, 'val', {
|
|
118
118
|
get: () => dynamic,
|
|
119
119
|
enumerable: true,
|
|
120
120
|
configurable: true,
|
|
121
121
|
})
|
|
122
|
-
const result = mergeProps({ val:
|
|
123
|
-
expect(result.val).toBe(
|
|
122
|
+
const result = mergeProps({ val: 'static' }, getterSrc)
|
|
123
|
+
expect(result.val).toBe('from-getter')
|
|
124
124
|
|
|
125
125
|
// When getter returns undefined, falls back to static
|
|
126
126
|
dynamic = undefined
|
|
127
|
-
expect(result.val).toBe(
|
|
127
|
+
expect(result.val).toBe('static')
|
|
128
128
|
})
|
|
129
129
|
|
|
130
|
-
test(
|
|
131
|
-
let g1val: string | undefined =
|
|
132
|
-
let g2val: string | undefined =
|
|
130
|
+
test('two getters: later getter wins when defined, falls to earlier getter', () => {
|
|
131
|
+
let g1val: string | undefined = 'g1'
|
|
132
|
+
let g2val: string | undefined = 'g2'
|
|
133
133
|
|
|
134
134
|
const src1 = {} as Record<string, unknown>
|
|
135
|
-
Object.defineProperty(src1,
|
|
135
|
+
Object.defineProperty(src1, 'x', {
|
|
136
136
|
get: () => g1val,
|
|
137
137
|
enumerable: true,
|
|
138
138
|
configurable: true,
|
|
139
139
|
})
|
|
140
140
|
|
|
141
141
|
const src2 = {} as Record<string, unknown>
|
|
142
|
-
Object.defineProperty(src2,
|
|
142
|
+
Object.defineProperty(src2, 'x', {
|
|
143
143
|
get: () => g2val,
|
|
144
144
|
enumerable: true,
|
|
145
145
|
configurable: true,
|
|
146
146
|
})
|
|
147
147
|
|
|
148
148
|
const result = mergeProps(src1, src2)
|
|
149
|
-
expect(result.x).toBe(
|
|
149
|
+
expect(result.x).toBe('g2')
|
|
150
150
|
|
|
151
151
|
g2val = undefined
|
|
152
|
-
expect(result.x).toBe(
|
|
152
|
+
expect(result.x).toBe('g1')
|
|
153
153
|
|
|
154
154
|
g1val = undefined
|
|
155
155
|
expect(result.x).toBeUndefined()
|
package/src/tests/props.test.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { createUniqueId, mergeProps, splitProps } from
|
|
1
|
+
import { createUniqueId, mergeProps, splitProps } from '../props'
|
|
2
2
|
|
|
3
|
-
describe(
|
|
4
|
-
test(
|
|
5
|
-
const props = { label:
|
|
6
|
-
const [own, html] = splitProps(props, [
|
|
7
|
-
expect(own).toEqual({ label:
|
|
8
|
-
expect(html).toEqual({ class:
|
|
3
|
+
describe('splitProps', () => {
|
|
4
|
+
test('splits known keys from rest', () => {
|
|
5
|
+
const props = { label: 'Hi', icon: 'star', class: 'btn', id: 'x' }
|
|
6
|
+
const [own, html] = splitProps(props, ['label', 'icon'])
|
|
7
|
+
expect(own).toEqual({ label: 'Hi', icon: 'star' })
|
|
8
|
+
expect(html).toEqual({ class: 'btn', id: 'x' })
|
|
9
9
|
})
|
|
10
10
|
|
|
11
|
-
test(
|
|
11
|
+
test('preserves getters', () => {
|
|
12
12
|
let count = 0
|
|
13
|
-
const props = Object.defineProperty({} as Record<string, unknown>,
|
|
13
|
+
const props = Object.defineProperty({} as Record<string, unknown>, 'value', {
|
|
14
14
|
get: () => ++count,
|
|
15
15
|
enumerable: true,
|
|
16
16
|
configurable: true,
|
|
17
17
|
})
|
|
18
|
-
const [own] = splitProps(props, [
|
|
18
|
+
const [own] = splitProps(props, ['value'])
|
|
19
19
|
expect(own.value).toBe(1)
|
|
20
20
|
expect(own.value).toBe(2) // getter called again
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
-
test(
|
|
23
|
+
test('handles empty keys array', () => {
|
|
24
24
|
const props = { a: 1, b: 2 }
|
|
25
25
|
const [own, rest] = splitProps(props, [])
|
|
26
26
|
expect(own).toEqual({})
|
|
@@ -28,20 +28,20 @@ describe("splitProps", () => {
|
|
|
28
28
|
})
|
|
29
29
|
})
|
|
30
30
|
|
|
31
|
-
describe(
|
|
32
|
-
test(
|
|
31
|
+
describe('mergeProps', () => {
|
|
32
|
+
test('later sources override earlier', () => {
|
|
33
33
|
const result = mergeProps({ a: 1, b: 2 }, { b: 3, c: 4 })
|
|
34
34
|
expect(result).toEqual({ a: 1, b: 3, c: 4 })
|
|
35
35
|
})
|
|
36
36
|
|
|
37
37
|
test("undefined values don't override defined", () => {
|
|
38
|
-
const result = mergeProps({ size:
|
|
39
|
-
expect(result.size).toBe(
|
|
38
|
+
const result = mergeProps({ size: 'md' }, { size: undefined as string | undefined })
|
|
39
|
+
expect(result.size).toBe('md')
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
-
test(
|
|
42
|
+
test('preserves getters from sources', () => {
|
|
43
43
|
let count = 0
|
|
44
|
-
const source = Object.defineProperty({} as Record<string, unknown>,
|
|
44
|
+
const source = Object.defineProperty({} as Record<string, unknown>, 'val', {
|
|
45
45
|
get: () => ++count,
|
|
46
46
|
enumerable: true,
|
|
47
47
|
configurable: true,
|
|
@@ -51,85 +51,85 @@ describe("mergeProps", () => {
|
|
|
51
51
|
expect(result.val).toBe(2)
|
|
52
52
|
})
|
|
53
53
|
|
|
54
|
-
test(
|
|
54
|
+
test('getter returning undefined falls back to previous value', () => {
|
|
55
55
|
let override: string | undefined
|
|
56
|
-
const source = Object.defineProperty({} as Record<string, unknown>,
|
|
56
|
+
const source = Object.defineProperty({} as Record<string, unknown>, 'size', {
|
|
57
57
|
get: () => override,
|
|
58
58
|
enumerable: true,
|
|
59
59
|
configurable: true,
|
|
60
60
|
})
|
|
61
|
-
const result = mergeProps({ size:
|
|
62
|
-
expect(result.size).toBe(
|
|
61
|
+
const result = mergeProps({ size: 'md' }, source)
|
|
62
|
+
expect(result.size).toBe('md') // getter returns undefined, fallback
|
|
63
63
|
|
|
64
|
-
override =
|
|
65
|
-
expect(result.size).toBe(
|
|
64
|
+
override = 'lg'
|
|
65
|
+
expect(result.size).toBe('lg') // getter returns value
|
|
66
66
|
})
|
|
67
67
|
})
|
|
68
68
|
|
|
69
|
-
describe(
|
|
70
|
-
test(
|
|
71
|
-
let dynamicSize =
|
|
72
|
-
const source1 = { size:
|
|
73
|
-
const source2 = Object.defineProperty({} as Record<string, unknown>,
|
|
69
|
+
describe('mergeProps — edge cases', () => {
|
|
70
|
+
test('mixed getter/static value merging across 3+ sources', () => {
|
|
71
|
+
let dynamicSize = 'sm'
|
|
72
|
+
const source1 = { size: 'md', variant: 'primary' }
|
|
73
|
+
const source2 = Object.defineProperty({} as Record<string, unknown>, 'size', {
|
|
74
74
|
get: () => dynamicSize,
|
|
75
75
|
enumerable: true,
|
|
76
76
|
configurable: true,
|
|
77
77
|
})
|
|
78
|
-
const source3 = { color:
|
|
78
|
+
const source3 = { color: 'red' }
|
|
79
79
|
const result = mergeProps(source1, source2, source3)
|
|
80
|
-
expect(result.size).toBe(
|
|
81
|
-
dynamicSize =
|
|
82
|
-
expect(result.size).toBe(
|
|
83
|
-
expect((result as Record<string, unknown>).variant).toBe(
|
|
84
|
-
expect((result as Record<string, unknown>).color).toBe(
|
|
80
|
+
expect(result.size).toBe('sm')
|
|
81
|
+
dynamicSize = 'xl'
|
|
82
|
+
expect(result.size).toBe('xl')
|
|
83
|
+
expect((result as Record<string, unknown>).variant).toBe('primary')
|
|
84
|
+
expect((result as Record<string, unknown>).color).toBe('red')
|
|
85
85
|
})
|
|
86
86
|
|
|
87
|
-
test(
|
|
87
|
+
test('getter returning undefined falling through multiple levels of defaults', () => {
|
|
88
88
|
let level2: string | undefined
|
|
89
89
|
let level1: string | undefined
|
|
90
|
-
const defaults = { theme:
|
|
91
|
-
const mid = Object.defineProperty({} as Record<string, unknown>,
|
|
90
|
+
const defaults = { theme: 'light' }
|
|
91
|
+
const mid = Object.defineProperty({} as Record<string, unknown>, 'theme', {
|
|
92
92
|
get: () => level1,
|
|
93
93
|
enumerable: true,
|
|
94
94
|
configurable: true,
|
|
95
95
|
})
|
|
96
|
-
const top = Object.defineProperty({} as Record<string, unknown>,
|
|
96
|
+
const top = Object.defineProperty({} as Record<string, unknown>, 'theme', {
|
|
97
97
|
get: () => level2,
|
|
98
98
|
enumerable: true,
|
|
99
99
|
configurable: true,
|
|
100
100
|
})
|
|
101
101
|
const result = mergeProps(defaults, mid, top)
|
|
102
102
|
// Both getters return undefined — falls back to "light"
|
|
103
|
-
expect(result.theme).toBe(
|
|
103
|
+
expect(result.theme).toBe('light')
|
|
104
104
|
// Mid-level getter returns value — top still undefined, falls to mid
|
|
105
|
-
level1 =
|
|
106
|
-
expect(result.theme).toBe(
|
|
105
|
+
level1 = 'dark'
|
|
106
|
+
expect(result.theme).toBe('dark')
|
|
107
107
|
// Top-level getter returns value — wins
|
|
108
|
-
level2 =
|
|
109
|
-
expect(result.theme).toBe(
|
|
108
|
+
level2 = 'system'
|
|
109
|
+
expect(result.theme).toBe('system')
|
|
110
110
|
})
|
|
111
111
|
|
|
112
|
-
test(
|
|
112
|
+
test('mergeProps with no sources (empty call)', () => {
|
|
113
113
|
const result = mergeProps()
|
|
114
114
|
expect(result).toEqual({})
|
|
115
115
|
})
|
|
116
116
|
|
|
117
|
-
test(
|
|
118
|
-
const dynamic =
|
|
119
|
-
const getterSource = Object.defineProperty({} as Record<string, unknown>,
|
|
117
|
+
test('later source static value overriding earlier getter', () => {
|
|
118
|
+
const dynamic = 'from-getter'
|
|
119
|
+
const getterSource = Object.defineProperty({} as Record<string, unknown>, 'val', {
|
|
120
120
|
get: () => dynamic,
|
|
121
121
|
enumerable: true,
|
|
122
122
|
configurable: true,
|
|
123
123
|
})
|
|
124
|
-
const staticSource = { val:
|
|
124
|
+
const staticSource = { val: 'static-wins' }
|
|
125
125
|
const result = mergeProps(getterSource, staticSource)
|
|
126
126
|
// Static value should override getter
|
|
127
|
-
expect(result.val).toBe(
|
|
127
|
+
expect(result.val).toBe('static-wins')
|
|
128
128
|
})
|
|
129
129
|
|
|
130
|
-
test(
|
|
131
|
-
let dynamic =
|
|
132
|
-
const getterSource = Object.defineProperty({} as Record<string, unknown>,
|
|
130
|
+
test('later source static undefined does not override earlier getter', () => {
|
|
131
|
+
let dynamic = 'from-getter'
|
|
132
|
+
const getterSource = Object.defineProperty({} as Record<string, unknown>, 'val', {
|
|
133
133
|
get: () => dynamic,
|
|
134
134
|
enumerable: true,
|
|
135
135
|
configurable: true,
|
|
@@ -137,31 +137,31 @@ describe("mergeProps — edge cases", () => {
|
|
|
137
137
|
const staticSource = { val: undefined }
|
|
138
138
|
const result = mergeProps(getterSource, staticSource)
|
|
139
139
|
// Static undefined — getter should still be used
|
|
140
|
-
expect(result.val).toBe(
|
|
141
|
-
dynamic =
|
|
142
|
-
expect(result.val).toBe(
|
|
140
|
+
expect(result.val).toBe('from-getter')
|
|
141
|
+
dynamic = 'updated'
|
|
142
|
+
expect(result.val).toBe('updated')
|
|
143
143
|
})
|
|
144
144
|
})
|
|
145
145
|
|
|
146
|
-
describe(
|
|
147
|
-
test(
|
|
146
|
+
describe('splitProps — getter reactivity', () => {
|
|
147
|
+
test('preserves getter reactivity through multiple reads', () => {
|
|
148
148
|
let count = 0
|
|
149
|
-
const props = Object.defineProperty({ other:
|
|
149
|
+
const props = Object.defineProperty({ other: 'x' } as Record<string, unknown>, 'value', {
|
|
150
150
|
get: () => ++count,
|
|
151
151
|
enumerable: true,
|
|
152
152
|
configurable: true,
|
|
153
153
|
})
|
|
154
|
-
const [own, rest] = splitProps(props, [
|
|
154
|
+
const [own, rest] = splitProps(props, ['value'])
|
|
155
155
|
expect(own.value).toBe(1)
|
|
156
156
|
expect(own.value).toBe(2)
|
|
157
157
|
expect(own.value).toBe(3)
|
|
158
158
|
// rest should not include the getter key
|
|
159
|
-
expect(rest).toEqual({ other:
|
|
159
|
+
expect(rest).toEqual({ other: 'x' })
|
|
160
160
|
})
|
|
161
161
|
})
|
|
162
162
|
|
|
163
|
-
describe(
|
|
164
|
-
test(
|
|
163
|
+
describe('createUniqueId', () => {
|
|
164
|
+
test('returns incrementing IDs', () => {
|
|
165
165
|
const id1 = createUniqueId()
|
|
166
166
|
const id2 = createUniqueId()
|
|
167
167
|
expect(id1).toMatch(/^pyreon-\d+$/)
|
package/src/tests/ref.test.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import type { Ref, RefCallback, RefProp } from
|
|
2
|
-
import { createRef } from
|
|
1
|
+
import type { Ref, RefCallback, RefProp } from '../ref'
|
|
2
|
+
import { createRef } from '../ref'
|
|
3
3
|
|
|
4
|
-
describe(
|
|
5
|
-
test(
|
|
4
|
+
describe('createRef', () => {
|
|
5
|
+
test('returns object with current = null', () => {
|
|
6
6
|
const ref = createRef()
|
|
7
7
|
expect(ref.current).toBeNull()
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
-
test(
|
|
10
|
+
test('current is mutable', () => {
|
|
11
11
|
const ref = createRef<number>()
|
|
12
12
|
ref.current = 42
|
|
13
13
|
expect(ref.current).toBe(42)
|
|
14
14
|
})
|
|
15
15
|
|
|
16
|
-
test(
|
|
16
|
+
test('typed ref — HTMLElement', () => {
|
|
17
17
|
const ref = createRef<HTMLDivElement>()
|
|
18
18
|
expect(ref.current).toBeNull()
|
|
19
19
|
// In real code, runtime-dom sets this after mount
|
|
@@ -21,13 +21,13 @@ describe("createRef", () => {
|
|
|
21
21
|
expect(ref.current).not.toBeNull()
|
|
22
22
|
})
|
|
23
23
|
|
|
24
|
-
test(
|
|
24
|
+
test('typed ref — string', () => {
|
|
25
25
|
const ref = createRef<string>()
|
|
26
|
-
ref.current =
|
|
27
|
-
expect(ref.current).toBe(
|
|
26
|
+
ref.current = 'hello'
|
|
27
|
+
expect(ref.current).toBe('hello')
|
|
28
28
|
})
|
|
29
29
|
|
|
30
|
-
test(
|
|
30
|
+
test('can be reset to null', () => {
|
|
31
31
|
const ref = createRef<number>()
|
|
32
32
|
ref.current = 99
|
|
33
33
|
expect(ref.current).toBe(99)
|
|
@@ -35,36 +35,36 @@ describe("createRef", () => {
|
|
|
35
35
|
expect(ref.current).toBeNull()
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
-
test(
|
|
38
|
+
test('each createRef returns a unique object', () => {
|
|
39
39
|
const ref1 = createRef()
|
|
40
40
|
const ref2 = createRef()
|
|
41
41
|
expect(ref1).not.toBe(ref2)
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
-
test(
|
|
44
|
+
test('ref object has exactly one property', () => {
|
|
45
45
|
const ref = createRef()
|
|
46
|
-
expect(Object.keys(ref)).toEqual([
|
|
46
|
+
expect(Object.keys(ref)).toEqual(['current'])
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
-
test(
|
|
49
|
+
test('ref object shape matches Ref interface', () => {
|
|
50
50
|
const ref: Ref<number> = createRef<number>()
|
|
51
|
-
expect(
|
|
51
|
+
expect('current' in ref).toBe(true)
|
|
52
52
|
expect(ref.current).toBeNull()
|
|
53
53
|
})
|
|
54
54
|
})
|
|
55
55
|
|
|
56
|
-
describe(
|
|
57
|
-
test(
|
|
56
|
+
describe('RefCallback type (type-level verification)', () => {
|
|
57
|
+
test('callback ref can be assigned to RefProp', () => {
|
|
58
58
|
const callback: RefCallback<HTMLElement> = (_el) => {}
|
|
59
59
|
// Type-level test: RefProp accepts both object ref and callback ref
|
|
60
60
|
const prop: RefProp<HTMLElement> = callback
|
|
61
|
-
expect(typeof prop).toBe(
|
|
61
|
+
expect(typeof prop).toBe('function')
|
|
62
62
|
})
|
|
63
63
|
|
|
64
|
-
test(
|
|
64
|
+
test('object ref can be assigned to RefProp', () => {
|
|
65
65
|
const ref = createRef<HTMLElement>()
|
|
66
66
|
const prop: RefProp<HTMLElement> = ref
|
|
67
|
-
expect(typeof prop).toBe(
|
|
67
|
+
expect(typeof prop).toBe('object')
|
|
68
68
|
expect(prop).toBe(ref)
|
|
69
69
|
})
|
|
70
70
|
})
|