@qwickapps/react-framework 1.3.5 → 1.4.0

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.
Files changed (320) hide show
  1. package/README.md +1681 -2
  2. package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts +66 -0
  3. package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts.map +1 -0
  4. package/dist/components/ErrorBoundary.d.ts +7 -0
  5. package/dist/components/ErrorBoundary.d.ts.map +1 -1
  6. package/dist/components/Html.d.ts +28 -18
  7. package/dist/components/Html.d.ts.map +1 -1
  8. package/dist/components/Logo.d.ts +12 -35
  9. package/dist/components/Logo.d.ts.map +1 -1
  10. package/dist/components/Markdown.d.ts +18 -13
  11. package/dist/components/Markdown.d.ts.map +1 -1
  12. package/dist/components/QwickApp.d.ts +16 -3
  13. package/dist/components/QwickApp.d.ts.map +1 -1
  14. package/dist/components/QwickIcon.d.ts +23 -0
  15. package/dist/components/QwickIcon.d.ts.map +1 -0
  16. package/dist/components/SafeSpan.d.ts +12 -5
  17. package/dist/components/SafeSpan.d.ts.map +1 -1
  18. package/dist/components/Scaffold.d.ts.map +1 -1
  19. package/dist/components/base/ModelView.d.ts +101 -0
  20. package/dist/components/base/ModelView.d.ts.map +1 -0
  21. package/dist/components/base/index.d.ts +11 -0
  22. package/dist/components/base/index.d.ts.map +1 -0
  23. package/dist/components/blocks/Article.d.ts +12 -2
  24. package/dist/components/blocks/Article.d.ts.map +1 -1
  25. package/dist/components/blocks/Code.d.ts +13 -2
  26. package/dist/components/blocks/Code.d.ts.map +1 -1
  27. package/dist/components/blocks/CoverImageHeader.d.ts.map +1 -1
  28. package/dist/components/blocks/FeatureCard.d.ts.map +1 -1
  29. package/dist/components/blocks/FeatureGrid.d.ts.map +1 -1
  30. package/dist/components/blocks/Footer.d.ts.map +1 -1
  31. package/dist/components/blocks/HeroBlock.d.ts +27 -13
  32. package/dist/components/blocks/HeroBlock.d.ts.map +1 -1
  33. package/dist/components/blocks/Image.d.ts +41 -0
  34. package/dist/components/blocks/Image.d.ts.map +1 -0
  35. package/dist/components/blocks/PageBannerHeader.d.ts.map +1 -1
  36. package/dist/components/blocks/Section.d.ts +16 -2
  37. package/dist/components/blocks/Section.d.ts.map +1 -1
  38. package/dist/components/blocks/Text.d.ts +41 -0
  39. package/dist/components/blocks/Text.d.ts.map +1 -0
  40. package/dist/components/blocks/index.d.ts +4 -0
  41. package/dist/components/blocks/index.d.ts.map +1 -1
  42. package/dist/components/buttons/Button.d.ts +23 -7
  43. package/dist/components/buttons/Button.d.ts.map +1 -1
  44. package/dist/components/forms/FormBlock.d.ts +19 -13
  45. package/dist/components/forms/FormBlock.d.ts.map +1 -1
  46. package/dist/components/index.d.ts +4 -0
  47. package/dist/components/index.d.ts.map +1 -1
  48. package/dist/components/input/ChoiceInputField.d.ts +17 -11
  49. package/dist/components/input/ChoiceInputField.d.ts.map +1 -1
  50. package/dist/components/input/HtmlInputField.d.ts +17 -11
  51. package/dist/components/input/HtmlInputField.d.ts.map +1 -1
  52. package/dist/components/input/SelectInputField.d.ts +16 -10
  53. package/dist/components/input/SelectInputField.d.ts.map +1 -1
  54. package/dist/components/input/SwitchInputField.d.ts +16 -10
  55. package/dist/components/input/SwitchInputField.d.ts.map +1 -1
  56. package/dist/components/input/TextField.d.ts.map +1 -1
  57. package/dist/components/input/TextInputField.d.ts +16 -11
  58. package/dist/components/input/TextInputField.d.ts.map +1 -1
  59. package/dist/components/layout/GridCell.d.ts +23 -6
  60. package/dist/components/layout/GridCell.d.ts.map +1 -1
  61. package/dist/components/layout/GridLayout.d.ts +24 -23
  62. package/dist/components/layout/GridLayout.d.ts.map +1 -1
  63. package/dist/components/pages/FormPage.d.ts.map +1 -1
  64. package/dist/components/pages/Page.d.ts +49 -87
  65. package/dist/components/pages/Page.d.ts.map +1 -1
  66. package/dist/components/pages/index.d.ts +2 -2
  67. package/dist/components/pages/index.d.ts.map +1 -1
  68. package/dist/config/AppConfig.d.ts +49 -0
  69. package/dist/config/AppConfig.d.ts.map +1 -0
  70. package/dist/config/AppConfigBuilder.d.ts +75 -0
  71. package/dist/config/AppConfigBuilder.d.ts.map +1 -0
  72. package/dist/config/index.d.ts +13 -0
  73. package/dist/config/index.d.ts.map +1 -0
  74. package/dist/config/types.d.ts +130 -0
  75. package/dist/config/types.d.ts.map +1 -0
  76. package/dist/config.d.ts +15 -0
  77. package/dist/config.d.ts.map +1 -0
  78. package/dist/config.esm.js +451 -0
  79. package/dist/config.js +455 -0
  80. package/dist/contexts/PrintModeContext.d.ts +27 -0
  81. package/dist/contexts/PrintModeContext.d.ts.map +1 -0
  82. package/dist/contexts/QwickAppContext.d.ts +2 -2
  83. package/dist/contexts/QwickAppContext.d.ts.map +1 -1
  84. package/dist/contexts/index.d.ts +2 -0
  85. package/dist/contexts/index.d.ts.map +1 -1
  86. package/dist/hooks/index.d.ts +2 -0
  87. package/dist/hooks/index.d.ts.map +1 -1
  88. package/dist/hooks/usePrintMode.d.ts +39 -0
  89. package/dist/hooks/usePrintMode.d.ts.map +1 -0
  90. package/dist/index.css +1 -1
  91. package/dist/index.d.ts +1 -0
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.esm.css +1 -1
  94. package/dist/index.esm.js +10951 -6238
  95. package/dist/index.js +11014 -6287
  96. package/dist/schemas/CodeSchema.d.ts +2 -1
  97. package/dist/schemas/CodeSchema.d.ts.map +1 -1
  98. package/dist/schemas/CollapsibleLayoutSchema.d.ts +2 -1
  99. package/dist/schemas/CollapsibleLayoutSchema.d.ts.map +1 -1
  100. package/dist/schemas/ContentSchema.d.ts +2 -1
  101. package/dist/schemas/ContentSchema.d.ts.map +1 -1
  102. package/dist/schemas/GridCellSchema.d.ts +25 -0
  103. package/dist/schemas/GridCellSchema.d.ts.map +1 -0
  104. package/dist/schemas/GridLayoutSchema.d.ts +23 -0
  105. package/dist/schemas/GridLayoutSchema.d.ts.map +1 -0
  106. package/dist/schemas/HtmlSchema.d.ts +14 -0
  107. package/dist/schemas/HtmlSchema.d.ts.map +1 -0
  108. package/dist/schemas/ImageSchema.d.ts +32 -0
  109. package/dist/schemas/ImageSchema.d.ts.map +1 -0
  110. package/dist/schemas/LogoSchema.d.ts +35 -0
  111. package/dist/schemas/LogoSchema.d.ts.map +1 -0
  112. package/dist/schemas/MarkdownSchema.d.ts +14 -0
  113. package/dist/schemas/MarkdownSchema.d.ts.map +1 -0
  114. package/dist/schemas/PageTemplateSchema.d.ts +31 -0
  115. package/dist/schemas/PageTemplateSchema.d.ts.map +1 -0
  116. package/dist/schemas/PrintConfigSchema.d.ts +31 -0
  117. package/dist/schemas/PrintConfigSchema.d.ts.map +1 -0
  118. package/dist/schemas/SectionSchema.d.ts +2 -1
  119. package/dist/schemas/SectionSchema.d.ts.map +1 -1
  120. package/dist/schemas/TextSchema.d.ts +37 -0
  121. package/dist/schemas/TextSchema.d.ts.map +1 -0
  122. package/dist/schemas/ViewModelSchema.d.ts +23 -0
  123. package/dist/schemas/ViewModelSchema.d.ts.map +1 -0
  124. package/dist/schemas/index.d.ts +15 -1
  125. package/dist/schemas/index.d.ts.map +1 -1
  126. package/dist/schemas/transformers/ComponentTransformer.d.ts +116 -0
  127. package/dist/schemas/transformers/ComponentTransformer.d.ts.map +1 -0
  128. package/dist/schemas/transformers/ReactNodeTransformer.d.ts +53 -0
  129. package/dist/schemas/transformers/ReactNodeTransformer.d.ts.map +1 -0
  130. package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts +66 -0
  131. package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts.map +1 -0
  132. package/dist/schemas/transformers/registry.d.ts +15 -0
  133. package/dist/schemas/transformers/registry.d.ts.map +1 -0
  134. package/dist/schemas/types/Serializable.d.ts +46 -0
  135. package/dist/schemas/types/Serializable.d.ts.map +1 -0
  136. package/dist/utils/htmlTransform.d.ts.map +1 -1
  137. package/dist/utils/reactUtils.d.ts +12 -3
  138. package/dist/utils/reactUtils.d.ts.map +1 -1
  139. package/package.json +17 -3
  140. package/src/{components/__tests__ → __tests__/components}/AccessibilityProvider.test.tsx +1 -1
  141. package/src/{components/__tests__ → __tests__/components}/Article.test.tsx +1 -1
  142. package/src/{components/__tests__ → __tests__/components}/Breadcrumbs.test.tsx +1 -1
  143. package/src/{components/__tests__ → __tests__/components}/Button.test.tsx +1 -1
  144. package/src/{components/__tests__ → __tests__/components}/CardListGrid.test.tsx +2 -2
  145. package/src/{components/__tests__ → __tests__/components}/ChoiceInputField.test.tsx +1 -1
  146. package/src/{components/__tests__ → __tests__/components}/Code.test.tsx +1 -1
  147. package/src/{components/__tests__ → __tests__/components}/Content.integration.test.tsx +1 -1
  148. package/src/{components/__tests__ → __tests__/components}/Content.test.tsx +1 -1
  149. package/src/{components/__tests__ → __tests__/components}/CoverImageHeader.test.tsx +2 -2
  150. package/src/{components/__tests__ → __tests__/components}/ErrorBoundary.test.tsx +1 -1
  151. package/src/{components/__tests__ → __tests__/components}/FeatureCard.integration.test.tsx +2 -2
  152. package/src/{components/__tests__ → __tests__/components}/FeatureGrid.integration.test.tsx +2 -2
  153. package/src/{components/__tests__ → __tests__/components}/FeatureGrid.test.tsx +2 -2
  154. package/src/{components/__tests__ → __tests__/components}/Footer.test.tsx +4 -4
  155. package/src/{components/__tests__ → __tests__/components}/FormBlock.test.tsx +1 -1
  156. package/src/{components/__tests__ → __tests__/components}/HeroBlock.integration.test.tsx +2 -2
  157. package/src/{components/__tests__ → __tests__/components}/HeroBlock.test.tsx +233 -7
  158. package/src/{components/__tests__ → __tests__/components}/Html.test.tsx +11 -2
  159. package/src/{components/__tests__ → __tests__/components}/HtmlInputField.test.tsx +3 -3
  160. package/src/__tests__/components/Logo.test.js +3 -3
  161. package/src/{components/__tests__ → __tests__/components}/Markdown.test.tsx +1 -1
  162. package/src/{components/__tests__ → __tests__/components}/PageBannerHeader.test.tsx +3 -3
  163. package/src/{components/__tests__ → __tests__/components}/PaletteSwitcher.test.tsx +3 -3
  164. package/src/{components/__tests__ → __tests__/components}/ProductCard.test.tsx +4 -4
  165. package/src/{components/__tests__ → __tests__/components}/SafeSpan.integration.test.tsx +2 -2
  166. package/src/{components/__tests__ → __tests__/components}/SafeSpan.simple.test.tsx +1 -1
  167. package/src/{components/__tests__ → __tests__/components}/SafeSpan.test.tsx +1 -1
  168. package/src/{components/__tests__ → __tests__/components}/Section.integration.test.tsx +1 -1
  169. package/src/{components/__tests__ → __tests__/components}/Section.test.tsx +1 -1
  170. package/src/{components/__tests__ → __tests__/components}/SelectInputField.test.tsx +1 -1
  171. package/src/{components/__tests__ → __tests__/components}/TextInputField.test.tsx +3 -3
  172. package/src/{components/__tests__ → __tests__/components}/ThemeSwitcher.test.tsx +3 -3
  173. package/src/__tests__/components/base/ModelView.test.tsx +220 -0
  174. package/src/__tests__/components/blocks/Code.performance.test.tsx +625 -0
  175. package/src/__tests__/components/blocks/Code.serialization.test.tsx +507 -0
  176. package/src/__tests__/components/blocks/HeroBlock.serialization.test.tsx +414 -0
  177. package/src/__tests__/components/blocks/Image.serialization.test.tsx +257 -0
  178. package/src/__tests__/components/blocks/Section.serialization.test.tsx +553 -0
  179. package/src/__tests__/components/blocks/Text.performance.test.tsx +442 -0
  180. package/src/__tests__/components/blocks/Text.serialization.test.tsx +491 -0
  181. package/src/__tests__/components/buttons/Button.serialization.test.tsx +443 -0
  182. package/src/__tests__/components/input/FormComponents.serialization.test.tsx +482 -0
  183. package/src/__tests__/components/input/SelectInputField.serialization.test.tsx +439 -0
  184. package/src/__tests__/components/input/TextInputField.serialization.test.tsx +359 -0
  185. package/src/{components/layout/CollapsibleLayout/__tests__ → __tests__/components/layout}/CollapsibleLayout.test.tsx +4 -4
  186. package/src/__tests__/components/layout/GridCell.serialization.test.tsx +403 -0
  187. package/src/__tests__/components/layout/GridLayout.serialization.test.tsx +311 -0
  188. package/src/__tests__/hooks/usePrintMode.test.ts +89 -0
  189. package/src/__tests__/schemas/PageTemplateSchema.test.ts +161 -0
  190. package/src/__tests__/schemas/PrintConfigSchema.test.ts +127 -0
  191. package/src/__tests__/schemas/ViewModelSchema.test.ts +80 -0
  192. package/src/__tests__/schemas/transformers/ComponentSerializationPatterns.test.tsx +602 -0
  193. package/src/__tests__/schemas/transformers/ComponentTransformer.htmlPatterns.test.ts +301 -0
  194. package/src/__tests__/schemas/transformers/ComponentTransformer.test.ts +521 -0
  195. package/src/__tests__/schemas/transformers/CrossBrowserCompatibility.test.ts +586 -0
  196. package/src/__tests__/schemas/transformers/MockSerializableComponent.ts +103 -0
  197. package/src/__tests__/schemas/transformers/RealWorldScenarios.test.tsx +1165 -0
  198. package/src/__tests__/schemas/transformers/SerializationErrorHandling.test.ts +602 -0
  199. package/src/__tests__/schemas/transformers/SerializationIntegration.test.tsx +691 -0
  200. package/src/__tests__/schemas/transformers/SerializationPerformance.test.ts +460 -0
  201. package/src/__tests__/schemas/transformers/TestAutomation.test.ts +597 -0
  202. package/src/{utils/__tests__ → __tests__/utils}/nested-dom-fix.test.tsx +1 -1
  203. package/src/components/ErrorBoundary.tsx +8 -8
  204. package/src/components/Html.tsx +147 -44
  205. package/src/components/Logo.tsx +198 -100
  206. package/src/components/Markdown.tsx +125 -16
  207. package/src/components/QwickApp.tsx +64 -31
  208. package/src/components/QwickIcon.tsx +59 -0
  209. package/src/components/SafeSpan.tsx +65 -10
  210. package/src/components/Scaffold.tsx +2 -8
  211. package/src/components/base/ModelView.tsx +199 -0
  212. package/src/components/base/index.ts +11 -0
  213. package/src/components/blocks/Article.tsx +57 -18
  214. package/src/components/blocks/Code.md +529 -0
  215. package/src/components/blocks/Code.tsx +102 -15
  216. package/src/components/blocks/CoverImageHeader.tsx +9 -4
  217. package/src/components/blocks/FeatureCard.tsx +1 -2
  218. package/src/components/blocks/FeatureGrid.tsx +19 -1
  219. package/src/components/blocks/Footer.tsx +13 -1
  220. package/src/components/blocks/HeroBlock.tsx +87 -20
  221. package/src/components/blocks/Image.tsx +395 -0
  222. package/src/components/blocks/PageBannerHeader.tsx +14 -12
  223. package/src/components/blocks/ProductCard.tsx +1 -1
  224. package/src/components/blocks/Section.tsx +113 -8
  225. package/src/components/blocks/Text.tsx +285 -0
  226. package/src/components/blocks/index.ts +4 -0
  227. package/src/components/buttons/Button.tsx +184 -15
  228. package/src/components/forms/FormBlock.tsx +70 -17
  229. package/src/components/index.ts +5 -0
  230. package/src/components/input/ChoiceInputField.tsx +48 -18
  231. package/src/components/input/HtmlInputField.tsx +48 -18
  232. package/src/components/input/SelectInputField.tsx +48 -16
  233. package/src/components/input/SwitchInputField.tsx +48 -17
  234. package/src/components/input/TextField.tsx +41 -1
  235. package/src/components/input/TextInputField.tsx +52 -18
  236. package/src/components/layout/GridCell.tsx +118 -9
  237. package/src/components/layout/GridLayout.tsx +125 -24
  238. package/src/components/pages/FormPage.tsx +0 -1
  239. package/src/components/pages/Page.css +304 -332
  240. package/src/components/pages/Page.tsx +307 -255
  241. package/src/components/pages/index.ts +2 -2
  242. package/src/config/AppConfig.ts +133 -0
  243. package/src/config/AppConfigBuilder.ts +421 -0
  244. package/src/config/__tests__/AppConfig.test.ts +385 -0
  245. package/src/config/__tests__/AppConfigBuilder.test.ts +432 -0
  246. package/src/config/index.ts +24 -0
  247. package/src/config/types.ts +170 -0
  248. package/src/config.ts +25 -0
  249. package/src/contexts/PrintModeContext.tsx +332 -0
  250. package/src/contexts/QwickAppContext.tsx +2 -2
  251. package/src/contexts/index.ts +2 -0
  252. package/src/hooks/index.ts +5 -1
  253. package/src/hooks/usePrintMode.ts +73 -0
  254. package/src/index.ts +3 -0
  255. package/src/schemas/CodeSchema.ts +3 -3
  256. package/src/schemas/CollapsibleLayoutSchema.ts +2 -1
  257. package/src/schemas/ContentSchema.ts +2 -1
  258. package/src/schemas/GridCellSchema.ts +164 -0
  259. package/src/schemas/GridLayoutSchema.ts +133 -0
  260. package/src/schemas/HtmlSchema.ts +47 -0
  261. package/src/schemas/ImageSchema.ts +235 -0
  262. package/src/schemas/LogoSchema.ts +241 -0
  263. package/src/schemas/MarkdownSchema.ts +47 -0
  264. package/src/schemas/PageTemplateSchema.ts +186 -0
  265. package/src/schemas/PrintConfigSchema.ts +207 -0
  266. package/src/schemas/README.md +661 -0
  267. package/src/schemas/SectionSchema.ts +2 -1
  268. package/src/schemas/TextSchema.ts +329 -0
  269. package/src/schemas/ViewModelSchema.ts +115 -0
  270. package/src/schemas/index.ts +21 -2
  271. package/src/schemas/transformers/ComponentTransformer.ts +403 -0
  272. package/src/schemas/transformers/ReactNodeTransformer.ts +236 -0
  273. package/src/schemas/transformers/registry.ts +72 -0
  274. package/src/schemas/types/Serializable.ts +51 -0
  275. package/src/stories/AccessibilityProvider.stories.tsx +253 -253
  276. package/src/stories/Article.stories.tsx +433 -433
  277. package/src/stories/Button.stories.tsx +1 -1
  278. package/src/stories/CardListGrid.stories.tsx +451 -451
  279. package/src/stories/ChoiceInputField.stories.tsx +503 -503
  280. package/src/stories/Code.stories.tsx +1 -1
  281. package/src/stories/CollapsibleLayout.stories.tsx +1414 -1414
  282. package/src/stories/Content.stories.tsx +393 -393
  283. package/src/stories/CoverImageHeader.stories.tsx +701 -701
  284. package/src/stories/DataBinding.advanced.stories.tsx +432 -432
  285. package/src/stories/DataProvider.stories.tsx +1192 -1192
  286. package/src/stories/FeatureCard.stories.tsx +557 -557
  287. package/src/stories/FeatureGrid.stories.tsx +594 -594
  288. package/src/stories/Footer.stories.tsx +640 -640
  289. package/src/stories/FormBlock.stories.tsx +760 -760
  290. package/src/stories/FormComponents.stories.tsx +349 -541
  291. package/src/stories/GridCell.stories.tsx +417 -0
  292. package/src/stories/GridLayout.stories.tsx +353 -0
  293. package/src/stories/HeroBlock.stories.tsx +862 -373
  294. package/src/stories/HtmlInputField.stories.tsx +474 -474
  295. package/src/stories/Image.stories.tsx +819 -0
  296. package/src/stories/Introduction.stories.tsx +667 -667
  297. package/src/stories/LayoutBlocks.stories.tsx +324 -324
  298. package/src/stories/Logo.stories.tsx +165 -6
  299. package/src/stories/Markdown.stories.tsx +137 -137
  300. package/src/stories/ModelView.stories.tsx +477 -0
  301. package/src/stories/Page.stories.tsx +688 -688
  302. package/src/stories/PageBannerHeader.stories.tsx +864 -864
  303. package/src/stories/PaletteSwitcher.stories.tsx +119 -119
  304. package/src/stories/ProductCard.stories.tsx +424 -424
  305. package/src/stories/QwickApp.stories.tsx +368 -368
  306. package/src/stories/ResponsiveMenu.stories.tsx +249 -249
  307. package/src/stories/SafeSpan.stories.tsx +531 -531
  308. package/src/stories/Section.stories.tsx +90 -2
  309. package/src/stories/SelectInputField.stories.tsx +524 -524
  310. package/src/stories/Text.stories.tsx +560 -0
  311. package/src/stories/TextInputField.stories.tsx +443 -443
  312. package/src/stories/ThemeSwitcher.stories.tsx +123 -123
  313. package/src/utils/htmlTransform.tsx +74 -53
  314. package/src/utils/reactUtils.tsx +57 -6
  315. package/dist/index.bundled.css +0 -12
  316. /package/src/{hooks/__tests__ → __tests__/hooks}/useDataBinding.test.tsx.disabled +0 -0
  317. /package/src/{schemas/__tests__ → __tests__/schemas}/builders.test.ts +0 -0
  318. /package/src/{utils/__tests__ → __tests__/utils}/createDataDrivenComponent.test.tsx.disabled +0 -0
  319. /package/src/{utils/__tests__ → __tests__/utils}/htmlTransform.test.tsx +0 -0
  320. /package/src/{utils/__tests__ → __tests__/utils}/optional-logging.test.ts +0 -0
