@pyreon/styler 0.11.5 → 0.11.7
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 +27 -23
- package/lib/index.d.ts +9 -2
- package/lib/index.js +49 -4
- package/package.json +22 -22
- package/src/ThemeProvider.ts +10 -3
- package/src/__tests__/ThemeProvider.test.ts +21 -21
- package/src/__tests__/benchmark.bench.ts +56 -45
- package/src/__tests__/composition-chain.test.ts +200 -151
- package/src/__tests__/forward.test.ts +122 -122
- package/src/__tests__/globalStyle.test.ts +18 -18
- package/src/__tests__/hash.test.ts +27 -27
- package/src/__tests__/hybrid-injection.test.ts +83 -59
- package/src/__tests__/index.ts +10 -10
- package/src/__tests__/insertion-effect.test.ts +45 -32
- package/src/__tests__/integration.test.ts +81 -51
- package/src/__tests__/keyframes.test.ts +13 -13
- package/src/__tests__/memory-growth.test.ts +21 -21
- package/src/__tests__/p3-features.test.ts +162 -104
- package/src/__tests__/shared.test.ts +51 -33
- package/src/__tests__/sheet-advanced.test.ts +227 -227
- package/src/__tests__/sheet-split-atrules.test.ts +85 -85
- package/src/__tests__/sheet.test.ts +69 -69
- package/src/__tests__/styled-ssr.test.ts +36 -28
- package/src/__tests__/styled.test.ts +214 -145
- package/src/__tests__/theme.test.ts +11 -11
- package/src/__tests__/useCSS.test.ts +89 -59
- package/src/css.ts +1 -1
- package/src/forward.ts +187 -187
- package/src/globalStyle.ts +5 -5
- package/src/index.ts +15 -15
- package/src/keyframes.ts +3 -3
- package/src/resolve.ts +14 -14
- package/src/shared.ts +2 -2
- package/src/sheet.ts +26 -26
- package/src/styled.tsx +157 -100
- package/src/useCSS.ts +4 -4
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* SSR tests for styled() and createGlobalStyle(). Re-imports modules
|
|
5
5
|
* with `document` deleted so IS_SERVER evaluates to true.
|
|
6
6
|
*/
|
|
7
|
-
describe(
|
|
7
|
+
describe('styled -- SSR mode', () => {
|
|
8
8
|
let originalDocument: typeof document
|
|
9
9
|
|
|
10
10
|
beforeEach(() => {
|
|
@@ -18,48 +18,56 @@ describe("styled -- SSR mode", () => {
|
|
|
18
18
|
globalThis.document = originalDocument
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
it(
|
|
22
|
-
const { styled } = await import(
|
|
23
|
-
const Comp = styled(
|
|
24
|
-
|
|
21
|
+
it('static: creates component with SSR injection path', async () => {
|
|
22
|
+
const { styled } = await import('../styled')
|
|
23
|
+
const Comp = styled('div')`
|
|
24
|
+
color: red;
|
|
25
|
+
`
|
|
26
|
+
expect((Comp as any).displayName).toBe('styled(div)')
|
|
25
27
|
})
|
|
26
28
|
|
|
27
|
-
it(
|
|
28
|
-
const { styled } = await import(
|
|
29
|
-
const Comp = styled(
|
|
30
|
-
expect((Comp as any).displayName).toBe(
|
|
29
|
+
it('static: empty CSS template in SSR', async () => {
|
|
30
|
+
const { styled } = await import('../styled')
|
|
31
|
+
const Comp = styled('div')``
|
|
32
|
+
expect((Comp as any).displayName).toBe('styled(div)')
|
|
31
33
|
})
|
|
32
34
|
|
|
33
|
-
it(
|
|
34
|
-
const { styled } = await import(
|
|
35
|
-
const Comp = styled(
|
|
36
|
-
|
|
35
|
+
it('static: boost option in SSR', async () => {
|
|
36
|
+
const { styled } = await import('../styled')
|
|
37
|
+
const Comp = styled('div', { boost: true })`
|
|
38
|
+
color: blue;
|
|
39
|
+
`
|
|
40
|
+
expect((Comp as any).displayName).toBe('styled(div)')
|
|
37
41
|
})
|
|
38
42
|
|
|
39
|
-
it(
|
|
40
|
-
const { styled } = await import(
|
|
41
|
-
const Comp = styled(
|
|
42
|
-
shouldForwardProp: (p) => p !==
|
|
43
|
-
})`
|
|
44
|
-
|
|
43
|
+
it('static: shouldForwardProp in SSR', async () => {
|
|
44
|
+
const { styled } = await import('../styled')
|
|
45
|
+
const Comp = styled('div', {
|
|
46
|
+
shouldForwardProp: (p) => p !== 'color',
|
|
47
|
+
})`
|
|
48
|
+
display: flex;
|
|
49
|
+
`
|
|
50
|
+
expect((Comp as any).displayName).toBe('styled(div)')
|
|
45
51
|
})
|
|
46
52
|
|
|
47
|
-
it(
|
|
48
|
-
const { styled } = await import(
|
|
49
|
-
const Comp = styled.div`
|
|
50
|
-
|
|
53
|
+
it('static: styled.div shorthand in SSR', async () => {
|
|
54
|
+
const { styled } = await import('../styled')
|
|
55
|
+
const Comp = styled.div`
|
|
56
|
+
color: green;
|
|
57
|
+
`
|
|
58
|
+
expect((Comp as any).displayName).toBe('styled(div)')
|
|
51
59
|
})
|
|
52
60
|
|
|
53
|
-
it(
|
|
54
|
-
const { createGlobalStyle } = await import(
|
|
61
|
+
it('createGlobalStyle: static SSR path', async () => {
|
|
62
|
+
const { createGlobalStyle } = await import('../globalStyle')
|
|
55
63
|
const GlobalStyle = createGlobalStyle`body { margin: 0; }`
|
|
56
64
|
// Static path injects immediately and returns a function that produces null
|
|
57
65
|
const result = GlobalStyle({})
|
|
58
66
|
expect(result).toBeNull()
|
|
59
67
|
})
|
|
60
68
|
|
|
61
|
-
it(
|
|
62
|
-
const { createGlobalStyle } = await import(
|
|
69
|
+
it('createGlobalStyle: empty CSS in SSR returns null', async () => {
|
|
70
|
+
const { createGlobalStyle } = await import('../globalStyle')
|
|
63
71
|
const GlobalStyle = createGlobalStyle``
|
|
64
72
|
const result = GlobalStyle({})
|
|
65
73
|
expect(result).toBeNull()
|
|
@@ -1,303 +1,372 @@
|
|
|
1
|
-
import type { VNode } from
|
|
2
|
-
import { afterEach, describe, expect, it } from
|
|
3
|
-
import { sheet } from
|
|
4
|
-
import { styled } from
|
|
1
|
+
import type { VNode } from '@pyreon/core'
|
|
2
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
3
|
+
import { sheet } from '../sheet'
|
|
4
|
+
import { styled } from '../styled'
|
|
5
5
|
|
|
6
|
-
describe(
|
|
6
|
+
describe('styled', () => {
|
|
7
7
|
afterEach(() => {
|
|
8
8
|
sheet.reset()
|
|
9
9
|
})
|
|
10
10
|
|
|
11
|
-
describe(
|
|
12
|
-
it(
|
|
13
|
-
const tagFn = styled(
|
|
14
|
-
expect(typeof tagFn).toBe(
|
|
11
|
+
describe('basic creation', () => {
|
|
12
|
+
it('returns a tagged template function', () => {
|
|
13
|
+
const tagFn = styled('div')
|
|
14
|
+
expect(typeof tagFn).toBe('function')
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
it(
|
|
18
|
-
const Comp = styled(
|
|
19
|
-
|
|
17
|
+
it('tagged template returns a ComponentFn', () => {
|
|
18
|
+
const Comp = styled('div')`
|
|
19
|
+
display: flex;
|
|
20
|
+
`
|
|
21
|
+
expect(typeof Comp).toBe('function')
|
|
20
22
|
})
|
|
21
23
|
})
|
|
22
24
|
|
|
23
|
-
describe(
|
|
24
|
-
it(
|
|
25
|
-
const Comp = styled(
|
|
25
|
+
describe('static CSS (no function interpolations)', () => {
|
|
26
|
+
it('produces a VNode with the correct tag', () => {
|
|
27
|
+
const Comp = styled('div')`
|
|
28
|
+
display: flex;
|
|
29
|
+
`
|
|
26
30
|
const vnode = Comp({}) as VNode
|
|
27
|
-
expect(vnode.type).toBe(
|
|
31
|
+
expect(vnode.type).toBe('div')
|
|
28
32
|
})
|
|
29
33
|
|
|
30
|
-
it(
|
|
31
|
-
const Comp = styled(
|
|
34
|
+
it('produces a VNode with the correct tag for span', () => {
|
|
35
|
+
const Comp = styled('span')`
|
|
36
|
+
color: red;
|
|
37
|
+
`
|
|
32
38
|
const vnode = Comp({}) as VNode
|
|
33
|
-
expect(vnode.type).toBe(
|
|
39
|
+
expect(vnode.type).toBe('span')
|
|
34
40
|
})
|
|
35
41
|
|
|
36
|
-
it(
|
|
37
|
-
const Comp = styled(
|
|
42
|
+
it('applies a generated className', () => {
|
|
43
|
+
const Comp = styled('div')`
|
|
44
|
+
display: flex;
|
|
45
|
+
`
|
|
38
46
|
const vnode = Comp({}) as VNode
|
|
39
47
|
expect(vnode.props.class).toMatch(/^pyr-[0-9a-z]+$/)
|
|
40
48
|
})
|
|
41
49
|
|
|
42
|
-
it(
|
|
43
|
-
const Comp = styled(
|
|
50
|
+
it('same component produces same className across calls', () => {
|
|
51
|
+
const Comp = styled('div')`
|
|
52
|
+
display: flex;
|
|
53
|
+
color: red;
|
|
54
|
+
`
|
|
44
55
|
const vnode1 = Comp({}) as VNode
|
|
45
56
|
const vnode2 = Comp({}) as VNode
|
|
46
57
|
expect(vnode1.props.class).toBe(vnode2.props.class)
|
|
47
58
|
})
|
|
48
59
|
|
|
49
|
-
it(
|
|
50
|
-
const Comp1 = styled(
|
|
51
|
-
|
|
60
|
+
it('different CSS produces different classNames', () => {
|
|
61
|
+
const Comp1 = styled('div')`
|
|
62
|
+
color: red;
|
|
63
|
+
`
|
|
64
|
+
const Comp2 = styled('div')`
|
|
65
|
+
color: blue;
|
|
66
|
+
`
|
|
52
67
|
const vnode1 = Comp1({}) as VNode
|
|
53
68
|
const vnode2 = Comp2({}) as VNode
|
|
54
69
|
expect(vnode1.props.class).not.toBe(vnode2.props.class)
|
|
55
70
|
})
|
|
56
71
|
})
|
|
57
72
|
|
|
58
|
-
describe(
|
|
59
|
-
it(
|
|
60
|
-
const Comp = styled(
|
|
73
|
+
describe('empty CSS', () => {
|
|
74
|
+
it('renders element without className for empty template', () => {
|
|
75
|
+
const Comp = styled('div')``
|
|
61
76
|
const vnode = Comp({}) as VNode
|
|
62
77
|
expect(vnode.props.class).toBeFalsy()
|
|
63
78
|
})
|
|
64
79
|
|
|
65
|
-
it(
|
|
66
|
-
const Comp = styled(
|
|
80
|
+
it('renders element without className for whitespace-only template', () => {
|
|
81
|
+
const Comp = styled('div')``
|
|
67
82
|
const vnode = Comp({}) as VNode
|
|
68
83
|
expect(vnode.props.class).toBeFalsy()
|
|
69
84
|
})
|
|
70
85
|
})
|
|
71
86
|
|
|
72
|
-
describe(
|
|
73
|
-
it(
|
|
74
|
-
const color =
|
|
75
|
-
const Comp = styled(
|
|
87
|
+
describe('static interpolations (non-function)', () => {
|
|
88
|
+
it('treats string interpolations as static', () => {
|
|
89
|
+
const color = 'red'
|
|
90
|
+
const Comp = styled('div')`
|
|
91
|
+
color: ${color};
|
|
92
|
+
`
|
|
76
93
|
const vnode = Comp({}) as VNode
|
|
77
94
|
expect(vnode.props.class).toMatch(/^pyr-/)
|
|
78
95
|
})
|
|
79
96
|
|
|
80
|
-
it(
|
|
97
|
+
it('treats number interpolations as static', () => {
|
|
81
98
|
const size = 16
|
|
82
|
-
const Comp = styled(
|
|
99
|
+
const Comp = styled('div')`
|
|
100
|
+
font-size: ${size}px;
|
|
101
|
+
`
|
|
83
102
|
const vnode = Comp({}) as VNode
|
|
84
103
|
expect(vnode.props.class).toMatch(/^pyr-/)
|
|
85
104
|
})
|
|
86
105
|
})
|
|
87
106
|
|
|
88
|
-
describe(
|
|
89
|
-
it(
|
|
90
|
-
const Comp = styled(
|
|
107
|
+
describe('dynamic CSS (function interpolations)', () => {
|
|
108
|
+
it('resolves function interpolations with props', () => {
|
|
109
|
+
const Comp = styled('div')`
|
|
91
110
|
color: ${(props: any) => props.color};
|
|
92
111
|
`
|
|
93
|
-
const vnode = Comp({ color:
|
|
112
|
+
const vnode = Comp({ color: 'red' }) as VNode
|
|
94
113
|
expect(vnode.props.class).toMatch(/^pyr-/)
|
|
95
114
|
})
|
|
96
115
|
|
|
97
|
-
it(
|
|
98
|
-
const Comp = styled(
|
|
116
|
+
it('different prop values produce different classNames', () => {
|
|
117
|
+
const Comp = styled('div')`
|
|
99
118
|
color: ${(props: any) => props.color};
|
|
100
119
|
`
|
|
101
|
-
const vnode1 = Comp({ color:
|
|
102
|
-
const vnode2 = Comp({ color:
|
|
120
|
+
const vnode1 = Comp({ color: 'red' }) as VNode
|
|
121
|
+
const vnode2 = Comp({ color: 'blue' }) as VNode
|
|
103
122
|
expect(vnode1.props.class).not.toBe(vnode2.props.class)
|
|
104
123
|
})
|
|
105
124
|
|
|
106
|
-
it(
|
|
107
|
-
const Comp = styled(
|
|
125
|
+
it('same prop values produce same className (dedup)', () => {
|
|
126
|
+
const Comp = styled('div')`
|
|
108
127
|
color: ${(props: any) => props.color};
|
|
109
128
|
`
|
|
110
|
-
const vnode1 = Comp({ color:
|
|
111
|
-
const vnode2 = Comp({ color:
|
|
129
|
+
const vnode1 = Comp({ color: 'red' }) as VNode
|
|
130
|
+
const vnode2 = Comp({ color: 'red' }) as VNode
|
|
112
131
|
expect(vnode1.props.class).toBe(vnode2.props.class)
|
|
113
132
|
})
|
|
114
133
|
|
|
115
|
-
it(
|
|
116
|
-
const Comp = styled(
|
|
134
|
+
it('handles functions returning empty string', () => {
|
|
135
|
+
const Comp = styled('div')`
|
|
136
|
+
${() => ''}
|
|
137
|
+
`
|
|
117
138
|
const vnode = Comp({}) as VNode
|
|
118
139
|
expect(vnode.props.class).toBeFalsy()
|
|
119
140
|
})
|
|
120
141
|
|
|
121
|
-
it(
|
|
122
|
-
const Comp = styled(
|
|
142
|
+
it('handles functions returning false', () => {
|
|
143
|
+
const Comp = styled('div')`
|
|
144
|
+
${(props: any) => (props.active ? 'color: red;' : false)}
|
|
145
|
+
`
|
|
123
146
|
const vnode = Comp({ active: false }) as VNode
|
|
124
147
|
expect(vnode.props.class).toBeFalsy()
|
|
125
148
|
})
|
|
126
149
|
})
|
|
127
150
|
|
|
128
|
-
describe(
|
|
129
|
-
it(
|
|
130
|
-
const Comp = styled(
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
151
|
+
describe('className merging', () => {
|
|
152
|
+
it('merges user class with generated className', () => {
|
|
153
|
+
const Comp = styled('div')`
|
|
154
|
+
display: flex;
|
|
155
|
+
`
|
|
156
|
+
const vnode = Comp({ class: 'custom' }) as VNode
|
|
157
|
+
expect(vnode.props.class).toContain('pyr-')
|
|
158
|
+
expect(vnode.props.class).toContain('custom')
|
|
134
159
|
})
|
|
135
160
|
|
|
136
|
-
it(
|
|
137
|
-
const Comp = styled(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
161
|
+
it('merges user className with generated className', () => {
|
|
162
|
+
const Comp = styled('div')`
|
|
163
|
+
display: flex;
|
|
164
|
+
`
|
|
165
|
+
const vnode = Comp({ className: 'custom' }) as VNode
|
|
166
|
+
expect(vnode.props.class).toContain('pyr-')
|
|
167
|
+
expect(vnode.props.class).toContain('custom')
|
|
141
168
|
})
|
|
142
169
|
|
|
143
|
-
it(
|
|
144
|
-
const Comp = styled(
|
|
145
|
-
const vnode = Comp({ class:
|
|
146
|
-
expect(vnode.props.class).toBe(
|
|
170
|
+
it('handles class without generated className (empty CSS)', () => {
|
|
171
|
+
const Comp = styled('div')``
|
|
172
|
+
const vnode = Comp({ class: 'custom' }) as VNode
|
|
173
|
+
expect(vnode.props.class).toBe('custom')
|
|
147
174
|
})
|
|
148
175
|
})
|
|
149
176
|
|
|
150
|
-
describe(
|
|
151
|
-
it(
|
|
152
|
-
const Comp = styled(
|
|
153
|
-
|
|
154
|
-
|
|
177
|
+
describe('as prop (polymorphic rendering)', () => {
|
|
178
|
+
it('changes the rendered element type', () => {
|
|
179
|
+
const Comp = styled('div')`
|
|
180
|
+
display: flex;
|
|
181
|
+
`
|
|
182
|
+
const vnode = Comp({ as: 'section' }) as VNode
|
|
183
|
+
expect(vnode.type).toBe('section')
|
|
155
184
|
})
|
|
156
185
|
|
|
157
|
-
it(
|
|
158
|
-
const Comp = styled(
|
|
159
|
-
|
|
160
|
-
|
|
186
|
+
it('renders as button', () => {
|
|
187
|
+
const Comp = styled('div')`
|
|
188
|
+
cursor: pointer;
|
|
189
|
+
`
|
|
190
|
+
const vnode = Comp({ as: 'button' }) as VNode
|
|
191
|
+
expect(vnode.type).toBe('button')
|
|
161
192
|
})
|
|
162
193
|
|
|
163
|
-
it(
|
|
164
|
-
const Comp = styled(
|
|
194
|
+
it('defaults to original tag when as is not provided', () => {
|
|
195
|
+
const Comp = styled('span')`
|
|
196
|
+
color: red;
|
|
197
|
+
`
|
|
165
198
|
const vnode = Comp({}) as VNode
|
|
166
|
-
expect(vnode.type).toBe(
|
|
199
|
+
expect(vnode.type).toBe('span')
|
|
167
200
|
})
|
|
168
201
|
})
|
|
169
202
|
|
|
170
|
-
describe(
|
|
171
|
-
it(
|
|
172
|
-
const Comp = styled(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
203
|
+
describe('prop filtering (HTML elements)', () => {
|
|
204
|
+
it('forwards valid HTML attributes', () => {
|
|
205
|
+
const Comp = styled('input')`
|
|
206
|
+
display: block;
|
|
207
|
+
`
|
|
208
|
+
const vnode = Comp({ type: 'text', placeholder: 'test' }) as VNode
|
|
209
|
+
expect(vnode.props.type).toBe('text')
|
|
210
|
+
expect(vnode.props.placeholder).toBe('test')
|
|
176
211
|
})
|
|
177
212
|
|
|
178
|
-
it(
|
|
179
|
-
const Comp = styled(
|
|
180
|
-
|
|
181
|
-
|
|
213
|
+
it('forwards data-* attributes', () => {
|
|
214
|
+
const Comp = styled('div')`
|
|
215
|
+
display: flex;
|
|
216
|
+
`
|
|
217
|
+
const vnode = Comp({ 'data-testid': 'hello' }) as VNode
|
|
218
|
+
expect(vnode.props['data-testid']).toBe('hello')
|
|
182
219
|
})
|
|
183
220
|
|
|
184
|
-
it(
|
|
185
|
-
const Comp = styled(
|
|
186
|
-
|
|
187
|
-
|
|
221
|
+
it('forwards aria-* attributes', () => {
|
|
222
|
+
const Comp = styled('div')`
|
|
223
|
+
display: flex;
|
|
224
|
+
`
|
|
225
|
+
const vnode = Comp({ 'aria-label': 'world' }) as VNode
|
|
226
|
+
expect(vnode.props['aria-label']).toBe('world')
|
|
188
227
|
})
|
|
189
228
|
|
|
190
|
-
it(
|
|
229
|
+
it('forwards event handlers (on* props)', () => {
|
|
191
230
|
const handler = () => {
|
|
192
231
|
/* no-op */
|
|
193
232
|
}
|
|
194
|
-
const Comp = styled(
|
|
233
|
+
const Comp = styled('button')`
|
|
234
|
+
cursor: pointer;
|
|
235
|
+
`
|
|
195
236
|
const vnode = Comp({ onClick: handler }) as VNode
|
|
196
237
|
expect(vnode.props.onClick).toBe(handler)
|
|
197
238
|
})
|
|
198
239
|
|
|
199
|
-
it(
|
|
200
|
-
const Comp = styled(
|
|
201
|
-
|
|
240
|
+
it('filters unknown props for HTML elements', () => {
|
|
241
|
+
const Comp = styled('div')`
|
|
242
|
+
display: flex;
|
|
243
|
+
`
|
|
244
|
+
const vnode = Comp({ unknownProp: 'test' }) as VNode
|
|
202
245
|
expect(vnode.props.unknownProp).toBeUndefined()
|
|
203
246
|
})
|
|
204
247
|
|
|
205
|
-
it(
|
|
206
|
-
const Comp = styled(
|
|
207
|
-
|
|
248
|
+
it('filters $-prefixed transient props', () => {
|
|
249
|
+
const Comp = styled('div')`
|
|
250
|
+
display: flex;
|
|
251
|
+
`
|
|
252
|
+
const vnode = Comp({ $variant: 'primary' }) as VNode
|
|
208
253
|
expect(vnode.props.$variant).toBeUndefined()
|
|
209
254
|
})
|
|
210
255
|
|
|
211
|
-
it(
|
|
212
|
-
const Comp = styled(
|
|
213
|
-
|
|
256
|
+
it('does not forward class/className as separate props', () => {
|
|
257
|
+
const Comp = styled('div')`
|
|
258
|
+
display: flex;
|
|
259
|
+
`
|
|
260
|
+
const vnode = Comp({ class: 'extra', className: 'another' }) as VNode
|
|
214
261
|
expect(vnode.props.className).toBeUndefined()
|
|
215
262
|
})
|
|
216
263
|
})
|
|
217
264
|
|
|
218
|
-
describe(
|
|
219
|
-
it(
|
|
220
|
-
const Comp = styled(
|
|
221
|
-
shouldForwardProp: (prop) => prop !==
|
|
222
|
-
})`
|
|
223
|
-
|
|
265
|
+
describe('shouldForwardProp option', () => {
|
|
266
|
+
it('uses custom filter when provided', () => {
|
|
267
|
+
const Comp = styled('div', {
|
|
268
|
+
shouldForwardProp: (prop) => prop !== 'color',
|
|
269
|
+
})`
|
|
270
|
+
display: flex;
|
|
271
|
+
`
|
|
272
|
+
const vnode = Comp({ color: 'red', 'data-testid': 'test' }) as VNode
|
|
224
273
|
expect(vnode.props.color).toBeUndefined()
|
|
225
|
-
expect(vnode.props[
|
|
274
|
+
expect(vnode.props['data-testid']).toBe('test')
|
|
226
275
|
})
|
|
227
276
|
|
|
228
|
-
it(
|
|
229
|
-
const Comp = styled(
|
|
277
|
+
it('custom filter controls all prop forwarding', () => {
|
|
278
|
+
const Comp = styled('div', {
|
|
230
279
|
shouldForwardProp: () => false,
|
|
231
|
-
})`
|
|
232
|
-
|
|
280
|
+
})`
|
|
281
|
+
display: flex;
|
|
282
|
+
`
|
|
283
|
+
const vnode = Comp({ id: 'test', role: 'button' }) as VNode
|
|
233
284
|
expect(vnode.props.id).toBeUndefined()
|
|
234
285
|
expect(vnode.props.role).toBeUndefined()
|
|
235
286
|
})
|
|
236
287
|
})
|
|
237
288
|
|
|
238
|
-
describe(
|
|
239
|
-
it(
|
|
240
|
-
const Comp = styled(
|
|
289
|
+
describe('boost option', () => {
|
|
290
|
+
it('accepts boost option without error', () => {
|
|
291
|
+
const Comp = styled('div', { boost: true })`
|
|
292
|
+
color: red;
|
|
293
|
+
`
|
|
241
294
|
const vnode = Comp({}) as VNode
|
|
242
295
|
expect(vnode.props.class).toMatch(/^pyr-/)
|
|
243
296
|
})
|
|
244
297
|
})
|
|
245
298
|
|
|
246
|
-
describe(
|
|
247
|
-
it(
|
|
248
|
-
const Comp = styled(
|
|
249
|
-
|
|
250
|
-
|
|
299
|
+
describe('children forwarding', () => {
|
|
300
|
+
it('passes single child through', () => {
|
|
301
|
+
const Comp = styled('div')`
|
|
302
|
+
display: flex;
|
|
303
|
+
`
|
|
304
|
+
const vnode = Comp({ children: 'hello' }) as VNode
|
|
305
|
+
expect(vnode.children).toEqual(['hello'])
|
|
251
306
|
})
|
|
252
307
|
|
|
253
|
-
it(
|
|
254
|
-
const Comp = styled(
|
|
255
|
-
|
|
308
|
+
it('passes array children through', () => {
|
|
309
|
+
const Comp = styled('div')`
|
|
310
|
+
display: flex;
|
|
311
|
+
`
|
|
312
|
+
const children = ['a', 'b', 'c']
|
|
256
313
|
const vnode = Comp({ children }) as VNode
|
|
257
|
-
expect(vnode.children).toEqual([
|
|
314
|
+
expect(vnode.children).toEqual(['a', 'b', 'c'])
|
|
258
315
|
})
|
|
259
316
|
|
|
260
|
-
it(
|
|
261
|
-
const Comp = styled(
|
|
317
|
+
it('handles null children', () => {
|
|
318
|
+
const Comp = styled('div')`
|
|
319
|
+
display: flex;
|
|
320
|
+
`
|
|
262
321
|
const vnode = Comp({ children: null }) as VNode
|
|
263
322
|
expect(vnode.children).toEqual([])
|
|
264
323
|
})
|
|
265
324
|
|
|
266
|
-
it(
|
|
267
|
-
const Comp = styled(
|
|
325
|
+
it('handles undefined children', () => {
|
|
326
|
+
const Comp = styled('div')`
|
|
327
|
+
display: flex;
|
|
328
|
+
`
|
|
268
329
|
const vnode = Comp({}) as VNode
|
|
269
330
|
expect(vnode.children).toEqual([])
|
|
270
331
|
})
|
|
271
332
|
})
|
|
272
333
|
})
|
|
273
334
|
|
|
274
|
-
describe(
|
|
335
|
+
describe('styled.tag (Proxy)', () => {
|
|
275
336
|
afterEach(() => {
|
|
276
337
|
sheet.reset()
|
|
277
338
|
})
|
|
278
339
|
|
|
279
|
-
it(
|
|
280
|
-
const Comp = styled.div`
|
|
340
|
+
it('styled.div creates a div component', () => {
|
|
341
|
+
const Comp = styled.div`
|
|
342
|
+
color: red;
|
|
343
|
+
`
|
|
281
344
|
const vnode = Comp({}) as VNode
|
|
282
|
-
expect(vnode.type).toBe(
|
|
345
|
+
expect(vnode.type).toBe('div')
|
|
283
346
|
expect(vnode.props.class).toMatch(/^pyr-/)
|
|
284
347
|
})
|
|
285
348
|
|
|
286
|
-
it(
|
|
287
|
-
const Comp = styled.span`
|
|
349
|
+
it('styled.span creates a span component', () => {
|
|
350
|
+
const Comp = styled.span`
|
|
351
|
+
font-size: 16px;
|
|
352
|
+
`
|
|
288
353
|
const vnode = Comp({}) as VNode
|
|
289
|
-
expect(vnode.type).toBe(
|
|
354
|
+
expect(vnode.type).toBe('span')
|
|
290
355
|
})
|
|
291
356
|
|
|
292
|
-
it(
|
|
293
|
-
const Comp = styled.button`
|
|
357
|
+
it('styled.button creates a button component', () => {
|
|
358
|
+
const Comp = styled.button`
|
|
359
|
+
cursor: pointer;
|
|
360
|
+
`
|
|
294
361
|
const vnode = Comp({}) as VNode
|
|
295
|
-
expect(vnode.type).toBe(
|
|
362
|
+
expect(vnode.type).toBe('button')
|
|
296
363
|
})
|
|
297
364
|
|
|
298
|
-
it(
|
|
299
|
-
const Comp = styled.section`
|
|
365
|
+
it('styled.section creates a section component', () => {
|
|
366
|
+
const Comp = styled.section`
|
|
367
|
+
padding: 20px;
|
|
368
|
+
`
|
|
300
369
|
const vnode = Comp({}) as VNode
|
|
301
|
-
expect(vnode.type).toBe(
|
|
370
|
+
expect(vnode.type).toBe('section')
|
|
302
371
|
})
|
|
303
372
|
})
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { describe, expect, it } from
|
|
2
|
-
import { ThemeContext, useTheme } from
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { ThemeContext, useTheme } from '../ThemeProvider'
|
|
3
3
|
|
|
4
|
-
describe(
|
|
5
|
-
it(
|
|
4
|
+
describe('ThemeContext', () => {
|
|
5
|
+
it('is a Context object', () => {
|
|
6
6
|
expect(ThemeContext).toBeDefined()
|
|
7
7
|
expect(ThemeContext.id).toBeDefined()
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
-
it(
|
|
11
|
-
expect(typeof ThemeContext.id).toBe(
|
|
10
|
+
it('has an id property for context identification', () => {
|
|
11
|
+
expect(typeof ThemeContext.id).toBe('symbol')
|
|
12
12
|
})
|
|
13
13
|
})
|
|
14
14
|
|
|
15
|
-
describe(
|
|
16
|
-
it(
|
|
17
|
-
expect(typeof useTheme).toBe(
|
|
15
|
+
describe('useTheme', () => {
|
|
16
|
+
it('is a function', () => {
|
|
17
|
+
expect(typeof useTheme).toBe('function')
|
|
18
18
|
})
|
|
19
19
|
|
|
20
|
-
it(
|
|
20
|
+
it('returns the default theme (empty object) when called outside a provider', () => {
|
|
21
21
|
const theme = useTheme()
|
|
22
22
|
expect(theme).toEqual({})
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
-
it(
|
|
25
|
+
it('can be called with a type parameter', () => {
|
|
26
26
|
interface MyTheme {
|
|
27
27
|
primary: string
|
|
28
28
|
spacing: number
|