@codeleap/styles 5.8.1 → 5.8.3
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 +9 -15
- package/package.json.bak +8 -14
- package/src/classes/Cacher.ts +169 -0
- package/src/classes/StaleControl.ts +125 -0
- package/src/classes/StyleCache.ts +116 -0
- package/src/classes/StylePersistor.ts +62 -0
- package/src/{lib → classes}/StyleRegistry.ts +7 -12
- package/src/classes/index.ts +2 -0
- package/src/classes/tests/Cache.spec.ts +371 -0
- package/src/classes/tests/StaleControl.spec.ts +175 -0
- package/src/classes/tests/StyleCache.spec.ts +452 -0
- package/src/classes/tests/StylePersistor.spec.ts +231 -0
- package/src/{lib/constants.ts → constants.ts} +1 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/tests/useCompositionStyles.spec.ts +107 -0
- package/src/hooks/tests/useStyleObserver.spec.ts +89 -0
- package/src/hooks/useCompositionStyles.ts +33 -0
- package/src/hooks/useNestedStylesByKey.ts +13 -0
- package/src/hooks/useStyleObserver.ts +19 -0
- package/src/hooks/useTheme.ts +16 -0
- package/src/index.ts +9 -5
- package/src/lib/createStyles.ts +10 -1
- package/src/lib/createTheme.ts +22 -13
- package/src/lib/index.ts +1 -10
- package/src/lib/tests/createStyles.spec.ts +151 -0
- package/src/tests/colors/baseColors.ts +166 -0
- package/src/tests/colors/darkMode.ts +232 -0
- package/src/tests/colors/lightMode.ts +285 -0
- package/src/tests/measures.ts +31 -0
- package/src/tests/theme.ts +58 -0
- package/src/theme/generateColorScheme.ts +53 -0
- package/src/theme/index.ts +3 -0
- package/src/theme/tests/generateColorScheme.spec.ts +118 -0
- package/src/theme/tests/themeStore.spec.ts +698 -0
- package/src/theme/tests/validateTheme.spec.ts +173 -0
- package/src/{lib → theme}/themeStore.ts +68 -3
- package/src/{lib → theme}/validateTheme.ts +13 -0
- package/src/tools/colors.ts +83 -39
- package/src/tools/deepClone.ts +10 -0
- package/src/tools/deepmerge.ts +10 -0
- package/src/{lib → tools}/hashKey.ts +7 -0
- package/src/tools/index.ts +6 -1
- package/src/tools/minifier.ts +38 -0
- package/src/tools/tests/colors.spec.ts +233 -0
- package/src/tools/tests/deepClone.spec.ts +102 -0
- package/src/tools/tests/deepmerge.spec.ts +155 -0
- package/src/tools/tests/hashKey.spec.ts +69 -0
- package/src/tools/tests/minifier.spec.ts +173 -0
- package/src/types/store.ts +2 -2
- package/src/types/style.ts +3 -3
- package/src/types/theme.ts +4 -4
- package/src/{lib/utils.ts → utils.ts} +3 -3
- package/src/{lib → variants}/borderCreator.ts +2 -2
- package/src/{lib → variants}/createAppVariants.ts +1 -1
- package/src/{lib → variants}/dynamicVariants.ts +1 -1
- package/src/variants/index.ts +6 -0
- package/src/{lib → variants}/spacing.ts +37 -24
- package/src/variants/tests/borderCreator.spec.ts +180 -0
- package/src/variants/tests/dynamicVariants.spec.ts +194 -0
- package/src/variants/tests/spacing.spec.ts +177 -0
- package/src/lib/Cacher.ts +0 -112
- package/src/lib/StaleControl.ts +0 -73
- package/src/lib/StyleCache.ts +0 -81
- package/src/lib/StylePersistor.ts +0 -28
- package/src/lib/hooks.ts +0 -60
- package/src/lib/minifier.ts +0 -20
- /package/src/{lib → tools}/multiplierProperty.ts +0 -0
- /package/src/{lib → variants}/defaultVariants.ts +0 -0
- /package/src/{lib → variants}/mediaQuery.ts +0 -0
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'bun:test'
|
|
2
|
+
import { ThemeStore, themeStore, themeStoreComputed } from '../themeStore'
|
|
3
|
+
|
|
4
|
+
describe('ThemeStore - Heavy Load Tests', () => {
|
|
5
|
+
let store: ThemeStore
|
|
6
|
+
|
|
7
|
+
const getThemeStore = () => store.theme as any
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
store = new ThemeStore()
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
describe('basic functionality', () => {
|
|
14
|
+
it('should handle theme management', () => {
|
|
15
|
+
const mockTheme = {
|
|
16
|
+
colors: { primary: '#007bff' },
|
|
17
|
+
spacing: { small: '8px' }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
store.setTheme(mockTheme)
|
|
21
|
+
expect(getThemeStore()).toEqual(mockTheme)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('should handle color scheme management', () => {
|
|
25
|
+
store.setColorScheme('dark')
|
|
26
|
+
expect(store.colorScheme).toBe('dark')
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
describe('stress tests - massive data operations', () => {
|
|
31
|
+
it('should handle thousands of theme updates without performance degradation', () => {
|
|
32
|
+
const iterations = 10000
|
|
33
|
+
const startTime = performance.now()
|
|
34
|
+
|
|
35
|
+
for (let i = 0; i < iterations; i++) {
|
|
36
|
+
const theme = {
|
|
37
|
+
colors: {
|
|
38
|
+
primary: `#${i.toString(16).padStart(6, '0')}`,
|
|
39
|
+
secondary: `#${(i * 2).toString(16).padStart(6, '0')}`,
|
|
40
|
+
background: `#${(i * 3).toString(16).padStart(6, '0')}`,
|
|
41
|
+
surface: `#${(i * 4).toString(16).padStart(6, '0')}`,
|
|
42
|
+
text: `#${(i * 5).toString(16).padStart(6, '0')}`
|
|
43
|
+
},
|
|
44
|
+
spacing: {
|
|
45
|
+
xs: `${i}px`,
|
|
46
|
+
sm: `${i * 2}px`,
|
|
47
|
+
md: `${i * 4}px`,
|
|
48
|
+
lg: `${i * 8}px`,
|
|
49
|
+
xl: `${i * 16}px`
|
|
50
|
+
},
|
|
51
|
+
typography: {
|
|
52
|
+
fontSize: `${i}px`,
|
|
53
|
+
fontWeight: i % 900,
|
|
54
|
+
lineHeight: i / 100
|
|
55
|
+
},
|
|
56
|
+
iteration: i
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
store.setTheme(theme)
|
|
60
|
+
|
|
61
|
+
// Verify state is correctly updated every 1000 iterations
|
|
62
|
+
if (i % 1000 === 0) {
|
|
63
|
+
expect(getThemeStore()?.iteration).toBe(i)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const endTime = performance.now()
|
|
68
|
+
const executionTime = endTime - startTime
|
|
69
|
+
|
|
70
|
+
// Should complete within reasonable time (adjust threshold as needed)
|
|
71
|
+
expect(executionTime).toBeLessThan(5000) // 5 seconds
|
|
72
|
+
expect(getThemeStore()?.iteration).toBe(iterations - 1)
|
|
73
|
+
|
|
74
|
+
console.log(`Theme updates: ${iterations} operations in ${executionTime.toFixed(2)}ms`)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('should handle massive color schemes with deep nesting', () => {
|
|
78
|
+
const colorSchemes = {}
|
|
79
|
+
const schemeCount = 1000
|
|
80
|
+
const colorsPerScheme = 100
|
|
81
|
+
|
|
82
|
+
// Generate massive color schemes
|
|
83
|
+
for (let scheme = 0; scheme < schemeCount; scheme++) {
|
|
84
|
+
const colors = {}
|
|
85
|
+
for (let color = 0; color < colorsPerScheme; color++) {
|
|
86
|
+
colors[`color_${color}`] = {
|
|
87
|
+
primary: `#${(scheme * color).toString(16).padStart(6, '0')}`,
|
|
88
|
+
variants: {
|
|
89
|
+
light: `#${(scheme * color + 100000).toString(16).padStart(6, '0')}`,
|
|
90
|
+
dark: `#${(scheme * color + 200000).toString(16).padStart(6, '0')}`,
|
|
91
|
+
medium: `#${(scheme * color + 300000).toString(16).padStart(6, '0')}`
|
|
92
|
+
},
|
|
93
|
+
states: {
|
|
94
|
+
hover: `#${(scheme * color + 400000).toString(16).padStart(6, '0')}`,
|
|
95
|
+
active: `#${(scheme * color + 500000).toString(16).padStart(6, '0')}`,
|
|
96
|
+
disabled: `#${(scheme * color + 600000).toString(16).padStart(6, '0')}`,
|
|
97
|
+
focus: `#${(scheme * color + 700000).toString(16).padStart(6, '0')}`
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
colorSchemes[`scheme_${scheme}`] = colors
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const startTime = performance.now()
|
|
105
|
+
store.setAlternateColorsScheme(colorSchemes)
|
|
106
|
+
const endTime = performance.now()
|
|
107
|
+
|
|
108
|
+
expect(Object.keys(store.alternateColorsScheme)).toHaveLength(schemeCount)
|
|
109
|
+
expect(Object.keys(store.alternateColorsScheme.scheme_0)).toHaveLength(colorsPerScheme)
|
|
110
|
+
|
|
111
|
+
console.log(`Color schemes: ${schemeCount} schemes with ${colorsPerScheme} colors each in ${(endTime - startTime).toFixed(2)}ms`)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('should handle rapid color scheme injections and ejections', () => {
|
|
115
|
+
const operations = 5000
|
|
116
|
+
const startTime = performance.now()
|
|
117
|
+
|
|
118
|
+
// Initial base scheme
|
|
119
|
+
store.setAlternateColorsScheme({
|
|
120
|
+
base: {
|
|
121
|
+
primary: '#000000',
|
|
122
|
+
secondary: '#111111',
|
|
123
|
+
tertiary: '#222222'
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
for (let i = 0; i < operations; i++) {
|
|
128
|
+
const schemeName = `scheme_${i}`
|
|
129
|
+
const colors = {
|
|
130
|
+
primary: `#${i.toString(16).padStart(6, '0')}`,
|
|
131
|
+
accent: `#${(i * 2).toString(16).padStart(6, '0')}`,
|
|
132
|
+
background: `#${(i * 3).toString(16).padStart(6, '0')}`,
|
|
133
|
+
customColor: `#${(i * 4).toString(16).padStart(6, '0')}`
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Inject scheme
|
|
137
|
+
const injected = store.injectColorScheme(schemeName, colors)
|
|
138
|
+
expect(injected[schemeName]).toBeDefined()
|
|
139
|
+
expect(injected[schemeName].primary).toBe(colors.primary)
|
|
140
|
+
expect(injected[schemeName].secondary).toBe('#111111') // inherited
|
|
141
|
+
|
|
142
|
+
// Every 10th operation, eject some schemes
|
|
143
|
+
if (i % 10 === 0 && i > 0) {
|
|
144
|
+
const toEject = `scheme_${i - 5}`
|
|
145
|
+
store.ejectColorScheme(toEject)
|
|
146
|
+
expect(store.alternateColorsScheme[toEject]).toBeUndefined()
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const endTime = performance.now()
|
|
151
|
+
const executionTime = endTime - startTime
|
|
152
|
+
|
|
153
|
+
expect(executionTime).toBeLessThan(3000) // Should be fast
|
|
154
|
+
console.log(`Color scheme operations: ${operations} inject/eject operations in ${executionTime.toFixed(2)}ms`)
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('should handle massive variants with complex structures', () => {
|
|
158
|
+
const componentCount = 500
|
|
159
|
+
const variantsPerComponent = 50
|
|
160
|
+
const variants = {}
|
|
161
|
+
|
|
162
|
+
for (let comp = 0; comp < componentCount; comp++) {
|
|
163
|
+
const componentVariants = {}
|
|
164
|
+
for (let variant = 0; variant < variantsPerComponent; variant++) {
|
|
165
|
+
componentVariants[`variant_${variant}`] = {
|
|
166
|
+
className: `comp-${comp}-var-${variant}`,
|
|
167
|
+
styles: {
|
|
168
|
+
color: `#${(comp * variant).toString(16).padStart(6, '0')}`,
|
|
169
|
+
backgroundColor: `#${(comp + variant).toString(16).padStart(6, '0')}`,
|
|
170
|
+
fontSize: `${comp + variant}px`,
|
|
171
|
+
padding: `${variant}px ${comp}px`,
|
|
172
|
+
margin: `${comp * variant}px`,
|
|
173
|
+
borderRadius: `${variant / 2}px`,
|
|
174
|
+
transform: `rotate(${variant}deg) scale(${1 + comp / 100})`,
|
|
175
|
+
boxShadow: `${variant}px ${comp}px ${comp + variant}px rgba(${comp}, ${variant}, ${comp + variant}, 0.${variant})`
|
|
176
|
+
},
|
|
177
|
+
states: {
|
|
178
|
+
hover: { opacity: 0.8 + (variant / 100) },
|
|
179
|
+
active: { transform: `scale(${1 + variant / 1000})` },
|
|
180
|
+
disabled: { opacity: 0.5 },
|
|
181
|
+
focus: { outline: `${variant}px solid #${comp.toString(16).padStart(6, '0')}` }
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
variants[`component_${comp}`] = componentVariants
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const startTime = performance.now()
|
|
189
|
+
store.setVariants(variants)
|
|
190
|
+
const endTime = performance.now()
|
|
191
|
+
|
|
192
|
+
expect(Object.keys(store.variants)).toHaveLength(componentCount)
|
|
193
|
+
// @ts-ignore
|
|
194
|
+
expect(Object.keys(store.variants.component_0)).toHaveLength(variantsPerComponent)
|
|
195
|
+
|
|
196
|
+
console.log(`Variants: ${componentCount} components with ${variantsPerComponent} variants each in ${(endTime - startTime).toFixed(2)}ms`)
|
|
197
|
+
})
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
describe('concurrent operations stress test', () => {
|
|
201
|
+
it('should handle simultaneous theme, color scheme, and variants updates', () => {
|
|
202
|
+
const iterations = 2000
|
|
203
|
+
const startTime = performance.now()
|
|
204
|
+
|
|
205
|
+
for (let i = 0; i < iterations; i++) {
|
|
206
|
+
// Simultaneous updates
|
|
207
|
+
store.setTheme({
|
|
208
|
+
colors: { primary: `#${i.toString(16).padStart(6, '0')}` },
|
|
209
|
+
iteration: i
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
store.setColorScheme(`scheme_${i % 50}`)
|
|
213
|
+
|
|
214
|
+
store.setVariants({
|
|
215
|
+
[`component_${i}`]: {
|
|
216
|
+
[`variant_${i}`]: {
|
|
217
|
+
className: `test-${i}`,
|
|
218
|
+
styles: { color: `#${i.toString(16).padStart(6, '0')}` }
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
store.injectColorScheme(`dynamic_${i % 100}`, {
|
|
224
|
+
primary: `#${(i * 2).toString(16).padStart(6, '0')}`,
|
|
225
|
+
secondary: `#${(i * 3).toString(16).padStart(6, '0')}`
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
// Verify consistency every 200 iterations
|
|
229
|
+
if (i % 200 === 0) {
|
|
230
|
+
expect(getThemeStore()?.iteration).toBe(i)
|
|
231
|
+
expect(store.colorScheme).toBe(`scheme_${i % 50}`)
|
|
232
|
+
expect(store.variants[`component_${i}`]).toBeDefined()
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const endTime = performance.now()
|
|
237
|
+
const executionTime = endTime - startTime
|
|
238
|
+
|
|
239
|
+
expect(executionTime).toBeLessThan(10000) // 10 seconds
|
|
240
|
+
expect(getThemeStore()?.iteration).toBe(iterations - 1)
|
|
241
|
+
|
|
242
|
+
console.log(`Concurrent operations: ${iterations * 4} total operations in ${executionTime.toFixed(2)}ms`)
|
|
243
|
+
})
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
describe('function storage and execution stress tests', () => {
|
|
247
|
+
it('should handle thousands of stored functions with complex computations', () => {
|
|
248
|
+
const functionCount = 5000
|
|
249
|
+
const theme = {
|
|
250
|
+
colors: {},
|
|
251
|
+
spacing: {},
|
|
252
|
+
calculators: {},
|
|
253
|
+
transformers: {},
|
|
254
|
+
validators: {}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const startTime = performance.now()
|
|
258
|
+
|
|
259
|
+
// Store various types of functions
|
|
260
|
+
for (let i = 0; i < functionCount; i++) {
|
|
261
|
+
// Simple calculators
|
|
262
|
+
theme.calculators[`calc_${i}`] = (value) => value * (i + 1)
|
|
263
|
+
|
|
264
|
+
// Complex transformers
|
|
265
|
+
theme.transformers[`transform_${i}`] = (input) => {
|
|
266
|
+
return {
|
|
267
|
+
scaled: input * Math.pow(2, i % 10),
|
|
268
|
+
offset: input + (i * 3.14159),
|
|
269
|
+
computed: Math.sin(input + i) * 100,
|
|
270
|
+
conditional: input > i ? input * 2 : input / 2,
|
|
271
|
+
recursive: i > 0 ? theme.calculators[`calc_${i - 1}`]?.(input) || input : input
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Spacing functions
|
|
276
|
+
theme.spacing[`space_${i}`] = (multiplier = 1) => `${i * 8 * multiplier}px`
|
|
277
|
+
|
|
278
|
+
// Color functions
|
|
279
|
+
theme.colors[`color_${i}`] = (opacity = 1) => {
|
|
280
|
+
const r = (i * 37) % 256
|
|
281
|
+
const g = (i * 73) % 256
|
|
282
|
+
const b = (i * 113) % 256
|
|
283
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Validators
|
|
287
|
+
theme.validators[`validate_${i}`] = (value) => {
|
|
288
|
+
return value !== null &&
|
|
289
|
+
value !== undefined &&
|
|
290
|
+
(typeof value === 'number' ? value >= i : value.length >= i % 10)
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
store.setTheme(theme)
|
|
295
|
+
const setTime = performance.now()
|
|
296
|
+
|
|
297
|
+
// Execute all functions to test performance
|
|
298
|
+
let executionResults = 0
|
|
299
|
+
const executeStartTime = performance.now()
|
|
300
|
+
|
|
301
|
+
for (let i = 0; i < functionCount; i++) {
|
|
302
|
+
const testValue = i * 2.5
|
|
303
|
+
|
|
304
|
+
// Execute calculators
|
|
305
|
+
const calcResult = getThemeStore()?.calculators[`calc_${i}`]?.(testValue)
|
|
306
|
+
if (calcResult) executionResults++
|
|
307
|
+
|
|
308
|
+
// Execute transformers
|
|
309
|
+
const transformResult = getThemeStore()?.transformers[`transform_${i}`]?.(testValue)
|
|
310
|
+
if (transformResult?.scaled) executionResults++
|
|
311
|
+
|
|
312
|
+
// Execute spacing functions
|
|
313
|
+
const spacingResult = getThemeStore()?.spacing[`space_${i}`]?.(2)
|
|
314
|
+
if (spacingResult?.includes('px')) executionResults++
|
|
315
|
+
|
|
316
|
+
// Execute color functions
|
|
317
|
+
const colorResult = getThemeStore()?.colors[`color_${i}`]?.(0.8)
|
|
318
|
+
if (colorResult?.includes('rgba')) executionResults++
|
|
319
|
+
|
|
320
|
+
// Execute validators
|
|
321
|
+
const validatorResult = getThemeStore()?.validators[`validate_${i}`]?.(testValue)
|
|
322
|
+
if (typeof validatorResult === 'boolean') executionResults++
|
|
323
|
+
|
|
324
|
+
// Test some complex chaining every 100 iterations
|
|
325
|
+
if (i % 100 === 0) {
|
|
326
|
+
const chainResult = getThemeStore()?.transformers[`transform_${i}`]?.(
|
|
327
|
+
getThemeStore()?.calculators[`calc_${i}`]?.(testValue) || 0
|
|
328
|
+
)
|
|
329
|
+
if (chainResult) executionResults++
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const executeEndTime = performance.now()
|
|
334
|
+
const totalTime = executeEndTime - startTime
|
|
335
|
+
|
|
336
|
+
expect(executionResults).toBeGreaterThan(functionCount * 4) // At least 4 successful executions per function
|
|
337
|
+
expect(totalTime).toBeLessThan(15000) // Should handle massive function storage/execution
|
|
338
|
+
|
|
339
|
+
console.log(`Function storage: ${functionCount} functions stored in ${(setTime - startTime).toFixed(2)}ms`)
|
|
340
|
+
console.log(`Function execution: ${executionResults} executions in ${(executeEndTime - executeStartTime).toFixed(2)}ms`)
|
|
341
|
+
console.log(`Total function test: ${totalTime.toFixed(2)}ms`)
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
it('should handle recursive and nested function calls', () => {
|
|
345
|
+
const depth = 100
|
|
346
|
+
const iterations = 1000
|
|
347
|
+
|
|
348
|
+
// Create deeply nested function chains
|
|
349
|
+
const theme = {
|
|
350
|
+
fibonacci: {},
|
|
351
|
+
factorial: {},
|
|
352
|
+
compose: {},
|
|
353
|
+
pipeline: {}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Fibonacci functions
|
|
357
|
+
for (let i = 0; i < depth; i++) {
|
|
358
|
+
theme.fibonacci[`fib_${i}`] = (n) => {
|
|
359
|
+
if (n <= 1) return n
|
|
360
|
+
if (i > 0 && theme.fibonacci[`fib_${i - 1}`]) {
|
|
361
|
+
return theme.fibonacci[`fib_${i - 1}`](n - 1) + theme.fibonacci[`fib_${i - 1}`](n - 2)
|
|
362
|
+
}
|
|
363
|
+
return n
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Factorial chains
|
|
368
|
+
for (let i = 0; i < depth; i++) {
|
|
369
|
+
theme.factorial[`fact_${i}`] = (n) => {
|
|
370
|
+
if (n <= 1) return 1
|
|
371
|
+
const prevFact = theme.factorial[`fact_${Math.max(0, i - 1)}`]
|
|
372
|
+
return prevFact ? n * prevFact(n - 1) : n
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Function composition
|
|
377
|
+
for (let i = 0; i < depth; i++) {
|
|
378
|
+
theme.compose[`comp_${i}`] = (value) => {
|
|
379
|
+
let result = value
|
|
380
|
+
for (let j = 0; j <= i && j < 10; j++) {
|
|
381
|
+
result = Math.sqrt(Math.abs(result * (j + 1)))
|
|
382
|
+
}
|
|
383
|
+
return result
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Pipeline functions
|
|
388
|
+
for (let i = 0; i < depth; i++) {
|
|
389
|
+
theme.pipeline[`pipe_${i}`] = (input) => {
|
|
390
|
+
const steps = [
|
|
391
|
+
(x) => x * 2,
|
|
392
|
+
(x) => x + i,
|
|
393
|
+
(x) => Math.pow(x, 1.5),
|
|
394
|
+
(x) => x % 1000,
|
|
395
|
+
(x) => theme.compose[`comp_${Math.min(i, depth - 1)}`]?.(x) || x
|
|
396
|
+
]
|
|
397
|
+
return steps.reduce((acc, fn) => fn(acc), input)
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
store.setTheme(theme)
|
|
402
|
+
|
|
403
|
+
const startTime = performance.now()
|
|
404
|
+
let successfulExecutions = 0
|
|
405
|
+
|
|
406
|
+
// Execute nested functions
|
|
407
|
+
for (let i = 0; i < iterations; i++) {
|
|
408
|
+
const testValue = i % 20
|
|
409
|
+
|
|
410
|
+
try {
|
|
411
|
+
// Test fibonacci (limited to avoid stack overflow)
|
|
412
|
+
const fibResult = getThemeStore()?.fibonacci[`fib_${i % 10}`]?.(testValue % 10)
|
|
413
|
+
if (typeof fibResult === 'number') successfulExecutions++
|
|
414
|
+
|
|
415
|
+
// Test factorial
|
|
416
|
+
const factResult = getThemeStore()?.factorial[`fact_${i % depth}`]?.(testValue % 8)
|
|
417
|
+
if (typeof factResult === 'number') successfulExecutions++
|
|
418
|
+
|
|
419
|
+
// Test composition
|
|
420
|
+
const compResult = getThemeStore()?.compose[`comp_${i % depth}`]?.(testValue + 1)
|
|
421
|
+
if (typeof compResult === 'number') successfulExecutions++
|
|
422
|
+
|
|
423
|
+
// Test pipeline
|
|
424
|
+
const pipeResult = getThemeStore()?.pipeline[`pipe_${i % depth}`]?.(testValue)
|
|
425
|
+
if (typeof pipeResult === 'number') successfulExecutions++
|
|
426
|
+
|
|
427
|
+
// Test chained execution
|
|
428
|
+
if (i % 50 === 0) {
|
|
429
|
+
const chainedResult = getThemeStore()?.pipeline[`pipe_${i % depth}`]?.(
|
|
430
|
+
getThemeStore()?.compose[`comp_${i % depth}`]?.(testValue) || 0
|
|
431
|
+
)
|
|
432
|
+
if (typeof chainedResult === 'number') successfulExecutions++
|
|
433
|
+
}
|
|
434
|
+
} catch (error) {
|
|
435
|
+
// Some recursion might fail, that's ok
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const endTime = performance.now()
|
|
440
|
+
const executionTime = endTime - startTime
|
|
441
|
+
|
|
442
|
+
expect(successfulExecutions).toBeGreaterThan(iterations * 3) // Most executions should succeed
|
|
443
|
+
expect(executionTime).toBeLessThan(10000)
|
|
444
|
+
|
|
445
|
+
console.log(`Recursive functions: ${depth} depth, ${iterations} iterations, ${successfulExecutions} successful executions in ${executionTime.toFixed(2)}ms`)
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
it('should handle function factories and dynamic function generation', () => {
|
|
449
|
+
const factoryCount = 1000
|
|
450
|
+
const generatedPerFactory = 10
|
|
451
|
+
|
|
452
|
+
const theme = {
|
|
453
|
+
factories: {},
|
|
454
|
+
generated: {},
|
|
455
|
+
dynamicComputed: {}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const startTime = performance.now()
|
|
459
|
+
|
|
460
|
+
// Create function factories
|
|
461
|
+
for (let i = 0; i < factoryCount; i++) {
|
|
462
|
+
theme.factories[`factory_${i}`] = (config) => {
|
|
463
|
+
return {
|
|
464
|
+
calculator: (value) => value * (config.multiplier || 1) + (config.offset || 0),
|
|
465
|
+
validator: (value) => value >= (config.min || 0) && value <= (config.max || 1000),
|
|
466
|
+
transformer: (value) => ({
|
|
467
|
+
original: value,
|
|
468
|
+
scaled: value * (config.scale || 1),
|
|
469
|
+
formatted: `${config.prefix || ''}${value}${config.suffix || ''}`,
|
|
470
|
+
computed: Math.pow(value, config.power || 1)
|
|
471
|
+
}),
|
|
472
|
+
composer: (...fns) => (value) => fns.reduce((acc, fn) => fn(acc), value)
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Generate functions using factories
|
|
477
|
+
for (let j = 0; j < generatedPerFactory; j++) {
|
|
478
|
+
const config = {
|
|
479
|
+
multiplier: i + j,
|
|
480
|
+
offset: j * 10,
|
|
481
|
+
scale: 1 + (j / 10),
|
|
482
|
+
min: i,
|
|
483
|
+
max: i * 100,
|
|
484
|
+
prefix: `gen_${i}_`,
|
|
485
|
+
suffix: `_${j}`,
|
|
486
|
+
power: 1 + (j / 5)
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const generatedFunctions = theme.factories[`factory_${i}`](config)
|
|
490
|
+
theme.generated[`gen_${i}_${j}`] = generatedFunctions
|
|
491
|
+
|
|
492
|
+
// Create dynamic computed values
|
|
493
|
+
theme.dynamicComputed[`comp_${i}_${j}`] = (input) => {
|
|
494
|
+
const calc = generatedFunctions.calculator(input)
|
|
495
|
+
const valid = generatedFunctions.validator(calc)
|
|
496
|
+
const transform = generatedFunctions.transformer(calc)
|
|
497
|
+
|
|
498
|
+
return {
|
|
499
|
+
calculated: calc,
|
|
500
|
+
isValid: valid,
|
|
501
|
+
transformed: transform,
|
|
502
|
+
final: valid ? transform.computed : 0
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
store.setTheme(theme)
|
|
509
|
+
const creationTime = performance.now()
|
|
510
|
+
|
|
511
|
+
// Execute generated functions
|
|
512
|
+
let executionCount = 0
|
|
513
|
+
const executionStartTime = performance.now()
|
|
514
|
+
|
|
515
|
+
for (let i = 0; i < factoryCount; i++) {
|
|
516
|
+
for (let j = 0; j < generatedPerFactory; j++) {
|
|
517
|
+
const testValue = (i + j) * 1.5
|
|
518
|
+
|
|
519
|
+
try {
|
|
520
|
+
// Test generated functions
|
|
521
|
+
const generated = getThemeStore()?.generated[`gen_${i}_${j}`]
|
|
522
|
+
if (generated) {
|
|
523
|
+
const calcResult = generated.calculator(testValue)
|
|
524
|
+
const validResult = generated.validator(calcResult)
|
|
525
|
+
const transformResult = generated.transformer(testValue)
|
|
526
|
+
|
|
527
|
+
if (typeof calcResult === 'number') executionCount++
|
|
528
|
+
if (typeof validResult === 'boolean') executionCount++
|
|
529
|
+
if (transformResult?.original === testValue) executionCount++
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Test dynamic computed
|
|
533
|
+
const dynamicResult = getThemeStore()?.dynamicComputed[`comp_${i}_${j}`]?.(testValue)
|
|
534
|
+
if (dynamicResult?.calculated !== undefined) executionCount++
|
|
535
|
+
|
|
536
|
+
} catch (error) {
|
|
537
|
+
// Some executions might fail
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Test function composition every 100 iterations
|
|
541
|
+
if ((i * generatedPerFactory + j) % 100 === 0) {
|
|
542
|
+
try {
|
|
543
|
+
const generated = getThemeStore()?.generated[`gen_${i}_${j}`]
|
|
544
|
+
if (generated?.composer) {
|
|
545
|
+
const composed = generated.composer(
|
|
546
|
+
(x) => x * 2,
|
|
547
|
+
(x) => x + 10,
|
|
548
|
+
generated.calculator
|
|
549
|
+
)(testValue)
|
|
550
|
+
if (typeof composed === 'number') executionCount++
|
|
551
|
+
}
|
|
552
|
+
} catch (error) {
|
|
553
|
+
// Composition might fail
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
const executionEndTime = performance.now()
|
|
560
|
+
const totalTime = executionEndTime - startTime
|
|
561
|
+
|
|
562
|
+
const expectedOperations = factoryCount * generatedPerFactory * 3 // At least 3 operations per generated function
|
|
563
|
+
expect(executionCount).toBeGreaterThan(expectedOperations * 0.8) // 80% success rate minimum
|
|
564
|
+
expect(totalTime).toBeLessThan(20000) // 20 seconds max
|
|
565
|
+
|
|
566
|
+
console.log(`Function factories: ${factoryCount} factories generating ${factoryCount * generatedPerFactory} functions`)
|
|
567
|
+
console.log(`Creation time: ${(creationTime - startTime).toFixed(2)}ms`)
|
|
568
|
+
console.log(`Execution time: ${(executionEndTime - executionStartTime).toFixed(2)}ms`)
|
|
569
|
+
console.log(`Total operations: ${executionCount} in ${totalTime.toFixed(2)}ms`)
|
|
570
|
+
})
|
|
571
|
+
})
|
|
572
|
+
|
|
573
|
+
describe('memory pressure and cleanup', () => {
|
|
574
|
+
it('should handle massive data without memory leaks', () => {
|
|
575
|
+
const hugeSets = 10
|
|
576
|
+
const itemsPerSet = 1000
|
|
577
|
+
|
|
578
|
+
for (let set = 0; set < hugeSets; set++) {
|
|
579
|
+
// Create massive theme
|
|
580
|
+
const hugeTheme = {
|
|
581
|
+
colors: {},
|
|
582
|
+
spacing: {},
|
|
583
|
+
typography: {},
|
|
584
|
+
components: {}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
for (let i = 0; i < itemsPerSet; i++) {
|
|
588
|
+
hugeTheme.colors[`color_${i}`] = `#${i.toString(16).padStart(6, '0')}`
|
|
589
|
+
hugeTheme.spacing[`space_${i}`] = `${i}px`
|
|
590
|
+
hugeTheme.typography[`font_${i}`] = `${i}px`
|
|
591
|
+
hugeTheme.components[`comp_${i}`] = {
|
|
592
|
+
styles: { margin: `${i}px` },
|
|
593
|
+
variants: Array.from({ length: 10 }, (_, j) => `variant_${j}`)
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
store.setTheme(hugeTheme)
|
|
598
|
+
|
|
599
|
+
// Create massive color schemes
|
|
600
|
+
const hugeColorSchemes = {}
|
|
601
|
+
for (let i = 0; i < itemsPerSet; i++) {
|
|
602
|
+
const scheme = {}
|
|
603
|
+
for (let j = 0; j < 50; j++) {
|
|
604
|
+
scheme[`color_${j}`] = `#${(i * j).toString(16).padStart(6, '0')}`
|
|
605
|
+
}
|
|
606
|
+
hugeColorSchemes[`scheme_${set}_${i}`] = scheme
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
store.setAlternateColorsScheme(hugeColorSchemes)
|
|
610
|
+
|
|
611
|
+
// Verify data is accessible
|
|
612
|
+
expect(Object.keys(getThemeStore()?.colors || {})).toHaveLength(itemsPerSet)
|
|
613
|
+
expect(Object.keys(store.alternateColorsScheme)).toHaveLength(itemsPerSet)
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Final verification
|
|
617
|
+
expect(getThemeStore()).toBeDefined()
|
|
618
|
+
expect(Object.keys(store.alternateColorsScheme)).toHaveLength(itemsPerSet)
|
|
619
|
+
|
|
620
|
+
console.log(`Memory test: Handled ${hugeSets} sets of ${itemsPerSet} items each`)
|
|
621
|
+
})
|
|
622
|
+
})
|
|
623
|
+
|
|
624
|
+
describe('computed store performance under heavy load', () => {
|
|
625
|
+
it('should maintain reactivity with rapid updates', () => {
|
|
626
|
+
const updates = 3000
|
|
627
|
+
const startTime = performance.now()
|
|
628
|
+
const computedValues = []
|
|
629
|
+
|
|
630
|
+
for (let i = 0; i < updates; i++) {
|
|
631
|
+
themeStore.setTheme({
|
|
632
|
+
colors: { primary: `#${i.toString(16).padStart(6, '0')}` },
|
|
633
|
+
iteration: i
|
|
634
|
+
})
|
|
635
|
+
themeStore.setColorScheme(`scheme_${i % 100}`)
|
|
636
|
+
|
|
637
|
+
const computed = themeStoreComputed.get() as any
|
|
638
|
+
computedValues.push(computed)
|
|
639
|
+
|
|
640
|
+
// Verify computed values every 500 iterations
|
|
641
|
+
if (i % 500 === 0) {
|
|
642
|
+
expect(computed.theme?.iteration).toBe(i)
|
|
643
|
+
expect(computed.colorScheme).toBe(`scheme_${i % 100}`)
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
const endTime = performance.now()
|
|
648
|
+
const executionTime = endTime - startTime
|
|
649
|
+
|
|
650
|
+
expect(computedValues).toHaveLength(updates)
|
|
651
|
+
expect(executionTime).toBeLessThan(8000) // 8 seconds
|
|
652
|
+
|
|
653
|
+
// Verify final state
|
|
654
|
+
const finalComputed = themeStoreComputed.get() as any
|
|
655
|
+
expect(finalComputed.theme?.iteration).toBe(updates - 1)
|
|
656
|
+
expect(finalComputed.colorScheme).toBe(`scheme_${(updates - 1) % 100}`)
|
|
657
|
+
|
|
658
|
+
console.log(`Computed reactivity: ${updates} updates with computed reads in ${executionTime.toFixed(2)}ms`)
|
|
659
|
+
})
|
|
660
|
+
|
|
661
|
+
it('should handle multiple subscribers without performance degradation', () => {
|
|
662
|
+
const subscribers = []
|
|
663
|
+
const subscribeCount = 100
|
|
664
|
+
const updates = 1000
|
|
665
|
+
|
|
666
|
+
// Create multiple subscribers
|
|
667
|
+
for (let i = 0; i < subscribeCount; i++) {
|
|
668
|
+
const unsubscribe = themeStoreComputed.subscribe((value: any) => {
|
|
669
|
+
// Simulate some work
|
|
670
|
+
if (value.theme?.iteration && value.theme.iteration % 100 === 0) {
|
|
671
|
+
// Do something with the value
|
|
672
|
+
expect(value).toBeDefined()
|
|
673
|
+
}
|
|
674
|
+
})
|
|
675
|
+
subscribers.push(unsubscribe)
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
const startTime = performance.now()
|
|
679
|
+
|
|
680
|
+
// Make updates that should trigger all subscribers
|
|
681
|
+
for (let i = 0; i < updates; i++) {
|
|
682
|
+
themeStore.setTheme({
|
|
683
|
+
colors: { primary: `#${i.toString(16).padStart(6, '0')}` },
|
|
684
|
+
iteration: i
|
|
685
|
+
})
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
const endTime = performance.now()
|
|
689
|
+
const executionTime = endTime - startTime
|
|
690
|
+
|
|
691
|
+
// Cleanup subscribers
|
|
692
|
+
subscribers.forEach(unsubscribe => unsubscribe())
|
|
693
|
+
|
|
694
|
+
expect(executionTime).toBeLessThan(5000) // Should handle multiple subscribers efficiently
|
|
695
|
+
console.log(`Multiple subscribers: ${subscribeCount} subscribers with ${updates} updates in ${executionTime.toFixed(2)}ms`)
|
|
696
|
+
})
|
|
697
|
+
})
|
|
698
|
+
})
|