@@ -0,0 +1,460 @@
1
+ /**
2
+ * Component Serialization Performance Tests
3
+ *
4
+ * Performance benchmarking and validation for the serialization system
5
+ * covering memory usage, speed, and scalability under various loads.
6
+ *
7
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
8
+ */
9
+
10
+ import React, { ReactElement } from 'react';
11
+ import { ComponentTransformer } from '../ComponentTransformer';
12
+ import { Serializable, SerializableConstructor } from '../../types/Serializable';
13
+
14
+ // Performance-focused mock components
15
+ class PerfMockButton implements Serializable {
16
+ static readonly tagName = 'Button';
17
+ static readonly version = '1.0.0';
18
+
19
+ constructor(public props: { id?: string; label?: string; metadata?: any }) {}
20
+
21
+ static fromJson(jsonData: any): ReactElement {
22
+ return React.createElement('button', {
23
+ id: jsonData.id,
24
+ 'data-label': jsonData.label,
25
+ 'data-metadata': JSON.stringify(jsonData.metadata || {})
26
+ }, jsonData.label || 'Button');
27
+ }
28
+
29
+ toJson(): any {
30
+ return {
31
+ id: this.props.id,
32
+ label: this.props.label,
33
+ metadata: this.props.metadata
34
+ };
35
+ }
36
+ }
37
+
38
+ class PerfMockSection implements Serializable {
39
+ static readonly tagName = 'Section';
40
+ static readonly version = '1.0.0';
41
+
42
+ constructor(public props: { id?: string; children?: any }) {}
43
+
44
+ static fromJson(jsonData: any): ReactElement {
45
+ const children = jsonData.children ? ComponentTransformer.deserialize(jsonData.children) : null;
46
+ return React.createElement('section', {
47
+ id: jsonData.id,
48
+ 'data-testid': 'perf-section'
49
+ }, children);
50
+ }
51
+
52
+ toJson(): any {
53
+ return {
54
+ id: this.props.id,
55
+ children: this.props.children ? ComponentTransformer.serialize(this.props.children) : null
56
+ };
57
+ }
58
+ }
59
+
60
+ // Performance measurement utilities
61
+ interface PerformanceMetrics {
62
+ duration: number;
63
+ memoryUsed?: number;
64
+ operations: number;
65
+ opsPerSecond: number;
66
+ }
67
+
68
+ function measurePerformance<T>(
69
+ operation: () => T,
70
+ operationCount: number = 1
71
+ ): { result: T; metrics: PerformanceMetrics } {
72
+ // Force garbage collection if available (for more accurate memory measurements)
73
+ if ((global as any).gc) {
74
+ (global as any).gc();
75
+ }
76
+
77
+ const startMemory = process.memoryUsage().heapUsed;
78
+ const startTime = performance.now();
79
+
80
+ let result: T;
81
+ for (let i = 0; i < operationCount; i++) {
82
+ result = operation();
83
+ }
84
+
85
+ const endTime = performance.now();
86
+ const endMemory = process.memoryUsage().heapUsed;
87
+
88
+ const duration = endTime - startTime;
89
+ const memoryUsed = endMemory - startMemory;
90
+ const opsPerSecond = operationCount > 1 ? (operationCount / duration) * 1000 : 1000 / duration;
91
+
92
+ return {
93
+ result: result!,
94
+ metrics: {
95
+ duration,
96
+ memoryUsed,
97
+ operations: operationCount,
98
+ opsPerSecond
99
+ }
100
+ };
101
+ }
102
+
103
+ describe('Component Serialization Performance Tests', () => {
104
+ beforeEach(() => {
105
+ ComponentTransformer.clearRegistry();
106
+ ComponentTransformer.registerComponent(PerfMockButton as SerializableConstructor);
107
+ ComponentTransformer.registerComponent(PerfMockSection as SerializableConstructor);
108
+ });
109
+
110
+ afterEach(() => {
111
+ ComponentTransformer.clearRegistry();
112
+ });
113
+
114
+ describe('Serialization Speed Benchmarks', () => {
115
+ it('should serialize 1000 simple components within performance budget', () => {
116
+ const components = Array.from({ length: 1000 }, (_, i) => ({
117
+ tag: 'Button',
118
+ version: '1.0.0',
119
+ data: {
120
+ id: `btn-${i}`,
121
+ label: `Button ${i}`,
122
+ metadata: { index: i, category: i % 10 }
123
+ }
124
+ }));
125
+
126
+ const { metrics } = measurePerformance(() => {
127
+ return ComponentTransformer.deserialize(components);
128
+ });
129
+
130
+ // Performance budget: should complete within 50ms for 1000 components
131
+ expect(metrics.duration).toBeLessThan(50);
132
+ expect(metrics.opsPerSecond).toBeGreaterThan(20000); // At least 20k ops/sec
133
+
134
+ console.log(`Serialized 1000 components in ${metrics.duration.toFixed(2)}ms (${metrics.opsPerSecond.toFixed(0)} ops/sec)`);
135
+ });
136
+
137
+ it('should deserialize complex nested structures efficiently', () => {
138
+ // Create nested structure with 10 sections, each containing 50 buttons
139
+ const nestedStructure = Array.from({ length: 10 }, (_, sectionIndex) => ({
140
+ tag: 'Section',
141
+ version: '1.0.0',
142
+ data: {
143
+ id: `section-${sectionIndex}`,
144
+ children: Array.from({ length: 50 }, (_, buttonIndex) => ({
145
+ tag: 'Button',
146
+ version: '1.0.0',
147
+ data: {
148
+ id: `btn-${sectionIndex}-${buttonIndex}`,
149
+ label: `Button ${buttonIndex}`,
150
+ metadata: { section: sectionIndex, button: buttonIndex }
151
+ }
152
+ }))
153
+ }
154
+ }));
155
+
156
+ const { result, metrics } = measurePerformance(() => {
157
+ return ComponentTransformer.deserialize(nestedStructure);
158
+ });
159
+
160
+ // Performance budget: 500 nested components should complete within 100ms
161
+ expect(metrics.duration).toBeLessThan(100);
162
+ expect(Array.isArray(result)).toBe(true);
163
+ expect(result).toHaveLength(10);
164
+
165
+ console.log(`Deserialized 500 nested components in ${metrics.duration.toFixed(2)}ms`);
166
+ });
167
+
168
+ it('should handle roundtrip serialization efficiently', () => {
169
+ const testData = Array.from({ length: 100 }, (_, i) => ({
170
+ tag: 'Section',
171
+ version: '1.0.0',
172
+ data: {
173
+ id: `section-${i}`,
174
+ children: [{
175
+ tag: 'Button',
176
+ version: '1.0.0',
177
+ data: { id: `btn-${i}`, label: `Button ${i}` }
178
+ }]
179
+ }
180
+ }));
181
+
182
+ const { metrics: deserializeMetrics } = measurePerformance(() => {
183
+ return ComponentTransformer.deserialize(testData);
184
+ });
185
+
186
+ const reactElements = ComponentTransformer.deserialize(testData);
187
+
188
+ const { metrics: serializeMetrics } = measurePerformance(() => {
189
+ return ComponentTransformer.serialize(reactElements);
190
+ });
191
+
192
+ // Both operations should be fast
193
+ expect(deserializeMetrics.duration).toBeLessThan(20);
194
+ expect(serializeMetrics.duration).toBeLessThan(20);
195
+
196
+ console.log(`Roundtrip: Deserialize ${deserializeMetrics.duration.toFixed(2)}ms, Serialize ${serializeMetrics.duration.toFixed(2)}ms`);
197
+ });
198
+ });
199
+
200
+ describe('Memory Usage Validation', () => {
201
+ it('should not create excessive memory overhead for large component trees', () => {
202
+ const largeComponentTree = Array.from({ length: 5000 }, (_, i) => ({
203
+ tag: 'Button',
204
+ version: '1.0.0',
205
+ data: {
206
+ id: `large-btn-${i}`,
207
+ label: `Large Button ${i}`,
208
+ metadata: {
209
+ index: i,
210
+ timestamp: Date.now(),
211
+ category: `category-${i % 20}`,
212
+ tags: [`tag-${i % 10}`, `tag-${(i + 1) % 10}`]
213
+ }
214
+ }
215
+ }));
216
+
217
+ const { result, metrics } = measurePerformance(() => {
218
+ return ComponentTransformer.deserialize(largeComponentTree);
219
+ });
220
+
221
+ expect(Array.isArray(result)).toBe(true);
222
+ expect(result).toHaveLength(5000);
223
+
224
+ // Memory budget: Should not use more than 50MB for 5000 components
225
+ if (metrics.memoryUsed) {
226
+ const memoryMB = metrics.memoryUsed / (1024 * 1024);
227
+ expect(memoryMB).toBeLessThan(50);
228
+ console.log(`Memory used for 5000 components: ${memoryMB.toFixed(2)}MB`);
229
+ }
230
+ });
231
+
232
+ it('should release memory properly after deserialization', async () => {
233
+ const initialMemory = process.memoryUsage().heapUsed;
234
+
235
+ // Create and process large data
236
+ for (let batch = 0; batch < 10; batch++) {
237
+ const batchData = Array.from({ length: 1000 }, (_, i) => ({
238
+ tag: 'Button',
239
+ version: '1.0.0',
240
+ data: { id: `batch-${batch}-btn-${i}`, label: `Button ${i}` }
241
+ }));
242
+
243
+ const result = ComponentTransformer.deserialize(batchData);
244
+ expect(Array.isArray(result)).toBe(true);
245
+ }
246
+
247
+ // Force garbage collection
248
+ if ((global as any).gc) {
249
+ (global as any).gc();
250
+ await new Promise(resolve => setTimeout(resolve, 100));
251
+ }
252
+
253
+ const finalMemory = process.memoryUsage().heapUsed;
254
+ const memoryGrowth = (finalMemory - initialMemory) / (1024 * 1024);
255
+
256
+ // Memory should not grow by more than 20MB after processing 10k components
257
+ expect(memoryGrowth).toBeLessThan(20);
258
+ console.log(`Memory growth after 10 batches: ${memoryGrowth.toFixed(2)}MB`);
259
+ });
260
+ });
261
+
262
+ describe('Scalability Testing', () => {
263
+ it('should scale linearly with component count', () => {
264
+ const componentCounts = [100, 500, 1000, 2000];
265
+ const results: { count: number; duration: number; opsPerSec: number }[] = [];
266
+
267
+ for (const count of componentCounts) {
268
+ const components = Array.from({ length: count }, (_, i) => ({
269
+ tag: 'Button',
270
+ version: '1.0.0',
271
+ data: { id: `scale-btn-${i}`, label: `Button ${i}` }
272
+ }));
273
+
274
+ const { metrics } = measurePerformance(() => {
275
+ return ComponentTransformer.deserialize(components);
276
+ });
277
+
278
+ results.push({
279
+ count,
280
+ duration: metrics.duration,
281
+ opsPerSec: metrics.opsPerSecond
282
+ });
283
+ }
284
+
285
+ // Verify scaling characteristics
286
+ for (let i = 1; i < results.length; i++) {
287
+ const prev = results[i - 1];
288
+ const curr = results[i];
289
+
290
+ // Duration should scale roughly linearly (with some tolerance)
291
+ const expectedDuration = (prev.duration * curr.count) / prev.count;
292
+ const tolerance = expectedDuration * 0.5; // 50% tolerance
293
+
294
+ expect(curr.duration).toBeLessThan(expectedDuration + tolerance);
295
+
296
+ console.log(`${curr.count} components: ${curr.duration.toFixed(2)}ms (${curr.opsPerSec.toFixed(0)} ops/sec)`);
297
+ }
298
+ });
299
+
300
+ it('should handle deeply nested structures without performance degradation', () => {
301
+ const depths = [5, 10, 20, 30];
302
+ const results: { depth: number; duration: number }[] = [];
303
+
304
+ for (const depth of depths) {
305
+ // Create nested structure
306
+ let nestedData: any = {
307
+ tag: 'Button',
308
+ version: '1.0.0',
309
+ data: { id: 'deep-button', label: `Button at depth ${depth}` }
310
+ };
311
+
312
+ for (let level = 0; level < depth; level++) {
313
+ nestedData = {
314
+ tag: 'Section',
315
+ version: '1.0.0',
316
+ data: {
317
+ id: `section-level-${level}`,
318
+ children: [nestedData]
319
+ }
320
+ };
321
+ }
322
+
323
+ const { metrics } = measurePerformance(() => {
324
+ return ComponentTransformer.deserialize(nestedData);
325
+ });
326
+
327
+ results.push({
328
+ depth,
329
+ duration: metrics.duration
330
+ });
331
+ }
332
+
333
+ // Verify that performance doesn't degrade exponentially with depth
334
+ for (let i = 1; i < results.length; i++) {
335
+ const prev = results[i - 1];
336
+ const curr = results[i];
337
+
338
+ // Each doubling of depth should not more than double the time
339
+ const depthRatio = curr.depth / prev.depth;
340
+ const timeRatio = curr.duration / prev.duration;
341
+
342
+ expect(timeRatio).toBeLessThan(depthRatio * 2);
343
+
344
+ console.log(`Depth ${curr.depth}: ${curr.duration.toFixed(2)}ms`);
345
+ }
346
+ });
347
+ });
348
+
349
+ describe('Stress Testing', () => {
350
+ it('should handle extreme component counts without crashing', () => {
351
+ // Test with 10,000 components
352
+ const extremeCount = 10000;
353
+ const components = Array.from({ length: extremeCount }, (_, i) => ({
354
+ tag: 'Button',
355
+ version: '1.0.0',
356
+ data: {
357
+ id: `extreme-btn-${i}`,
358
+ label: `Button ${i}`,
359
+ metadata: { batch: Math.floor(i / 1000) }
360
+ }
361
+ }));
362
+
363
+ expect(() => {
364
+ const startTime = performance.now();
365
+ const result = ComponentTransformer.deserialize(components);
366
+ const endTime = performance.now();
367
+
368
+ expect(Array.isArray(result)).toBe(true);
369
+ expect(result).toHaveLength(extremeCount);
370
+
371
+ const duration = endTime - startTime;
372
+ console.log(`Processed ${extremeCount} components in ${duration.toFixed(2)}ms`);
373
+
374
+ // Should complete within 1 second even for extreme loads
375
+ expect(duration).toBeLessThan(1000);
376
+ }).not.toThrow();
377
+ });
378
+
379
+ it('should handle concurrent serialization operations', async () => {
380
+ const concurrentOperations = 10;
381
+ const componentsPerOperation = 500;
382
+
383
+ const operations = Array.from({ length: concurrentOperations }, (_, opIndex) => {
384
+ const components = Array.from({ length: componentsPerOperation }, (_, compIndex) => ({
385
+ tag: 'Button',
386
+ version: '1.0.0',
387
+ data: {
388
+ id: `concurrent-op${opIndex}-btn${compIndex}`,
389
+ label: `Op ${opIndex} Button ${compIndex}`
390
+ }
391
+ }));
392
+
393
+ return () => ComponentTransformer.deserialize(components);
394
+ });
395
+
396
+ const startTime = performance.now();
397
+
398
+ // Run all operations concurrently
399
+ const results = await Promise.all(
400
+ operations.map(async (operation) => {
401
+ return new Promise((resolve) => {
402
+ setTimeout(() => resolve(operation()), 0);
403
+ });
404
+ })
405
+ );
406
+
407
+ const endTime = performance.now();
408
+ const totalDuration = endTime - startTime;
409
+
410
+ // Verify all operations completed successfully
411
+ results.forEach((result, index) => {
412
+ expect(Array.isArray(result)).toBe(true);
413
+ expect((result as any[]).length).toBe(componentsPerOperation);
414
+ });
415
+
416
+ console.log(`${concurrentOperations} concurrent operations completed in ${totalDuration.toFixed(2)}ms`);
417
+ });
418
+ });
419
+
420
+ describe('Performance Regression Detection', () => {
421
+ it('should maintain consistent performance characteristics', () => {
422
+ const benchmarkData = Array.from({ length: 1000 }, (_, i) => ({
423
+ tag: 'Section',
424
+ version: '1.0.0',
425
+ data: {
426
+ id: `benchmark-section-${i}`,
427
+ children: [
428
+ {
429
+ tag: 'Button',
430
+ version: '1.0.0',
431
+ data: { id: `benchmark-btn-${i}`, label: `Button ${i}` }
432
+ }
433
+ ]
434
+ }
435
+ }));
436
+
437
+ // Run benchmark multiple times to get consistent results
438
+ const runs = 5;
439
+ const durations: number[] = [];
440
+
441
+ for (let run = 0; run < runs; run++) {
442
+ const { metrics } = measurePerformance(() => {
443
+ return ComponentTransformer.deserialize(benchmarkData);
444
+ });
445
+ durations.push(metrics.duration);
446
+ }
447
+
448
+ const averageDuration = durations.reduce((a, b) => a + b, 0) / durations.length;
449
+ const maxDuration = Math.max(...durations);
450
+ const minDuration = Math.min(...durations);
451
+ const variance = maxDuration - minDuration;
452
+
453
+ // Performance should be consistent (low variance)
454
+ expect(variance).toBeLessThan(averageDuration * 0.5); // Variance should be < 50% of average
455
+ expect(averageDuration).toBeLessThan(50); // Average should be under 50ms for 1000 components
456
+
457
+ console.log(`Performance consistency: avg=${averageDuration.toFixed(2)}ms, min=${minDuration.toFixed(2)}ms, max=${maxDuration.toFixed(2)}ms, variance=${variance.toFixed(2)}ms`);
458
+ });
459
+ });
460
+ });