@pyreon/elements 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 +38 -35
- package/lib/index.d.ts +15 -15
- package/package.json +24 -24
- package/src/Element/component.tsx +14 -14
- package/src/Element/constants.ts +25 -25
- package/src/Element/index.ts +2 -2
- package/src/Element/types.ts +3 -3
- package/src/Element/utils.ts +1 -1
- package/src/List/component.tsx +7 -7
- package/src/List/index.ts +2 -2
- package/src/Overlay/component.tsx +22 -22
- package/src/Overlay/context.tsx +2 -2
- package/src/Overlay/index.ts +3 -3
- package/src/Overlay/useOverlay.tsx +97 -97
- package/src/Portal/component.tsx +6 -6
- package/src/Portal/index.ts +2 -2
- package/src/Text/component.tsx +6 -6
- package/src/Text/index.ts +2 -2
- package/src/Text/styled.ts +4 -4
- package/src/Util/component.tsx +5 -5
- package/src/Util/index.ts +2 -2
- package/src/__tests__/Content.test.tsx +46 -46
- package/src/__tests__/Element.test.ts +251 -251
- package/src/__tests__/Iterator.test.ts +142 -142
- package/src/__tests__/List.test.ts +61 -61
- package/src/__tests__/Overlay.test.ts +125 -125
- package/src/__tests__/Portal.test.ts +33 -33
- package/src/__tests__/Text.test.ts +128 -128
- package/src/__tests__/Util.test.ts +31 -31
- package/src/__tests__/Wrapper.test.tsx +60 -60
- package/src/__tests__/equalBeforeAfter.test.ts +41 -41
- package/src/__tests__/helpers.test.ts +29 -29
- package/src/__tests__/overlayContext.test.tsx +14 -14
- package/src/__tests__/responsiveProps.test.ts +116 -116
- package/src/__tests__/useOverlay.test.ts +283 -283
- package/src/__tests__/utils.test.ts +43 -43
- package/src/constants.ts +1 -1
- package/src/helpers/Content/component.tsx +5 -5
- package/src/helpers/Content/index.ts +1 -1
- package/src/helpers/Content/styled.ts +16 -16
- package/src/helpers/Content/types.ts +7 -7
- package/src/helpers/Iterator/component.tsx +28 -28
- package/src/helpers/Iterator/index.ts +2 -2
- package/src/helpers/Iterator/types.ts +3 -3
- package/src/helpers/Wrapper/component.tsx +6 -6
- package/src/helpers/Wrapper/index.ts +1 -1
- package/src/helpers/Wrapper/styled.ts +8 -8
- package/src/helpers/Wrapper/types.ts +3 -3
- package/src/helpers/Wrapper/utils.ts +1 -1
- package/src/helpers/index.ts +2 -2
- package/src/index.ts +16 -16
- package/src/types.ts +7 -7
- package/src/utils.ts +1 -1
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
import type { VNode } from
|
|
2
|
-
import { Portal as CorePortal, h } from
|
|
3
|
-
import { describe, expect, it } from
|
|
4
|
-
import { Portal } from
|
|
1
|
+
import type { VNode } from '@pyreon/core'
|
|
2
|
+
import { Portal as CorePortal, h } from '@pyreon/core'
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
|
+
import { Portal } from '../Portal'
|
|
5
5
|
|
|
6
6
|
const asVNode = (v: unknown) => v as VNode
|
|
7
7
|
|
|
8
|
-
describe(
|
|
9
|
-
describe(
|
|
10
|
-
it(
|
|
11
|
-
const child = h(
|
|
8
|
+
describe('Portal', () => {
|
|
9
|
+
describe('rendering', () => {
|
|
10
|
+
it('returns a VNode whose type is CorePortal', () => {
|
|
11
|
+
const child = h('div', null, 'modal content')
|
|
12
12
|
const result = asVNode(Portal({ children: child }))
|
|
13
13
|
expect(result.type).toBe(CorePortal)
|
|
14
14
|
})
|
|
15
15
|
|
|
16
|
-
it(
|
|
17
|
-
const child = h(
|
|
16
|
+
it('defaults target to document.body when DOMLocation is not provided', () => {
|
|
17
|
+
const child = h('div', null, 'content')
|
|
18
18
|
const result = asVNode(Portal({ children: child }))
|
|
19
19
|
const props = result.props as Record<string, unknown>
|
|
20
20
|
expect(props.target).toBe(document.body)
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
-
it(
|
|
24
|
-
const customTarget = document.createElement(
|
|
25
|
-
const child = h(
|
|
23
|
+
it('uses DOMLocation as target when provided', () => {
|
|
24
|
+
const customTarget = document.createElement('div')
|
|
25
|
+
const child = h('span', null, 'inside')
|
|
26
26
|
const result = asVNode(Portal({ DOMLocation: customTarget, children: child }))
|
|
27
27
|
const props = result.props as Record<string, unknown>
|
|
28
28
|
expect(props.target).toBe(customTarget)
|
|
29
29
|
})
|
|
30
30
|
|
|
31
|
-
it(
|
|
32
|
-
const child = h(
|
|
31
|
+
it('passes children through to the CorePortal VNode', () => {
|
|
32
|
+
const child = h('div', { class: 'modal' }, 'Modal content')
|
|
33
33
|
const result = asVNode(Portal({ children: child }))
|
|
34
34
|
const props = result.props as Record<string, unknown>
|
|
35
35
|
expect(props.children).toBe(child)
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
-
it(
|
|
39
|
-
const result = asVNode(Portal({ children:
|
|
38
|
+
it('passes string children', () => {
|
|
39
|
+
const result = asVNode(Portal({ children: 'text content' }))
|
|
40
40
|
const props = result.props as Record<string, unknown>
|
|
41
|
-
expect(props.children).toBe(
|
|
41
|
+
expect(props.children).toBe('text content')
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
-
it(
|
|
44
|
+
it('passes number children', () => {
|
|
45
45
|
const result = asVNode(Portal({ children: 42 }))
|
|
46
46
|
const props = result.props as Record<string, unknown>
|
|
47
47
|
expect(props.children).toBe(42)
|
|
48
48
|
})
|
|
49
49
|
|
|
50
|
-
it(
|
|
51
|
-
const nested = h(
|
|
50
|
+
it('passes nested VNode children', () => {
|
|
51
|
+
const nested = h('div', null, h('span', null, 'level 1'), h('span', null, 'level 2'))
|
|
52
52
|
const result = asVNode(Portal({ children: nested }))
|
|
53
53
|
const props = result.props as Record<string, unknown>
|
|
54
54
|
const childVNode = asVNode(props.children)
|
|
55
|
-
expect(childVNode.type).toBe(
|
|
55
|
+
expect(childVNode.type).toBe('div')
|
|
56
56
|
expect(childVNode.children).toHaveLength(2)
|
|
57
57
|
})
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
-
describe(
|
|
61
|
-
it(
|
|
62
|
-
const child = h(
|
|
63
|
-
const result = asVNode(Portal({ tag:
|
|
60
|
+
describe('tag prop', () => {
|
|
61
|
+
it('accepts tag prop without affecting output type', () => {
|
|
62
|
+
const child = h('div', null, 'content')
|
|
63
|
+
const result = asVNode(Portal({ tag: 'section', children: child }))
|
|
64
64
|
// tag is accepted but not used — output is still a Portal VNode
|
|
65
65
|
expect(result.type).toBe(CorePortal)
|
|
66
66
|
})
|
|
67
67
|
})
|
|
68
68
|
|
|
69
|
-
describe(
|
|
70
|
-
it(
|
|
71
|
-
expect(Portal.displayName).toBe(
|
|
69
|
+
describe('statics', () => {
|
|
70
|
+
it('has correct displayName', () => {
|
|
71
|
+
expect(Portal.displayName).toBe('@pyreon/elements/Portal')
|
|
72
72
|
})
|
|
73
73
|
|
|
74
|
-
it(
|
|
75
|
-
expect(Portal.pkgName).toBe(
|
|
74
|
+
it('has correct pkgName', () => {
|
|
75
|
+
expect(Portal.pkgName).toBe('@pyreon/elements')
|
|
76
76
|
})
|
|
77
77
|
|
|
78
|
-
it(
|
|
79
|
-
expect(Portal.PYREON__COMPONENT).toBe(
|
|
78
|
+
it('has correct PYREON__COMPONENT', () => {
|
|
79
|
+
expect(Portal.PYREON__COMPONENT).toBe('@pyreon/elements/Portal')
|
|
80
80
|
})
|
|
81
81
|
})
|
|
82
82
|
})
|
|
@@ -1,226 +1,226 @@
|
|
|
1
|
-
import type { VNode } from
|
|
2
|
-
import { h } from
|
|
3
|
-
import { describe, expect, it } from
|
|
4
|
-
import { Text } from
|
|
1
|
+
import type { VNode } from '@pyreon/core'
|
|
2
|
+
import { h } from '@pyreon/core'
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
|
+
import { Text } from '../Text'
|
|
5
5
|
|
|
6
6
|
const asVNode = (v: unknown) => v as VNode
|
|
7
7
|
|
|
8
|
-
describe(
|
|
9
|
-
describe(
|
|
10
|
-
it(
|
|
8
|
+
describe('Text', () => {
|
|
9
|
+
describe('static properties', () => {
|
|
10
|
+
it('has isText set to true', () => {
|
|
11
11
|
expect(Text.isText).toBe(true)
|
|
12
12
|
})
|
|
13
13
|
|
|
14
|
-
it(
|
|
15
|
-
expect(Text.displayName).toBe(
|
|
14
|
+
it('has correct displayName', () => {
|
|
15
|
+
expect(Text.displayName).toBe('@pyreon/elements/Text')
|
|
16
16
|
})
|
|
17
17
|
|
|
18
|
-
it(
|
|
19
|
-
expect(Text.pkgName).toBe(
|
|
18
|
+
it('has correct pkgName', () => {
|
|
19
|
+
expect(Text.pkgName).toBe('@pyreon/elements')
|
|
20
20
|
})
|
|
21
21
|
|
|
22
|
-
it(
|
|
23
|
-
expect(Text.PYREON__COMPONENT).toBe(
|
|
22
|
+
it('has correct PYREON__COMPONENT', () => {
|
|
23
|
+
expect(Text.PYREON__COMPONENT).toBe('@pyreon/elements/Text')
|
|
24
24
|
})
|
|
25
25
|
})
|
|
26
26
|
|
|
27
|
-
describe(
|
|
28
|
-
it(
|
|
29
|
-
const result = asVNode(Text({ children:
|
|
30
|
-
expect(typeof result.type).toBe(
|
|
27
|
+
describe('default rendering', () => {
|
|
28
|
+
it('returns a VNode whose type is the Styled component (a function)', () => {
|
|
29
|
+
const result = asVNode(Text({ children: 'Hello' }))
|
|
30
|
+
expect(typeof result.type).toBe('function')
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
-
it(
|
|
34
|
-
const result = asVNode(Text({ children:
|
|
33
|
+
it('does not set as prop when no tag or paragraph provided', () => {
|
|
34
|
+
const result = asVNode(Text({ children: 'Hello' }))
|
|
35
35
|
expect(result.props.as).toBeUndefined()
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
-
it(
|
|
39
|
-
const result = asVNode(Text({ children:
|
|
40
|
-
expect(result.props.children).toBe(
|
|
38
|
+
it('renders children in output', () => {
|
|
39
|
+
const result = asVNode(Text({ children: 'Hello' }))
|
|
40
|
+
expect(result.props.children).toBe('Hello')
|
|
41
41
|
})
|
|
42
42
|
|
|
43
|
-
it(
|
|
44
|
-
const result = asVNode(Text({ children:
|
|
43
|
+
it('passes $text prop with extraStyles', () => {
|
|
44
|
+
const result = asVNode(Text({ children: 'Hello' }))
|
|
45
45
|
expect(result.props.$text).toEqual({ extraStyles: undefined })
|
|
46
46
|
})
|
|
47
47
|
|
|
48
|
-
it(
|
|
48
|
+
it('renders null content when no children or label', () => {
|
|
49
49
|
const result = asVNode(Text({}))
|
|
50
50
|
expect(result.props.children).toBeUndefined()
|
|
51
51
|
})
|
|
52
52
|
})
|
|
53
53
|
|
|
54
|
-
describe(
|
|
55
|
-
it(
|
|
56
|
-
const result = asVNode(Text({ children:
|
|
57
|
-
expect(result.props.children).toBe(
|
|
54
|
+
describe('content fallback chain', () => {
|
|
55
|
+
it('renders children as content', () => {
|
|
56
|
+
const result = asVNode(Text({ children: 'child content' }))
|
|
57
|
+
expect(result.props.children).toBe('child content')
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
-
it(
|
|
61
|
-
const result = asVNode(Text({ label:
|
|
62
|
-
expect(result.props.children).toBe(
|
|
60
|
+
it('renders label when children not provided', () => {
|
|
61
|
+
const result = asVNode(Text({ label: 'label text' }))
|
|
62
|
+
expect(result.props.children).toBe('label text')
|
|
63
63
|
})
|
|
64
64
|
|
|
65
|
-
it(
|
|
66
|
-
const result = asVNode(Text({ children:
|
|
67
|
-
expect(result.props.children).toBe(
|
|
65
|
+
it('prefers children over label', () => {
|
|
66
|
+
const result = asVNode(Text({ children: 'child', label: 'label' }))
|
|
67
|
+
expect(result.props.children).toBe('child')
|
|
68
68
|
})
|
|
69
69
|
|
|
70
|
-
it(
|
|
71
|
-
const child = h(
|
|
70
|
+
it('renders VNode children', () => {
|
|
71
|
+
const child = h('strong', null, 'bold')
|
|
72
72
|
const result = asVNode(Text({ children: child }))
|
|
73
73
|
expect(result.props.children).toBe(child)
|
|
74
74
|
})
|
|
75
75
|
|
|
76
|
-
it(
|
|
76
|
+
it('renders number label', () => {
|
|
77
77
|
const result = asVNode(Text({ label: 42 }))
|
|
78
78
|
expect(result.props.children).toBe(42)
|
|
79
79
|
})
|
|
80
80
|
})
|
|
81
81
|
|
|
82
|
-
describe(
|
|
83
|
-
it(
|
|
84
|
-
const result = asVNode(Text({ tag:
|
|
85
|
-
expect(result.props.as).toBe(
|
|
82
|
+
describe('tag prop', () => {
|
|
83
|
+
it('sets as prop to h1', () => {
|
|
84
|
+
const result = asVNode(Text({ tag: 'h1', children: 'Heading' }))
|
|
85
|
+
expect(result.props.as).toBe('h1')
|
|
86
86
|
})
|
|
87
87
|
|
|
88
|
-
it(
|
|
89
|
-
const result = asVNode(Text({ tag:
|
|
90
|
-
expect(result.props.as).toBe(
|
|
88
|
+
it('sets as prop to h2', () => {
|
|
89
|
+
const result = asVNode(Text({ tag: 'h2', children: 'Sub heading' }))
|
|
90
|
+
expect(result.props.as).toBe('h2')
|
|
91
91
|
})
|
|
92
92
|
|
|
93
|
-
it(
|
|
94
|
-
const result = asVNode(Text({ tag:
|
|
95
|
-
expect(result.props.as).toBe(
|
|
93
|
+
it('sets as prop to strong', () => {
|
|
94
|
+
const result = asVNode(Text({ tag: 'strong', children: 'Bold' }))
|
|
95
|
+
expect(result.props.as).toBe('strong')
|
|
96
96
|
})
|
|
97
97
|
|
|
98
|
-
it(
|
|
99
|
-
const result = asVNode(Text({ tag:
|
|
100
|
-
expect(result.props.as).toBe(
|
|
98
|
+
it('sets as prop to em', () => {
|
|
99
|
+
const result = asVNode(Text({ tag: 'em', children: 'Italic' }))
|
|
100
|
+
expect(result.props.as).toBe('em')
|
|
101
101
|
})
|
|
102
102
|
|
|
103
|
-
it(
|
|
104
|
-
const result = asVNode(Text({ tag:
|
|
103
|
+
it('does not forward tag as a prop', () => {
|
|
104
|
+
const result = asVNode(Text({ tag: 'h1', children: 'Heading' }))
|
|
105
105
|
expect(result.props.tag).toBeUndefined()
|
|
106
106
|
})
|
|
107
107
|
})
|
|
108
108
|
|
|
109
|
-
describe(
|
|
110
|
-
it(
|
|
111
|
-
const result = asVNode(Text({ paragraph: true, children:
|
|
112
|
-
expect(result.props.as).toBe(
|
|
109
|
+
describe('paragraph prop', () => {
|
|
110
|
+
it('sets as prop to p when paragraph is true', () => {
|
|
111
|
+
const result = asVNode(Text({ paragraph: true, children: 'Paragraph text' }))
|
|
112
|
+
expect(result.props.as).toBe('p')
|
|
113
113
|
})
|
|
114
114
|
|
|
115
|
-
it(
|
|
116
|
-
const result = asVNode(Text({ paragraph: false, children:
|
|
115
|
+
it('does not set as prop when paragraph is false', () => {
|
|
116
|
+
const result = asVNode(Text({ paragraph: false, children: 'Inline text' }))
|
|
117
117
|
expect(result.props.as).toBeUndefined()
|
|
118
118
|
})
|
|
119
119
|
|
|
120
|
-
it(
|
|
120
|
+
it('paragraph is overridden when tag is also set (tag wins because paragraph branch is skipped)', () => {
|
|
121
121
|
// When paragraph is true, finalTag = 'p'
|
|
122
122
|
// When tag is also set, the else branch is not reached, so paragraph wins
|
|
123
|
-
const result = asVNode(Text({ tag:
|
|
124
|
-
expect(result.props.as).toBe(
|
|
123
|
+
const result = asVNode(Text({ tag: 'h1', paragraph: true, children: 'Heading' }))
|
|
124
|
+
expect(result.props.as).toBe('p')
|
|
125
125
|
})
|
|
126
126
|
|
|
127
|
-
it(
|
|
128
|
-
const result = asVNode(Text({ tag:
|
|
129
|
-
expect(result.props.as).toBe(
|
|
127
|
+
it('uses tag when paragraph is false', () => {
|
|
128
|
+
const result = asVNode(Text({ tag: 'h1', paragraph: false, children: 'Heading' }))
|
|
129
|
+
expect(result.props.as).toBe('h1')
|
|
130
130
|
})
|
|
131
131
|
|
|
132
|
-
it(
|
|
133
|
-
const result = asVNode(Text({ paragraph: true, children:
|
|
132
|
+
it('does not forward paragraph as a prop', () => {
|
|
133
|
+
const result = asVNode(Text({ paragraph: true, children: 'text' }))
|
|
134
134
|
expect(result.props.paragraph).toBeUndefined()
|
|
135
135
|
})
|
|
136
136
|
})
|
|
137
137
|
|
|
138
|
-
describe(
|
|
139
|
-
it(
|
|
140
|
-
const customCss =
|
|
141
|
-
const result = asVNode(Text({ css: customCss, children:
|
|
138
|
+
describe('css prop', () => {
|
|
139
|
+
it('passes css value through $text.extraStyles', () => {
|
|
140
|
+
const customCss = 'color: red;'
|
|
141
|
+
const result = asVNode(Text({ css: customCss, children: 'styled' }))
|
|
142
142
|
expect(result.props.$text).toEqual({ extraStyles: customCss })
|
|
143
143
|
})
|
|
144
144
|
|
|
145
|
-
it(
|
|
146
|
-
const result = asVNode(Text({ children:
|
|
145
|
+
it('passes undefined extraStyles when no css prop', () => {
|
|
146
|
+
const result = asVNode(Text({ children: 'plain' }))
|
|
147
147
|
expect(result.props.$text).toEqual({ extraStyles: undefined })
|
|
148
148
|
})
|
|
149
149
|
|
|
150
|
-
it(
|
|
151
|
-
const result = asVNode(Text({ css:
|
|
150
|
+
it('does not forward css as a direct prop', () => {
|
|
151
|
+
const result = asVNode(Text({ css: 'color: blue;', children: 'text' }))
|
|
152
152
|
expect(result.props.css).toBeUndefined()
|
|
153
153
|
})
|
|
154
154
|
})
|
|
155
155
|
|
|
156
|
-
describe(
|
|
157
|
-
it(
|
|
158
|
-
const result = asVNode(Text({ id:
|
|
159
|
-
expect(result.props.id).toBe(
|
|
156
|
+
describe('HTML attribute forwarding', () => {
|
|
157
|
+
it('passes through id', () => {
|
|
158
|
+
const result = asVNode(Text({ id: 'text-id', children: 'text' }))
|
|
159
|
+
expect(result.props.id).toBe('text-id')
|
|
160
160
|
})
|
|
161
161
|
|
|
162
|
-
it(
|
|
163
|
-
const result = asVNode(Text({ role:
|
|
164
|
-
expect(result.props.role).toBe(
|
|
162
|
+
it('passes through role', () => {
|
|
163
|
+
const result = asVNode(Text({ role: 'heading', children: 'text' }))
|
|
164
|
+
expect(result.props.role).toBe('heading')
|
|
165
165
|
})
|
|
166
166
|
|
|
167
|
-
it(
|
|
168
|
-
const result = asVNode(Text({ title:
|
|
169
|
-
expect(result.props.title).toBe(
|
|
167
|
+
it('passes through title', () => {
|
|
168
|
+
const result = asVNode(Text({ title: 'tooltip', children: 'text' }))
|
|
169
|
+
expect(result.props.title).toBe('tooltip')
|
|
170
170
|
})
|
|
171
171
|
|
|
172
|
-
it(
|
|
173
|
-
const result = asVNode(Text({
|
|
174
|
-
expect(result.props[
|
|
172
|
+
it('passes through data- attributes', () => {
|
|
173
|
+
const result = asVNode(Text({ 'data-testid': 'txt', children: 'text' }))
|
|
174
|
+
expect(result.props['data-testid']).toBe('txt')
|
|
175
175
|
})
|
|
176
176
|
|
|
177
|
-
it(
|
|
178
|
-
const result = asVNode(Text({
|
|
179
|
-
expect(result.props[
|
|
177
|
+
it('passes through aria- attributes', () => {
|
|
178
|
+
const result = asVNode(Text({ 'aria-label': 'label', children: 'text' }))
|
|
179
|
+
expect(result.props['aria-label']).toBe('label')
|
|
180
180
|
})
|
|
181
181
|
|
|
182
|
-
it(
|
|
182
|
+
it('passes through on-prefixed event handlers', () => {
|
|
183
183
|
const handler = () => undefined
|
|
184
|
-
const result = asVNode(Text({ onClick: handler, children:
|
|
184
|
+
const result = asVNode(Text({ onClick: handler, children: 'text' }))
|
|
185
185
|
expect(result.props.onClick).toBe(handler)
|
|
186
186
|
})
|
|
187
187
|
|
|
188
|
-
it(
|
|
188
|
+
it('passes through ref', () => {
|
|
189
189
|
const ref = { current: null }
|
|
190
|
-
const result = asVNode(Text({ ref, children:
|
|
190
|
+
const result = asVNode(Text({ ref, children: 'text' }))
|
|
191
191
|
expect(result.props.ref).toBe(ref)
|
|
192
192
|
})
|
|
193
193
|
|
|
194
|
-
it(
|
|
195
|
-
const result = asVNode(Text({ class:
|
|
196
|
-
expect(result.props.class).toBe(
|
|
194
|
+
it('passes through class', () => {
|
|
195
|
+
const result = asVNode(Text({ class: 'title', children: 'text' }))
|
|
196
|
+
expect(result.props.class).toBe('title')
|
|
197
197
|
})
|
|
198
198
|
|
|
199
|
-
it(
|
|
200
|
-
const result = asVNode(Text({ style:
|
|
201
|
-
expect(result.props.style).toBe(
|
|
199
|
+
it('passes through style', () => {
|
|
200
|
+
const result = asVNode(Text({ style: 'color: red;', children: 'text' }))
|
|
201
|
+
expect(result.props.style).toBe('color: red;')
|
|
202
202
|
})
|
|
203
203
|
|
|
204
|
-
it(
|
|
205
|
-
const result = asVNode(Text({ children:
|
|
204
|
+
it('does not set class when not provided', () => {
|
|
205
|
+
const result = asVNode(Text({ children: 'text' }))
|
|
206
206
|
expect(result.props.class).toBeUndefined()
|
|
207
207
|
})
|
|
208
208
|
|
|
209
|
-
it(
|
|
210
|
-
const result = asVNode(Text({ children:
|
|
209
|
+
it('does not set style when not provided', () => {
|
|
210
|
+
const result = asVNode(Text({ children: 'text' }))
|
|
211
211
|
expect(result.props.style).toBeUndefined()
|
|
212
212
|
})
|
|
213
213
|
})
|
|
214
214
|
|
|
215
|
-
describe(
|
|
216
|
-
it(
|
|
215
|
+
describe('reserved props are consumed and not forwarded', () => {
|
|
216
|
+
it('does not forward paragraph, label, tag, or css', () => {
|
|
217
217
|
const result = asVNode(
|
|
218
218
|
Text({
|
|
219
219
|
paragraph: true,
|
|
220
|
-
label:
|
|
221
|
-
children:
|
|
222
|
-
tag:
|
|
223
|
-
css:
|
|
220
|
+
label: 'lbl',
|
|
221
|
+
children: 'text',
|
|
222
|
+
tag: 'h1',
|
|
223
|
+
css: 'font-size: 2rem;',
|
|
224
224
|
}),
|
|
225
225
|
)
|
|
226
226
|
expect(result.props.paragraph).toBeUndefined()
|
|
@@ -230,45 +230,45 @@ describe("Text", () => {
|
|
|
230
230
|
})
|
|
231
231
|
})
|
|
232
232
|
|
|
233
|
-
describe(
|
|
234
|
-
it(
|
|
233
|
+
describe('combined props', () => {
|
|
234
|
+
it('renders with paragraph, css, class, and data attribute together', () => {
|
|
235
235
|
const result = asVNode(
|
|
236
236
|
Text({
|
|
237
237
|
paragraph: true,
|
|
238
|
-
css:
|
|
239
|
-
class:
|
|
240
|
-
|
|
241
|
-
children:
|
|
238
|
+
css: 'margin: 0;',
|
|
239
|
+
class: 'intro',
|
|
240
|
+
'data-testid': 'intro-text',
|
|
241
|
+
children: 'Hello world',
|
|
242
242
|
}),
|
|
243
243
|
)
|
|
244
244
|
|
|
245
|
-
expect(typeof result.type).toBe(
|
|
246
|
-
expect(result.props.as).toBe(
|
|
247
|
-
expect(result.props.$text).toEqual({ extraStyles:
|
|
248
|
-
expect(result.props.class).toBe(
|
|
249
|
-
expect(result.props[
|
|
250
|
-
expect(result.props.children).toBe(
|
|
245
|
+
expect(typeof result.type).toBe('function')
|
|
246
|
+
expect(result.props.as).toBe('p')
|
|
247
|
+
expect(result.props.$text).toEqual({ extraStyles: 'margin: 0;' })
|
|
248
|
+
expect(result.props.class).toBe('intro')
|
|
249
|
+
expect(result.props['data-testid']).toBe('intro-text')
|
|
250
|
+
expect(result.props.children).toBe('Hello world')
|
|
251
251
|
// Reserved props not forwarded
|
|
252
252
|
expect(result.props.paragraph).toBeUndefined()
|
|
253
253
|
expect(result.props.css).toBeUndefined()
|
|
254
254
|
})
|
|
255
255
|
|
|
256
|
-
it(
|
|
256
|
+
it('renders with tag, ref, and event handler together', () => {
|
|
257
257
|
const ref = { current: null }
|
|
258
258
|
const handler = () => undefined
|
|
259
259
|
const result = asVNode(
|
|
260
260
|
Text({
|
|
261
|
-
tag:
|
|
261
|
+
tag: 'h2',
|
|
262
262
|
ref,
|
|
263
263
|
onClick: handler,
|
|
264
|
-
children:
|
|
264
|
+
children: 'Subtitle',
|
|
265
265
|
}),
|
|
266
266
|
)
|
|
267
267
|
|
|
268
|
-
expect(result.props.as).toBe(
|
|
268
|
+
expect(result.props.as).toBe('h2')
|
|
269
269
|
expect(result.props.ref).toBe(ref)
|
|
270
270
|
expect(result.props.onClick).toBe(handler)
|
|
271
|
-
expect(result.props.children).toBe(
|
|
271
|
+
expect(result.props.children).toBe('Subtitle')
|
|
272
272
|
})
|
|
273
273
|
})
|
|
274
274
|
})
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
import type { VNodeChild } from
|
|
2
|
-
import { h } from
|
|
3
|
-
import { describe, expect, it } from
|
|
4
|
-
import Util from
|
|
1
|
+
import type { VNodeChild } from '@pyreon/core'
|
|
2
|
+
import { h } from '@pyreon/core'
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
|
+
import Util from '../Util/component'
|
|
5
5
|
|
|
6
|
-
describe(
|
|
7
|
-
describe(
|
|
8
|
-
it(
|
|
9
|
-
expect(Util.displayName).toBe(
|
|
6
|
+
describe('Util', () => {
|
|
7
|
+
describe('statics', () => {
|
|
8
|
+
it('has displayName', () => {
|
|
9
|
+
expect(Util.displayName).toBe('@pyreon/elements/Util')
|
|
10
10
|
})
|
|
11
11
|
|
|
12
|
-
it(
|
|
13
|
-
expect(Util.pkgName).toBe(
|
|
12
|
+
it('has pkgName', () => {
|
|
13
|
+
expect(Util.pkgName).toBe('@pyreon/elements')
|
|
14
14
|
})
|
|
15
15
|
|
|
16
|
-
it(
|
|
17
|
-
expect(Util.PYREON__COMPONENT).toBe(
|
|
16
|
+
it('has PYREON__COMPONENT', () => {
|
|
17
|
+
expect(Util.PYREON__COMPONENT).toBe('@pyreon/elements/Util')
|
|
18
18
|
})
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
describe(
|
|
22
|
-
it(
|
|
23
|
-
const child = h(
|
|
24
|
-
const result = Util({ children: child, className:
|
|
21
|
+
describe('className injection', () => {
|
|
22
|
+
it('calls render with className prop for string className', () => {
|
|
23
|
+
const child = h('div', { 'data-testid': 'child' }, 'Content')
|
|
24
|
+
const result = Util({ children: child, className: 'my-class' }) as VNodeChild
|
|
25
25
|
// render() should merge className into the child
|
|
26
26
|
expect(result).toBeDefined()
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
it(
|
|
30
|
-
const child = h(
|
|
31
|
-
const result = Util({ children: child, className: [
|
|
29
|
+
it('joins array className into space-separated string', () => {
|
|
30
|
+
const child = h('div', { 'data-testid': 'child' }, 'Content')
|
|
31
|
+
const result = Util({ children: child, className: ['cls-a', 'cls-b'] }) as VNodeChild
|
|
32
32
|
expect(result).toBeDefined()
|
|
33
33
|
})
|
|
34
34
|
})
|
|
35
35
|
|
|
36
|
-
describe(
|
|
37
|
-
it(
|
|
38
|
-
const child = h(
|
|
39
|
-
const result = Util({ children: child, style: { color:
|
|
36
|
+
describe('style injection', () => {
|
|
37
|
+
it('calls render with style prop for style object', () => {
|
|
38
|
+
const child = h('div', { 'data-testid': 'child' }, 'Content')
|
|
39
|
+
const result = Util({ children: child, style: { color: 'red' } }) as VNodeChild
|
|
40
40
|
expect(result).toBeDefined()
|
|
41
41
|
})
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
-
describe(
|
|
45
|
-
it(
|
|
46
|
-
const child = h(
|
|
44
|
+
describe('both className and style', () => {
|
|
45
|
+
it('passes both className and style to render', () => {
|
|
46
|
+
const child = h('div', { 'data-testid': 'child' }, 'Content')
|
|
47
47
|
const result = Util({
|
|
48
48
|
children: child,
|
|
49
|
-
className:
|
|
50
|
-
style: { color:
|
|
49
|
+
className: 'my-class',
|
|
50
|
+
style: { color: 'blue' },
|
|
51
51
|
}) as VNodeChild
|
|
52
52
|
expect(result).toBeDefined()
|
|
53
53
|
})
|
|
54
54
|
})
|
|
55
55
|
|
|
56
|
-
describe(
|
|
57
|
-
it(
|
|
58
|
-
const child = h(
|
|
56
|
+
describe('no-op when no props', () => {
|
|
57
|
+
it('renders children without modification when no className or style', () => {
|
|
58
|
+
const child = h('div', { 'data-testid': 'child' }, 'Content')
|
|
59
59
|
const result = Util({ children: child }) as VNodeChild
|
|
60
60
|
expect(result).toBeDefined()
|
|
61
61
|
})
|