@pyreon/rocketstyle 0.11.0 → 0.11.2
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/package.json +14 -12
- package/src/__tests__/attrs.test.ts +190 -0
- package/src/__tests__/chaining.test.ts +86 -0
- package/src/__tests__/collection.test.ts +35 -0
- package/src/__tests__/compose.test.ts +36 -0
- package/src/__tests__/context.test.ts +200 -0
- package/src/__tests__/createLocalProvider.test.ts +248 -0
- package/src/__tests__/dimensions.test.ts +183 -0
- package/src/__tests__/e2e-styler.test.ts +291 -0
- package/src/__tests__/hooks.test.ts +207 -0
- package/src/__tests__/isRocketComponent.test.ts +48 -0
- package/src/__tests__/misc.test.ts +204 -0
- package/src/__tests__/providerConsumer.test.ts +248 -0
- package/src/__tests__/rocketstyleIntegration.test.ts +615 -0
- package/src/__tests__/themeUtils.test.ts +463 -0
- package/src/cache/LocalThemeManager.ts +14 -0
- package/src/cache/index.ts +3 -0
- package/src/constants/booleanTags.ts +32 -0
- package/src/constants/defaultDimensions.ts +23 -0
- package/src/constants/index.ts +44 -0
- package/src/context/context.ts +51 -0
- package/src/context/createLocalProvider.ts +84 -0
- package/src/context/localContext.ts +37 -0
- package/src/hoc/index.ts +3 -0
- package/src/hoc/rocketstyleAttrsHoc.ts +63 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/usePseudoState.ts +79 -0
- package/src/hooks/useTheme.ts +36 -0
- package/src/index.ts +77 -0
- package/src/init.ts +93 -0
- package/src/isRocketComponent.ts +16 -0
- package/src/rocketstyle.ts +320 -0
- package/src/types/attrs.ts +13 -0
- package/src/types/config.ts +48 -0
- package/src/types/configuration.ts +69 -0
- package/src/types/dimensions.ts +106 -0
- package/src/types/hoc.ts +5 -0
- package/src/types/pseudo.ts +19 -0
- package/src/types/rocketComponent.ts +24 -0
- package/src/types/rocketstyle.ts +156 -0
- package/src/types/styles.ts +46 -0
- package/src/types/theme.ts +19 -0
- package/src/types/utils.ts +55 -0
- package/src/utils/attrs.ts +134 -0
- package/src/utils/chaining.ts +58 -0
- package/src/utils/collection.ts +9 -0
- package/src/utils/compose.ts +11 -0
- package/src/utils/dimensions.ts +126 -0
- package/src/utils/statics.ts +44 -0
- package/src/utils/styles.ts +18 -0
- package/src/utils/theme.ts +196 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import ThemeManager from "../cache/LocalThemeManager"
|
|
2
|
+
import {
|
|
3
|
+
ALL_RESERVED_KEYS,
|
|
4
|
+
CONFIG_KEYS,
|
|
5
|
+
MODE_DEFAULT,
|
|
6
|
+
PSEUDO_KEYS,
|
|
7
|
+
PSEUDO_META_KEYS,
|
|
8
|
+
STATIC_KEYS,
|
|
9
|
+
STYLING_KEYS,
|
|
10
|
+
THEME_MODES,
|
|
11
|
+
THEME_MODES_INVERSED,
|
|
12
|
+
} from "../constants"
|
|
13
|
+
import BOOLEAN_TAGS from "../constants/booleanTags"
|
|
14
|
+
import DEFAULT_DIMENSIONS from "../constants/defaultDimensions"
|
|
15
|
+
import { createStaticsChainingEnhancers, createStaticsEnhancers } from "../utils/statics"
|
|
16
|
+
import { calculateStyles } from "../utils/styles"
|
|
17
|
+
|
|
18
|
+
describe("createStaticsChainingEnhancers", () => {
|
|
19
|
+
it("attaches chaining methods for dimension keys + static keys", () => {
|
|
20
|
+
const context: Record<string, any> = {}
|
|
21
|
+
const func = vi.fn()
|
|
22
|
+
|
|
23
|
+
createStaticsChainingEnhancers({
|
|
24
|
+
context,
|
|
25
|
+
dimensionKeys: ["states", "sizes"],
|
|
26
|
+
func,
|
|
27
|
+
options: {} as any,
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
expect(typeof context.states).toBe("function")
|
|
31
|
+
expect(typeof context.sizes).toBe("function")
|
|
32
|
+
expect(typeof context.theme).toBe("function")
|
|
33
|
+
expect(typeof context.styles).toBe("function")
|
|
34
|
+
expect(typeof context.compose).toBe("function")
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it("calls func with options and key-value pair", () => {
|
|
38
|
+
const context: Record<string, any> = {}
|
|
39
|
+
const func = vi.fn()
|
|
40
|
+
const options = { some: "option" } as any
|
|
41
|
+
|
|
42
|
+
createStaticsChainingEnhancers({
|
|
43
|
+
context,
|
|
44
|
+
dimensionKeys: ["states"],
|
|
45
|
+
func,
|
|
46
|
+
options,
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
context.states({ primary: { color: "red" } })
|
|
50
|
+
expect(func).toHaveBeenCalledWith(options, {
|
|
51
|
+
states: { primary: { color: "red" } },
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
describe("createStaticsEnhancers", () => {
|
|
57
|
+
it("copies options to context", () => {
|
|
58
|
+
const context: Record<string, any> = {}
|
|
59
|
+
createStaticsEnhancers({ context, options: { foo: "bar", baz: 42 } })
|
|
60
|
+
expect(context.foo).toBe("bar")
|
|
61
|
+
expect(context.baz).toBe(42)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it("does nothing when options is empty", () => {
|
|
65
|
+
const context: Record<string, any> = { existing: true }
|
|
66
|
+
createStaticsEnhancers({ context, options: {} })
|
|
67
|
+
expect(context).toEqual({ existing: true })
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it("does nothing when options is undefined", () => {
|
|
71
|
+
const context: Record<string, any> = { existing: true }
|
|
72
|
+
createStaticsEnhancers({ context, options: undefined as any })
|
|
73
|
+
expect(context).toEqual({ existing: true })
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
describe("calculateStyles", () => {
|
|
78
|
+
it("returns empty array when styles is undefined", () => {
|
|
79
|
+
expect(calculateStyles(undefined)).toEqual([])
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it("evaluates each style callback", () => {
|
|
83
|
+
const styleFn1 = () => "style1"
|
|
84
|
+
const styleFn2 = () => "style2"
|
|
85
|
+
const result = calculateStyles([styleFn1, styleFn2] as any)
|
|
86
|
+
expect(result).toHaveLength(2)
|
|
87
|
+
expect(result[0]).toBe("style1")
|
|
88
|
+
expect(result[1]).toBe("style2")
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it("returns empty array for empty styles array", () => {
|
|
92
|
+
const result = calculateStyles([])
|
|
93
|
+
expect(result).toEqual([])
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
describe("ThemeManager", () => {
|
|
98
|
+
it("creates instance with WeakMap caches", () => {
|
|
99
|
+
const tm = new ThemeManager()
|
|
100
|
+
expect(tm.baseTheme).toBeInstanceOf(WeakMap)
|
|
101
|
+
expect(tm.dimensionsThemes).toBeInstanceOf(WeakMap)
|
|
102
|
+
expect(tm.modeBaseTheme.light).toBeInstanceOf(WeakMap)
|
|
103
|
+
expect(tm.modeBaseTheme.dark).toBeInstanceOf(WeakMap)
|
|
104
|
+
expect(tm.modeDimensionTheme.light).toBeInstanceOf(WeakMap)
|
|
105
|
+
expect(tm.modeDimensionTheme.dark).toBeInstanceOf(WeakMap)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it("caches and retrieves values", () => {
|
|
109
|
+
const tm = new ThemeManager()
|
|
110
|
+
const key = {}
|
|
111
|
+
tm.baseTheme.set(key, { color: "red" })
|
|
112
|
+
expect(tm.baseTheme.get(key)).toEqual({ color: "red" })
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it("mode caches are independent", () => {
|
|
116
|
+
const tm = new ThemeManager()
|
|
117
|
+
const key = {}
|
|
118
|
+
tm.modeBaseTheme.light.set(key, "light-theme")
|
|
119
|
+
tm.modeBaseTheme.dark.set(key, "dark-theme")
|
|
120
|
+
expect(tm.modeBaseTheme.light.get(key)).toBe("light-theme")
|
|
121
|
+
expect(tm.modeBaseTheme.dark.get(key)).toBe("dark-theme")
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
describe("constants", () => {
|
|
126
|
+
it("MODE_DEFAULT is light", () => {
|
|
127
|
+
expect(MODE_DEFAULT).toBe("light")
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
it("PSEUDO_KEYS", () => {
|
|
131
|
+
expect(PSEUDO_KEYS).toEqual(["hover", "active", "focus", "pressed"])
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
it("PSEUDO_META_KEYS", () => {
|
|
135
|
+
expect(PSEUDO_META_KEYS).toEqual(["disabled", "readOnly"])
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it("THEME_MODES", () => {
|
|
139
|
+
expect(THEME_MODES.light).toBe(true)
|
|
140
|
+
expect(THEME_MODES.dark).toBe(true)
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
it("THEME_MODES_INVERSED", () => {
|
|
144
|
+
expect(THEME_MODES_INVERSED.light).toBe("dark")
|
|
145
|
+
expect(THEME_MODES_INVERSED.dark).toBe("light")
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it("CONFIG_KEYS includes expected keys", () => {
|
|
149
|
+
expect(CONFIG_KEYS).toContain("provider")
|
|
150
|
+
expect(CONFIG_KEYS).toContain("consumer")
|
|
151
|
+
expect(CONFIG_KEYS).toContain("name")
|
|
152
|
+
expect(CONFIG_KEYS).toContain("component")
|
|
153
|
+
expect(CONFIG_KEYS).toContain("inversed")
|
|
154
|
+
expect(CONFIG_KEYS).toContain("passProps")
|
|
155
|
+
expect(CONFIG_KEYS).toContain("styled")
|
|
156
|
+
expect(CONFIG_KEYS).toContain("DEBUG")
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it("STYLING_KEYS", () => {
|
|
160
|
+
expect(STYLING_KEYS).toEqual(["theme", "styles"])
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
it("STATIC_KEYS includes styling keys and compose", () => {
|
|
164
|
+
expect(STATIC_KEYS).toContain("theme")
|
|
165
|
+
expect(STATIC_KEYS).toContain("styles")
|
|
166
|
+
expect(STATIC_KEYS).toContain("compose")
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
it("ALL_RESERVED_KEYS includes mode keys and others", () => {
|
|
170
|
+
expect(ALL_RESERVED_KEYS).toContain("light")
|
|
171
|
+
expect(ALL_RESERVED_KEYS).toContain("dark")
|
|
172
|
+
expect(ALL_RESERVED_KEYS).toContain("attrs")
|
|
173
|
+
expect(ALL_RESERVED_KEYS).toContain("theme")
|
|
174
|
+
expect(ALL_RESERVED_KEYS).toContain("compose")
|
|
175
|
+
})
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
describe("DEFAULT_DIMENSIONS", () => {
|
|
179
|
+
it("has states, sizes, variants, multiple", () => {
|
|
180
|
+
expect(DEFAULT_DIMENSIONS.states).toBe("state")
|
|
181
|
+
expect(DEFAULT_DIMENSIONS.sizes).toBe("size")
|
|
182
|
+
expect(DEFAULT_DIMENSIONS.variants).toBe("variant")
|
|
183
|
+
expect(DEFAULT_DIMENSIONS.multiple).toEqual({
|
|
184
|
+
propName: "multiple",
|
|
185
|
+
multi: true,
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
describe("BOOLEAN_TAGS", () => {
|
|
191
|
+
it("is an array of HTML boolean attributes", () => {
|
|
192
|
+
expect(Array.isArray(BOOLEAN_TAGS)).toBe(true)
|
|
193
|
+
expect(BOOLEAN_TAGS).toContain("disabled")
|
|
194
|
+
expect(BOOLEAN_TAGS).toContain("checked")
|
|
195
|
+
expect(BOOLEAN_TAGS).toContain("readOnly")
|
|
196
|
+
expect(BOOLEAN_TAGS).toContain("required")
|
|
197
|
+
expect(BOOLEAN_TAGS).toContain("hidden")
|
|
198
|
+
expect(BOOLEAN_TAGS).toContain("autoFocus")
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
it("has more than 20 entries", () => {
|
|
202
|
+
expect(BOOLEAN_TAGS.length).toBeGreaterThan(20)
|
|
203
|
+
})
|
|
204
|
+
})
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { popContext, pushContext } from "@pyreon/core"
|
|
2
|
+
import { config } from "@pyreon/ui-core"
|
|
3
|
+
import { context } from "../context/context"
|
|
4
|
+
import rocketstyle from "../init"
|
|
5
|
+
|
|
6
|
+
// Mock styled function that returns the component unchanged
|
|
7
|
+
const mockStyled = (component: any) => {
|
|
8
|
+
const taggedTemplate = (_strings: any, ..._args: any[]) => component
|
|
9
|
+
return taggedTemplate
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const mockCss = (_strings: any, ..._args: any[]) => ""
|
|
13
|
+
|
|
14
|
+
const originalStyled = config.styled
|
|
15
|
+
const originalCss = config.css
|
|
16
|
+
|
|
17
|
+
beforeAll(() => {
|
|
18
|
+
config.init({
|
|
19
|
+
css: mockCss as any,
|
|
20
|
+
styled: mockStyled as any,
|
|
21
|
+
component: "div",
|
|
22
|
+
textComponent: "span",
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
afterAll(() => {
|
|
27
|
+
config.styled = originalStyled
|
|
28
|
+
config.css = originalCss
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Base component that exposes internal props for testing.
|
|
33
|
+
* In Pyreon, components are plain functions — no forwardRef needed.
|
|
34
|
+
*/
|
|
35
|
+
const BaseComponent: any = ({ children, $rocketstyle, $rocketstate, ...rest }: any) => ({
|
|
36
|
+
type: "div",
|
|
37
|
+
props: {
|
|
38
|
+
...rest,
|
|
39
|
+
"data-hover": String($rocketstate?.pseudo?.hover ?? "none"),
|
|
40
|
+
"data-focus": String($rocketstate?.pseudo?.focus ?? "none"),
|
|
41
|
+
"data-pressed": String($rocketstate?.pseudo?.pressed ?? "none"),
|
|
42
|
+
},
|
|
43
|
+
children,
|
|
44
|
+
$rocketstyle,
|
|
45
|
+
$rocketstate,
|
|
46
|
+
})
|
|
47
|
+
BaseComponent.displayName = "BaseComponent"
|
|
48
|
+
|
|
49
|
+
/** Child component that reads consumer context */
|
|
50
|
+
const ChildComponent: any = ({
|
|
51
|
+
children,
|
|
52
|
+
$rocketstyle,
|
|
53
|
+
$rocketstate,
|
|
54
|
+
parentHover,
|
|
55
|
+
...rest
|
|
56
|
+
}: any) => ({
|
|
57
|
+
type: "div",
|
|
58
|
+
props: { ...rest, "data-parent-hover": parentHover ?? "none" },
|
|
59
|
+
children,
|
|
60
|
+
})
|
|
61
|
+
ChildComponent.displayName = "ChildComponent"
|
|
62
|
+
|
|
63
|
+
/** Push a theme context and run fn, then pop */
|
|
64
|
+
const withThemeContext = (fn: () => any) => {
|
|
65
|
+
pushContext(
|
|
66
|
+
new Map([
|
|
67
|
+
[
|
|
68
|
+
context.id,
|
|
69
|
+
{
|
|
70
|
+
theme: { rootSize: 16 },
|
|
71
|
+
mode: "light",
|
|
72
|
+
isDark: false,
|
|
73
|
+
isLight: true,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
]),
|
|
77
|
+
)
|
|
78
|
+
try {
|
|
79
|
+
return fn()
|
|
80
|
+
} finally {
|
|
81
|
+
popContext()
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// --------------------------------------------------------
|
|
86
|
+
// Provider/Consumer integration
|
|
87
|
+
// --------------------------------------------------------
|
|
88
|
+
describe("Provider/Consumer integration", () => {
|
|
89
|
+
describe("provider component", () => {
|
|
90
|
+
it("renders with provider: true", () => {
|
|
91
|
+
const ParentButton: any = rocketstyle()({
|
|
92
|
+
name: "ProviderButton",
|
|
93
|
+
component: BaseComponent,
|
|
94
|
+
}).config({ provider: true })
|
|
95
|
+
|
|
96
|
+
const result = withThemeContext(() => ParentButton({ children: "Child" }))
|
|
97
|
+
expect(result).toBeDefined()
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it("detects pseudo-state via $rocketstate on provider", () => {
|
|
101
|
+
const ParentButton: any = rocketstyle()({
|
|
102
|
+
name: "HoverProvider",
|
|
103
|
+
component: BaseComponent,
|
|
104
|
+
}).config({ provider: true })
|
|
105
|
+
|
|
106
|
+
const result = withThemeContext(() => ParentButton({ children: "Child" }))
|
|
107
|
+
// Provider wraps with createLocalProvider which injects pseudo state
|
|
108
|
+
// Initial state should be false
|
|
109
|
+
expect(result.props["data-hover"]).toBe("false")
|
|
110
|
+
expect(result.props["data-focus"]).toBe("false")
|
|
111
|
+
expect(result.props["data-pressed"]).toBe("false")
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
describe("consumer component", () => {
|
|
116
|
+
it("consumer receives pseudo-state from provider context", () => {
|
|
117
|
+
const Parent: any = rocketstyle()({
|
|
118
|
+
name: "ParentProvider",
|
|
119
|
+
component: BaseComponent,
|
|
120
|
+
}).config({ provider: true })
|
|
121
|
+
|
|
122
|
+
const Child: any = rocketstyle()({
|
|
123
|
+
name: "ChildConsumer",
|
|
124
|
+
component: ChildComponent,
|
|
125
|
+
}).config({
|
|
126
|
+
consumer: (ctx: any) =>
|
|
127
|
+
ctx((rawCtx: any) => ({
|
|
128
|
+
parentHover: rawCtx?.pseudo?.hover ? "yes" : "no",
|
|
129
|
+
})),
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
// Render parent, then render child within the same context
|
|
133
|
+
withThemeContext(() => {
|
|
134
|
+
const _parentResult = Parent({ children: null })
|
|
135
|
+
// The parent pushes local context — child should see it
|
|
136
|
+
const childResult = Child({})
|
|
137
|
+
expect(childResult).toBeDefined()
|
|
138
|
+
const childProps = childResult?.props ?? childResult
|
|
139
|
+
expect(childProps["data-parent-hover"]).toBe("no")
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
it("consumer without provider returns default pseudo", () => {
|
|
144
|
+
const Child: any = rocketstyle()({
|
|
145
|
+
name: "OrphanConsumer",
|
|
146
|
+
component: ChildComponent,
|
|
147
|
+
}).config({
|
|
148
|
+
consumer: (ctx: any) =>
|
|
149
|
+
ctx((rawCtx: any) => ({
|
|
150
|
+
parentHover: rawCtx?.pseudo?.hover ? "yes" : "no",
|
|
151
|
+
})),
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
const result = withThemeContext(() => Child({}))
|
|
155
|
+
const props = result?.props ?? result
|
|
156
|
+
expect(props["data-parent-hover"]).toBe("no")
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it("component without consumer ignores provider context", () => {
|
|
160
|
+
const Parent: any = rocketstyle()({
|
|
161
|
+
name: "IgnoredProvider",
|
|
162
|
+
component: BaseComponent,
|
|
163
|
+
}).config({ provider: true })
|
|
164
|
+
|
|
165
|
+
const Child: any = rocketstyle()({
|
|
166
|
+
name: "NoConsumer",
|
|
167
|
+
component: BaseComponent,
|
|
168
|
+
}).config({})
|
|
169
|
+
|
|
170
|
+
withThemeContext(() => {
|
|
171
|
+
Parent({ children: null })
|
|
172
|
+
const childResult = Child({})
|
|
173
|
+
expect(childResult).toBeDefined()
|
|
174
|
+
})
|
|
175
|
+
})
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
describe("theme mode", () => {
|
|
179
|
+
it("light mode is default", () => {
|
|
180
|
+
const Button: any = rocketstyle()({
|
|
181
|
+
name: "LightButton",
|
|
182
|
+
component: BaseComponent,
|
|
183
|
+
}).config({})
|
|
184
|
+
|
|
185
|
+
const result = withThemeContext(() => Button({}))
|
|
186
|
+
expect(result).toBeDefined()
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
it("dark mode is passed through Provider", () => {
|
|
190
|
+
const Button: any = rocketstyle()({
|
|
191
|
+
name: "DarkButton",
|
|
192
|
+
component: BaseComponent,
|
|
193
|
+
}).config({})
|
|
194
|
+
|
|
195
|
+
pushContext(
|
|
196
|
+
new Map([
|
|
197
|
+
[
|
|
198
|
+
context.id,
|
|
199
|
+
{
|
|
200
|
+
theme: { rootSize: 16 },
|
|
201
|
+
mode: "dark",
|
|
202
|
+
isDark: true,
|
|
203
|
+
isLight: false,
|
|
204
|
+
},
|
|
205
|
+
],
|
|
206
|
+
]),
|
|
207
|
+
)
|
|
208
|
+
try {
|
|
209
|
+
const result = Button({})
|
|
210
|
+
expect(result).toBeDefined()
|
|
211
|
+
} finally {
|
|
212
|
+
popContext()
|
|
213
|
+
}
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
it("inversed config flips the mode", () => {
|
|
217
|
+
const Button: any = rocketstyle()({
|
|
218
|
+
name: "InversedButton",
|
|
219
|
+
component: BaseComponent,
|
|
220
|
+
}).config({ inversed: true })
|
|
221
|
+
|
|
222
|
+
const result = withThemeContext(() => Button({}))
|
|
223
|
+
expect(result).toBeDefined()
|
|
224
|
+
})
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
describe("nested providers", () => {
|
|
228
|
+
it("supports nested provider components", () => {
|
|
229
|
+
const Outer: any = rocketstyle()({
|
|
230
|
+
name: "OuterProvider",
|
|
231
|
+
component: BaseComponent,
|
|
232
|
+
}).config({ provider: true })
|
|
233
|
+
|
|
234
|
+
const Inner: any = rocketstyle()({
|
|
235
|
+
name: "InnerProvider",
|
|
236
|
+
component: BaseComponent,
|
|
237
|
+
}).config({ provider: true })
|
|
238
|
+
|
|
239
|
+
withThemeContext(() => {
|
|
240
|
+
const outerResult = Outer({ children: null })
|
|
241
|
+
expect(outerResult).toBeDefined()
|
|
242
|
+
|
|
243
|
+
const innerResult = Inner({ children: null })
|
|
244
|
+
expect(innerResult).toBeDefined()
|
|
245
|
+
})
|
|
246
|
+
})
|
|
247
|
+
})
|
|
248
|
+
})
|