@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
package/src/tests/show.test.ts
CHANGED
|
@@ -1,238 +1,238 @@
|
|
|
1
|
-
import { h } from
|
|
2
|
-
import { Match, MatchSymbol, Show, Switch } from
|
|
3
|
-
import type { VNodeChild } from
|
|
1
|
+
import { h } from '../h'
|
|
2
|
+
import { Match, MatchSymbol, Show, Switch } from '../show'
|
|
3
|
+
import type { VNodeChild } from '../types'
|
|
4
4
|
|
|
5
|
-
describe(
|
|
6
|
-
test(
|
|
7
|
-
const result = Show({ when: () => true, children:
|
|
8
|
-
expect(typeof result).toBe(
|
|
5
|
+
describe('Show', () => {
|
|
6
|
+
test('returns a reactive getter (function)', () => {
|
|
7
|
+
const result = Show({ when: () => true, children: 'visible' })
|
|
8
|
+
expect(typeof result).toBe('function')
|
|
9
9
|
})
|
|
10
10
|
|
|
11
|
-
test(
|
|
12
|
-
const getter = Show({ when: () => true, children:
|
|
13
|
-
expect(getter()).toBe(
|
|
11
|
+
test('getter returns children when condition is truthy', () => {
|
|
12
|
+
const getter = Show({ when: () => true, children: 'visible' }) as unknown as () => VNodeChild
|
|
13
|
+
expect(getter()).toBe('visible')
|
|
14
14
|
})
|
|
15
15
|
|
|
16
|
-
test(
|
|
17
|
-
const getter = Show({ when: () => false, children:
|
|
16
|
+
test('getter returns null when condition is falsy and no fallback', () => {
|
|
17
|
+
const getter = Show({ when: () => false, children: 'hidden' }) as unknown as () => VNodeChild
|
|
18
18
|
expect(getter()).toBeNull()
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
test(
|
|
22
|
-
const fb = h(
|
|
21
|
+
test('getter returns fallback when condition is falsy', () => {
|
|
22
|
+
const fb = h('span', null, 'fallback')
|
|
23
23
|
const getter = Show({
|
|
24
24
|
when: () => false,
|
|
25
25
|
fallback: fb,
|
|
26
|
-
children:
|
|
26
|
+
children: 'main',
|
|
27
27
|
}) as unknown as () => VNodeChild
|
|
28
28
|
expect(getter()).toBe(fb)
|
|
29
29
|
})
|
|
30
30
|
|
|
31
|
-
test(
|
|
31
|
+
test('reacts to condition changes', () => {
|
|
32
32
|
let flag = true
|
|
33
33
|
const getter = Show({
|
|
34
34
|
when: () => flag,
|
|
35
|
-
children:
|
|
36
|
-
fallback:
|
|
35
|
+
children: 'yes',
|
|
36
|
+
fallback: 'no',
|
|
37
37
|
}) as unknown as () => VNodeChild
|
|
38
|
-
expect(getter()).toBe(
|
|
38
|
+
expect(getter()).toBe('yes')
|
|
39
39
|
flag = false
|
|
40
|
-
expect(getter()).toBe(
|
|
40
|
+
expect(getter()).toBe('no')
|
|
41
41
|
flag = true
|
|
42
|
-
expect(getter()).toBe(
|
|
42
|
+
expect(getter()).toBe('yes')
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
-
test(
|
|
45
|
+
test('returns null for undefined children when truthy', () => {
|
|
46
46
|
const getter = Show({ when: () => true }) as unknown as () => VNodeChild
|
|
47
47
|
expect(getter()).toBeNull()
|
|
48
48
|
})
|
|
49
49
|
|
|
50
|
-
test(
|
|
51
|
-
const getter = Show({ when: () => false, children:
|
|
50
|
+
test('returns null for undefined fallback when falsy', () => {
|
|
51
|
+
const getter = Show({ when: () => false, children: 'x' }) as unknown as () => VNodeChild
|
|
52
52
|
expect(getter()).toBeNull()
|
|
53
53
|
})
|
|
54
54
|
|
|
55
|
-
test(
|
|
56
|
-
const child = h(
|
|
55
|
+
test('VNode children are preserved as-is', () => {
|
|
56
|
+
const child = h('div', null, 'content')
|
|
57
57
|
const getter = Show({ when: () => true, children: child }) as unknown as () => VNodeChild
|
|
58
58
|
expect(getter()).toBe(child)
|
|
59
59
|
})
|
|
60
60
|
|
|
61
|
-
test(
|
|
61
|
+
test('truthiness: non-empty string', () => {
|
|
62
62
|
const getter = Show({
|
|
63
|
-
when: () =>
|
|
64
|
-
children:
|
|
63
|
+
when: () => 'truthy-string',
|
|
64
|
+
children: 'shown',
|
|
65
65
|
}) as unknown as () => VNodeChild
|
|
66
|
-
expect(getter()).toBe(
|
|
66
|
+
expect(getter()).toBe('shown')
|
|
67
67
|
})
|
|
68
68
|
|
|
69
|
-
test(
|
|
69
|
+
test('truthiness: 0 is falsy', () => {
|
|
70
70
|
const getter = Show({
|
|
71
71
|
when: () => 0,
|
|
72
|
-
children:
|
|
73
|
-
fallback:
|
|
72
|
+
children: 'shown',
|
|
73
|
+
fallback: 'hidden',
|
|
74
74
|
}) as unknown as () => VNodeChild
|
|
75
|
-
expect(getter()).toBe(
|
|
75
|
+
expect(getter()).toBe('hidden')
|
|
76
76
|
})
|
|
77
77
|
|
|
78
|
-
test(
|
|
78
|
+
test('truthiness: empty string is falsy', () => {
|
|
79
79
|
const getter = Show({
|
|
80
|
-
when: () =>
|
|
81
|
-
children:
|
|
82
|
-
fallback:
|
|
80
|
+
when: () => '',
|
|
81
|
+
children: 'shown',
|
|
82
|
+
fallback: 'hidden',
|
|
83
83
|
}) as unknown as () => VNodeChild
|
|
84
|
-
expect(getter()).toBe(
|
|
84
|
+
expect(getter()).toBe('hidden')
|
|
85
85
|
})
|
|
86
86
|
|
|
87
|
-
test(
|
|
87
|
+
test('truthiness: null is falsy', () => {
|
|
88
88
|
const getter = Show({
|
|
89
89
|
when: () => null,
|
|
90
|
-
children:
|
|
91
|
-
fallback:
|
|
90
|
+
children: 'shown',
|
|
91
|
+
fallback: 'hidden',
|
|
92
92
|
}) as unknown as () => VNodeChild
|
|
93
|
-
expect(getter()).toBe(
|
|
93
|
+
expect(getter()).toBe('hidden')
|
|
94
94
|
})
|
|
95
95
|
|
|
96
|
-
test(
|
|
96
|
+
test('truthiness: object is truthy', () => {
|
|
97
97
|
const getter = Show({
|
|
98
98
|
when: () => ({ a: 1 }),
|
|
99
|
-
children:
|
|
99
|
+
children: 'shown',
|
|
100
100
|
}) as unknown as () => VNodeChild
|
|
101
|
-
expect(getter()).toBe(
|
|
101
|
+
expect(getter()).toBe('shown')
|
|
102
102
|
})
|
|
103
103
|
})
|
|
104
104
|
|
|
105
|
-
describe(
|
|
106
|
-
test(
|
|
107
|
-
const result = Match({ when: () => true, children:
|
|
105
|
+
describe('Match', () => {
|
|
106
|
+
test('returns null (marker-only component)', () => {
|
|
107
|
+
const result = Match({ when: () => true, children: 'content' })
|
|
108
108
|
expect(result).toBeNull()
|
|
109
109
|
})
|
|
110
110
|
|
|
111
|
-
test(
|
|
112
|
-
expect(typeof MatchSymbol).toBe(
|
|
113
|
-
expect(MatchSymbol.toString()).toContain(
|
|
111
|
+
test('MatchSymbol is a unique symbol', () => {
|
|
112
|
+
expect(typeof MatchSymbol).toBe('symbol')
|
|
113
|
+
expect(MatchSymbol.toString()).toContain('pyreon.Match')
|
|
114
114
|
})
|
|
115
115
|
})
|
|
116
116
|
|
|
117
|
-
describe(
|
|
118
|
-
test(
|
|
117
|
+
describe('Switch', () => {
|
|
118
|
+
test('renders first truthy Match branch', () => {
|
|
119
119
|
const result = Switch({
|
|
120
120
|
children: [
|
|
121
|
-
h(Match, { when: () => false },
|
|
122
|
-
h(Match, { when: () => true },
|
|
123
|
-
h(Match, { when: () => true },
|
|
121
|
+
h(Match, { when: () => false }, 'first'),
|
|
122
|
+
h(Match, { when: () => true }, 'second'),
|
|
123
|
+
h(Match, { when: () => true }, 'third'),
|
|
124
124
|
],
|
|
125
125
|
})
|
|
126
126
|
const getter = result as unknown as () => VNodeChild
|
|
127
|
-
expect(getter()).toBe(
|
|
127
|
+
expect(getter()).toBe('second')
|
|
128
128
|
})
|
|
129
129
|
|
|
130
|
-
test(
|
|
131
|
-
const fb = h(
|
|
130
|
+
test('renders fallback when no match', () => {
|
|
131
|
+
const fb = h('p', null, '404')
|
|
132
132
|
const result = Switch({
|
|
133
133
|
fallback: fb,
|
|
134
|
-
children: [h(Match, { when: () => false },
|
|
134
|
+
children: [h(Match, { when: () => false }, 'a'), h(Match, { when: () => false }, 'b')],
|
|
135
135
|
})
|
|
136
136
|
const getter = result as unknown as () => VNodeChild
|
|
137
137
|
expect(getter()).toBe(fb)
|
|
138
138
|
})
|
|
139
139
|
|
|
140
|
-
test(
|
|
140
|
+
test('returns null when no match and no fallback', () => {
|
|
141
141
|
const result = Switch({
|
|
142
|
-
children: [h(Match, { when: () => false },
|
|
142
|
+
children: [h(Match, { when: () => false }, 'a')],
|
|
143
143
|
})
|
|
144
144
|
const getter = result as unknown as () => VNodeChild
|
|
145
145
|
expect(getter()).toBeNull()
|
|
146
146
|
})
|
|
147
147
|
|
|
148
|
-
test(
|
|
148
|
+
test('handles single child (not array)', () => {
|
|
149
149
|
const result = Switch({
|
|
150
|
-
children: h(Match, { when: () => true },
|
|
150
|
+
children: h(Match, { when: () => true }, 'only'),
|
|
151
151
|
})
|
|
152
152
|
const getter = result as unknown as () => VNodeChild
|
|
153
|
-
expect(getter()).toBe(
|
|
153
|
+
expect(getter()).toBe('only')
|
|
154
154
|
})
|
|
155
155
|
|
|
156
|
-
test(
|
|
156
|
+
test('handles no children', () => {
|
|
157
157
|
const result = Switch({})
|
|
158
158
|
const getter = result as unknown as () => VNodeChild
|
|
159
159
|
expect(getter()).toBeNull()
|
|
160
160
|
})
|
|
161
161
|
|
|
162
|
-
test(
|
|
162
|
+
test('handles null/undefined children', () => {
|
|
163
163
|
const result = Switch({ children: null as unknown as VNodeChild })
|
|
164
164
|
const getter = result as unknown as () => VNodeChild
|
|
165
165
|
expect(getter()).toBeNull()
|
|
166
166
|
})
|
|
167
167
|
|
|
168
|
-
test(
|
|
168
|
+
test('skips non-Match VNode children', () => {
|
|
169
169
|
const result = Switch({
|
|
170
|
-
fallback:
|
|
171
|
-
children: [h(
|
|
170
|
+
fallback: 'default',
|
|
171
|
+
children: [h('div', null, 'not-a-match'), h(Match, { when: () => true }, 'found')],
|
|
172
172
|
})
|
|
173
173
|
const getter = result as unknown as () => VNodeChild
|
|
174
|
-
expect(getter()).toBe(
|
|
174
|
+
expect(getter()).toBe('found')
|
|
175
175
|
})
|
|
176
176
|
|
|
177
|
-
test(
|
|
177
|
+
test('skips non-object children (strings, null)', () => {
|
|
178
178
|
const result = Switch({
|
|
179
|
-
fallback:
|
|
179
|
+
fallback: 'default',
|
|
180
180
|
children: [
|
|
181
181
|
null as unknown as VNodeChild,
|
|
182
|
-
|
|
183
|
-
h(Match, { when: () => true },
|
|
182
|
+
'string-child' as unknown as VNodeChild,
|
|
183
|
+
h(Match, { when: () => true }, 'found'),
|
|
184
184
|
],
|
|
185
185
|
})
|
|
186
186
|
const getter = result as unknown as () => VNodeChild
|
|
187
|
-
expect(getter()).toBe(
|
|
187
|
+
expect(getter()).toBe('found')
|
|
188
188
|
})
|
|
189
189
|
|
|
190
|
-
test(
|
|
190
|
+
test('reacts to condition changes', () => {
|
|
191
191
|
let a = false
|
|
192
192
|
let b = false
|
|
193
193
|
const result = Switch({
|
|
194
|
-
fallback:
|
|
195
|
-
children: [h(Match, { when: () => a },
|
|
194
|
+
fallback: 'none',
|
|
195
|
+
children: [h(Match, { when: () => a }, 'A'), h(Match, { when: () => b }, 'B')],
|
|
196
196
|
})
|
|
197
197
|
const getter = result as unknown as () => VNodeChild
|
|
198
|
-
expect(getter()).toBe(
|
|
198
|
+
expect(getter()).toBe('none')
|
|
199
199
|
b = true
|
|
200
|
-
expect(getter()).toBe(
|
|
200
|
+
expect(getter()).toBe('B')
|
|
201
201
|
a = true
|
|
202
|
-
expect(getter()).toBe(
|
|
202
|
+
expect(getter()).toBe('A') // first match wins
|
|
203
203
|
b = false
|
|
204
|
-
expect(getter()).toBe(
|
|
204
|
+
expect(getter()).toBe('A')
|
|
205
205
|
a = false
|
|
206
|
-
expect(getter()).toBe(
|
|
206
|
+
expect(getter()).toBe('none')
|
|
207
207
|
})
|
|
208
208
|
|
|
209
|
-
test(
|
|
209
|
+
test('Match with multiple children returns array', () => {
|
|
210
210
|
const result = Switch({
|
|
211
|
-
children: [h(Match, { when: () => true },
|
|
211
|
+
children: [h(Match, { when: () => true }, 'child1', 'child2')],
|
|
212
212
|
})
|
|
213
213
|
const getter = result as unknown as () => VNodeChild
|
|
214
214
|
const value = getter()
|
|
215
215
|
expect(Array.isArray(value)).toBe(true)
|
|
216
|
-
expect(value).toEqual([
|
|
216
|
+
expect(value).toEqual(['child1', 'child2'])
|
|
217
217
|
})
|
|
218
218
|
|
|
219
|
-
test(
|
|
219
|
+
test('Match with zero vnode.children falls back to props.children', () => {
|
|
220
220
|
const matchVNode = {
|
|
221
221
|
type: Match,
|
|
222
|
-
props: { when: () => true, children:
|
|
222
|
+
props: { when: () => true, children: 'from-props' },
|
|
223
223
|
children: [],
|
|
224
224
|
key: null,
|
|
225
225
|
} as unknown as VNodeChild
|
|
226
226
|
const result = Switch({ children: [matchVNode] })
|
|
227
227
|
const getter = result as unknown as () => VNodeChild
|
|
228
|
-
expect(getter()).toBe(
|
|
228
|
+
expect(getter()).toBe('from-props')
|
|
229
229
|
})
|
|
230
230
|
|
|
231
|
-
test(
|
|
231
|
+
test('Match with single vnode.children returns it directly (not array)', () => {
|
|
232
232
|
const result = Switch({
|
|
233
|
-
children: [h(Match, { when: () => true },
|
|
233
|
+
children: [h(Match, { when: () => true }, 'single')],
|
|
234
234
|
})
|
|
235
235
|
const getter = result as unknown as () => VNodeChild
|
|
236
|
-
expect(getter()).toBe(
|
|
236
|
+
expect(getter()).toBe('single')
|
|
237
237
|
})
|
|
238
238
|
})
|
package/src/tests/style.test.ts
CHANGED
|
@@ -1,157 +1,157 @@
|
|
|
1
|
-
import { CSS_UNITLESS, cx, normalizeStyleValue, toKebabCase } from
|
|
1
|
+
import { CSS_UNITLESS, cx, normalizeStyleValue, toKebabCase } from '../style'
|
|
2
2
|
|
|
3
3
|
// cx() is extensively tested in cx.test.ts — these tests cover toKebabCase,
|
|
4
4
|
// normalizeStyleValue, and CSS_UNITLESS which are used by runtime-dom/runtime-server.
|
|
5
5
|
|
|
6
|
-
describe(
|
|
7
|
-
test(
|
|
8
|
-
expect(toKebabCase(
|
|
6
|
+
describe('toKebabCase', () => {
|
|
7
|
+
test('converts camelCase to kebab-case', () => {
|
|
8
|
+
expect(toKebabCase('backgroundColor')).toBe('background-color')
|
|
9
9
|
})
|
|
10
10
|
|
|
11
|
-
test(
|
|
12
|
-
expect(toKebabCase(
|
|
11
|
+
test('handles single uppercase letter', () => {
|
|
12
|
+
expect(toKebabCase('zIndex')).toBe('z-index')
|
|
13
13
|
})
|
|
14
14
|
|
|
15
|
-
test(
|
|
16
|
-
expect(toKebabCase(
|
|
15
|
+
test('handles multiple uppercase letters', () => {
|
|
16
|
+
expect(toKebabCase('borderTopLeftRadius')).toBe('border-top-left-radius')
|
|
17
17
|
})
|
|
18
18
|
|
|
19
|
-
test(
|
|
20
|
-
expect(toKebabCase(
|
|
19
|
+
test('returns lowercase string unchanged', () => {
|
|
20
|
+
expect(toKebabCase('color')).toBe('color')
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
-
test(
|
|
24
|
-
expect(toKebabCase(
|
|
23
|
+
test('handles empty string', () => {
|
|
24
|
+
expect(toKebabCase('')).toBe('')
|
|
25
25
|
})
|
|
26
26
|
|
|
27
|
-
test(
|
|
28
|
-
expect(toKebabCase(
|
|
27
|
+
test('handles consecutive uppercase (treated individually)', () => {
|
|
28
|
+
expect(toKebabCase('MSTransform')).toBe('-m-s-transform')
|
|
29
29
|
})
|
|
30
30
|
|
|
31
|
-
test(
|
|
32
|
-
expect(toKebabCase(
|
|
31
|
+
test('handles leading lowercase with single word', () => {
|
|
32
|
+
expect(toKebabCase('opacity')).toBe('opacity')
|
|
33
33
|
})
|
|
34
34
|
})
|
|
35
35
|
|
|
36
|
-
describe(
|
|
37
|
-
test(
|
|
38
|
-
expect(normalizeStyleValue(
|
|
39
|
-
expect(normalizeStyleValue(
|
|
40
|
-
expect(normalizeStyleValue(
|
|
41
|
-
expect(normalizeStyleValue(
|
|
36
|
+
describe('normalizeStyleValue', () => {
|
|
37
|
+
test('appends px to numbers for non-unitless properties', () => {
|
|
38
|
+
expect(normalizeStyleValue('width', 100)).toBe('100px')
|
|
39
|
+
expect(normalizeStyleValue('height', 50)).toBe('50px')
|
|
40
|
+
expect(normalizeStyleValue('padding', 0)).toBe('0px')
|
|
41
|
+
expect(normalizeStyleValue('marginTop', 20)).toBe('20px')
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
-
test(
|
|
45
|
-
expect(normalizeStyleValue(
|
|
46
|
-
expect(normalizeStyleValue(
|
|
47
|
-
expect(normalizeStyleValue(
|
|
48
|
-
expect(normalizeStyleValue(
|
|
49
|
-
expect(normalizeStyleValue(
|
|
50
|
-
expect(normalizeStyleValue(
|
|
51
|
-
expect(normalizeStyleValue(
|
|
52
|
-
expect(normalizeStyleValue(
|
|
53
|
-
expect(normalizeStyleValue(
|
|
54
|
-
expect(normalizeStyleValue(
|
|
55
|
-
expect(normalizeStyleValue(
|
|
44
|
+
test('does not append px to unitless properties', () => {
|
|
45
|
+
expect(normalizeStyleValue('opacity', 0.5)).toBe('0.5')
|
|
46
|
+
expect(normalizeStyleValue('zIndex', 10)).toBe('10')
|
|
47
|
+
expect(normalizeStyleValue('flexGrow', 1)).toBe('1')
|
|
48
|
+
expect(normalizeStyleValue('fontWeight', 700)).toBe('700')
|
|
49
|
+
expect(normalizeStyleValue('lineHeight', 1.5)).toBe('1.5')
|
|
50
|
+
expect(normalizeStyleValue('order', 3)).toBe('3')
|
|
51
|
+
expect(normalizeStyleValue('columns', 2)).toBe('2')
|
|
52
|
+
expect(normalizeStyleValue('flex', 1)).toBe('1')
|
|
53
|
+
expect(normalizeStyleValue('scale', 2)).toBe('2')
|
|
54
|
+
expect(normalizeStyleValue('widows', 2)).toBe('2')
|
|
55
|
+
expect(normalizeStyleValue('orphans', 3)).toBe('3')
|
|
56
56
|
})
|
|
57
57
|
|
|
58
|
-
test(
|
|
59
|
-
expect(normalizeStyleValue(
|
|
60
|
-
expect(normalizeStyleValue(
|
|
61
|
-
expect(normalizeStyleValue(
|
|
58
|
+
test('passes through string values unchanged', () => {
|
|
59
|
+
expect(normalizeStyleValue('width', '100%')).toBe('100%')
|
|
60
|
+
expect(normalizeStyleValue('color', 'red')).toBe('red')
|
|
61
|
+
expect(normalizeStyleValue('display', 'flex')).toBe('flex')
|
|
62
62
|
})
|
|
63
63
|
|
|
64
|
-
test(
|
|
65
|
-
expect(normalizeStyleValue(
|
|
66
|
-
expect(normalizeStyleValue(
|
|
67
|
-
expect(normalizeStyleValue(
|
|
64
|
+
test('converts non-string/non-number to string', () => {
|
|
65
|
+
expect(normalizeStyleValue('display', null)).toBe('null')
|
|
66
|
+
expect(normalizeStyleValue('display', undefined)).toBe('undefined')
|
|
67
|
+
expect(normalizeStyleValue('display', true)).toBe('true')
|
|
68
68
|
})
|
|
69
69
|
|
|
70
|
-
test(
|
|
71
|
-
expect(normalizeStyleValue(
|
|
70
|
+
test('handles zero correctly for non-unitless props', () => {
|
|
71
|
+
expect(normalizeStyleValue('margin', 0)).toBe('0px')
|
|
72
72
|
})
|
|
73
73
|
|
|
74
|
-
test(
|
|
75
|
-
expect(normalizeStyleValue(
|
|
76
|
-
expect(normalizeStyleValue(
|
|
74
|
+
test('handles negative numbers', () => {
|
|
75
|
+
expect(normalizeStyleValue('marginLeft', -10)).toBe('-10px')
|
|
76
|
+
expect(normalizeStyleValue('zIndex', -1)).toBe('-1')
|
|
77
77
|
})
|
|
78
78
|
})
|
|
79
79
|
|
|
80
|
-
describe(
|
|
81
|
-
test(
|
|
80
|
+
describe('CSS_UNITLESS', () => {
|
|
81
|
+
test('is a Set', () => {
|
|
82
82
|
expect(CSS_UNITLESS).toBeInstanceOf(Set)
|
|
83
83
|
})
|
|
84
84
|
|
|
85
|
-
test(
|
|
86
|
-
expect(CSS_UNITLESS.has(
|
|
87
|
-
expect(CSS_UNITLESS.has(
|
|
88
|
-
expect(CSS_UNITLESS.has(
|
|
89
|
-
expect(CSS_UNITLESS.has(
|
|
90
|
-
expect(CSS_UNITLESS.has(
|
|
91
|
-
expect(CSS_UNITLESS.has(
|
|
92
|
-
expect(CSS_UNITLESS.has(
|
|
93
|
-
expect(CSS_UNITLESS.has(
|
|
94
|
-
expect(CSS_UNITLESS.has(
|
|
95
|
-
expect(CSS_UNITLESS.has(
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
test(
|
|
99
|
-
expect(CSS_UNITLESS.has(
|
|
100
|
-
expect(CSS_UNITLESS.has(
|
|
101
|
-
expect(CSS_UNITLESS.has(
|
|
102
|
-
expect(CSS_UNITLESS.has(
|
|
103
|
-
expect(CSS_UNITLESS.has(
|
|
104
|
-
expect(CSS_UNITLESS.has(
|
|
105
|
-
expect(CSS_UNITLESS.has(
|
|
106
|
-
expect(CSS_UNITLESS.has(
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
test(
|
|
110
|
-
expect(CSS_UNITLESS.has(
|
|
111
|
-
expect(CSS_UNITLESS.has(
|
|
112
|
-
expect(CSS_UNITLESS.has(
|
|
113
|
-
expect(CSS_UNITLESS.has(
|
|
114
|
-
expect(CSS_UNITLESS.has(
|
|
115
|
-
expect(CSS_UNITLESS.has(
|
|
116
|
-
expect(CSS_UNITLESS.has(
|
|
117
|
-
expect(CSS_UNITLESS.has(
|
|
85
|
+
test('contains common unitless properties', () => {
|
|
86
|
+
expect(CSS_UNITLESS.has('opacity')).toBe(true)
|
|
87
|
+
expect(CSS_UNITLESS.has('zIndex')).toBe(true)
|
|
88
|
+
expect(CSS_UNITLESS.has('fontWeight')).toBe(true)
|
|
89
|
+
expect(CSS_UNITLESS.has('lineHeight')).toBe(true)
|
|
90
|
+
expect(CSS_UNITLESS.has('flex')).toBe(true)
|
|
91
|
+
expect(CSS_UNITLESS.has('flexGrow')).toBe(true)
|
|
92
|
+
expect(CSS_UNITLESS.has('flexShrink')).toBe(true)
|
|
93
|
+
expect(CSS_UNITLESS.has('order')).toBe(true)
|
|
94
|
+
expect(CSS_UNITLESS.has('columnCount')).toBe(true)
|
|
95
|
+
expect(CSS_UNITLESS.has('animationIterationCount')).toBe(true)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test('contains SVG unitless properties', () => {
|
|
99
|
+
expect(CSS_UNITLESS.has('fillOpacity')).toBe(true)
|
|
100
|
+
expect(CSS_UNITLESS.has('floodOpacity')).toBe(true)
|
|
101
|
+
expect(CSS_UNITLESS.has('stopOpacity')).toBe(true)
|
|
102
|
+
expect(CSS_UNITLESS.has('strokeOpacity')).toBe(true)
|
|
103
|
+
expect(CSS_UNITLESS.has('strokeWidth')).toBe(true)
|
|
104
|
+
expect(CSS_UNITLESS.has('strokeMiterlimit')).toBe(true)
|
|
105
|
+
expect(CSS_UNITLESS.has('strokeDasharray')).toBe(true)
|
|
106
|
+
expect(CSS_UNITLESS.has('strokeDashoffset')).toBe(true)
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
test('does not contain properties that need units', () => {
|
|
110
|
+
expect(CSS_UNITLESS.has('width')).toBe(false)
|
|
111
|
+
expect(CSS_UNITLESS.has('height')).toBe(false)
|
|
112
|
+
expect(CSS_UNITLESS.has('margin')).toBe(false)
|
|
113
|
+
expect(CSS_UNITLESS.has('padding')).toBe(false)
|
|
114
|
+
expect(CSS_UNITLESS.has('fontSize')).toBe(false)
|
|
115
|
+
expect(CSS_UNITLESS.has('borderWidth')).toBe(false)
|
|
116
|
+
expect(CSS_UNITLESS.has('top')).toBe(false)
|
|
117
|
+
expect(CSS_UNITLESS.has('left')).toBe(false)
|
|
118
118
|
})
|
|
119
119
|
})
|
|
120
120
|
|
|
121
|
-
describe(
|
|
122
|
-
test(
|
|
123
|
-
expect(cx({ a: false, b: false, c: false })).toBe(
|
|
121
|
+
describe('cx — additional edge cases', () => {
|
|
122
|
+
test('object with all false values', () => {
|
|
123
|
+
expect(cx({ a: false, b: false, c: false })).toBe('')
|
|
124
124
|
})
|
|
125
125
|
|
|
126
|
-
test(
|
|
127
|
-
expect(cx({ a: null, b: undefined, c: true })).toBe(
|
|
126
|
+
test('object with null and undefined values', () => {
|
|
127
|
+
expect(cx({ a: null, b: undefined, c: true })).toBe('c')
|
|
128
128
|
})
|
|
129
129
|
|
|
130
|
-
test(
|
|
131
|
-
expect(cx([1,
|
|
130
|
+
test('mixed array of numbers, strings, and objects', () => {
|
|
131
|
+
expect(cx([1, 'two', { three: true, four: false }])).toBe('1 two three')
|
|
132
132
|
})
|
|
133
133
|
|
|
134
|
-
test(
|
|
135
|
-
expect(cx([
|
|
134
|
+
test('single-element array', () => {
|
|
135
|
+
expect(cx(['only'])).toBe('only')
|
|
136
136
|
})
|
|
137
137
|
|
|
138
|
-
test(
|
|
139
|
-
expect(cx([0,
|
|
138
|
+
test('number 0 in an array', () => {
|
|
139
|
+
expect(cx([0, 'one'])).toBe('0 one')
|
|
140
140
|
})
|
|
141
141
|
|
|
142
|
-
test(
|
|
143
|
-
expect(cx([true,
|
|
142
|
+
test('boolean true in array is filtered', () => {
|
|
143
|
+
expect(cx([true, 'visible'])).toBe('visible')
|
|
144
144
|
})
|
|
145
145
|
|
|
146
|
-
test(
|
|
147
|
-
expect(cx([[], [[]], [[[]]]])).toBe(
|
|
146
|
+
test('nested empty arrays', () => {
|
|
147
|
+
expect(cx([[], [[]], [[[]]]])).toBe('')
|
|
148
148
|
})
|
|
149
149
|
|
|
150
|
-
test(
|
|
151
|
-
expect(cx({ hidden: () => false })).toBe(
|
|
150
|
+
test('object with function returning false', () => {
|
|
151
|
+
expect(cx({ hidden: () => false })).toBe('')
|
|
152
152
|
})
|
|
153
153
|
|
|
154
|
-
test(
|
|
155
|
-
expect(cx({ active: true })).toBe(
|
|
154
|
+
test('single key object', () => {
|
|
155
|
+
expect(cx({ active: true })).toBe('active')
|
|
156
156
|
})
|
|
157
157
|
})
|