@qwickapps/react-framework 1.3.4 → 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 (325) hide show
  1. package/README.md +1688 -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/Content.d.ts.map +1 -1
  28. package/dist/components/blocks/CoverImageHeader.d.ts.map +1 -1
  29. package/dist/components/blocks/FeatureCard.d.ts.map +1 -1
  30. package/dist/components/blocks/FeatureGrid.d.ts.map +1 -1
  31. package/dist/components/blocks/Footer.d.ts.map +1 -1
  32. package/dist/components/blocks/HeroBlock.d.ts +27 -13
  33. package/dist/components/blocks/HeroBlock.d.ts.map +1 -1
  34. package/dist/components/blocks/Image.d.ts +41 -0
  35. package/dist/components/blocks/Image.d.ts.map +1 -0
  36. package/dist/components/blocks/PageBannerHeader.d.ts.map +1 -1
  37. package/dist/components/blocks/ProductCard.d.ts.map +1 -1
  38. package/dist/components/blocks/Section.d.ts +16 -2
  39. package/dist/components/blocks/Section.d.ts.map +1 -1
  40. package/dist/components/blocks/Text.d.ts +41 -0
  41. package/dist/components/blocks/Text.d.ts.map +1 -0
  42. package/dist/components/blocks/index.d.ts +4 -0
  43. package/dist/components/blocks/index.d.ts.map +1 -1
  44. package/dist/components/buttons/Button.d.ts +23 -7
  45. package/dist/components/buttons/Button.d.ts.map +1 -1
  46. package/dist/components/forms/FormBlock.d.ts +19 -13
  47. package/dist/components/forms/FormBlock.d.ts.map +1 -1
  48. package/dist/components/index.d.ts +4 -0
  49. package/dist/components/index.d.ts.map +1 -1
  50. package/dist/components/input/ChoiceInputField.d.ts +17 -11
  51. package/dist/components/input/ChoiceInputField.d.ts.map +1 -1
  52. package/dist/components/input/HtmlInputField.d.ts +17 -11
  53. package/dist/components/input/HtmlInputField.d.ts.map +1 -1
  54. package/dist/components/input/SelectInputField.d.ts +16 -10
  55. package/dist/components/input/SelectInputField.d.ts.map +1 -1
  56. package/dist/components/input/SwitchInputField.d.ts +16 -10
  57. package/dist/components/input/SwitchInputField.d.ts.map +1 -1
  58. package/dist/components/input/TextField.d.ts.map +1 -1
  59. package/dist/components/input/TextInputField.d.ts +16 -11
  60. package/dist/components/input/TextInputField.d.ts.map +1 -1
  61. package/dist/components/layout/GridCell.d.ts +23 -6
  62. package/dist/components/layout/GridCell.d.ts.map +1 -1
  63. package/dist/components/layout/GridLayout.d.ts +24 -23
  64. package/dist/components/layout/GridLayout.d.ts.map +1 -1
  65. package/dist/components/pages/FormPage.d.ts.map +1 -1
  66. package/dist/components/pages/Page.d.ts +49 -87
  67. package/dist/components/pages/Page.d.ts.map +1 -1
  68. package/dist/components/pages/index.d.ts +2 -2
  69. package/dist/components/pages/index.d.ts.map +1 -1
  70. package/dist/config/AppConfig.d.ts +49 -0
  71. package/dist/config/AppConfig.d.ts.map +1 -0
  72. package/dist/config/AppConfigBuilder.d.ts +75 -0
  73. package/dist/config/AppConfigBuilder.d.ts.map +1 -0
  74. package/dist/config/index.d.ts +13 -0
  75. package/dist/config/index.d.ts.map +1 -0
  76. package/dist/config/types.d.ts +130 -0
  77. package/dist/config/types.d.ts.map +1 -0
  78. package/dist/config.d.ts +15 -0
  79. package/dist/config.d.ts.map +1 -0
  80. package/dist/config.esm.js +451 -0
  81. package/dist/config.js +455 -0
  82. package/dist/contexts/PrintModeContext.d.ts +27 -0
  83. package/dist/contexts/PrintModeContext.d.ts.map +1 -0
  84. package/dist/contexts/QwickAppContext.d.ts +2 -2
  85. package/dist/contexts/QwickAppContext.d.ts.map +1 -1
  86. package/dist/contexts/ThemeContext.d.ts.map +1 -1
  87. package/dist/contexts/index.d.ts +2 -0
  88. package/dist/contexts/index.d.ts.map +1 -1
  89. package/dist/hooks/index.d.ts +2 -0
  90. package/dist/hooks/index.d.ts.map +1 -1
  91. package/dist/hooks/usePrintMode.d.ts +39 -0
  92. package/dist/hooks/usePrintMode.d.ts.map +1 -0
  93. package/dist/index.css +1 -1
  94. package/dist/index.d.ts +1 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.esm.css +1 -1
  97. package/dist/index.esm.js +20722 -16021
  98. package/dist/index.js +20725 -16010
  99. package/dist/schemas/CodeSchema.d.ts +2 -1
  100. package/dist/schemas/CodeSchema.d.ts.map +1 -1
  101. package/dist/schemas/CollapsibleLayoutSchema.d.ts +2 -1
  102. package/dist/schemas/CollapsibleLayoutSchema.d.ts.map +1 -1
  103. package/dist/schemas/ContentSchema.d.ts +2 -1
  104. package/dist/schemas/ContentSchema.d.ts.map +1 -1
  105. package/dist/schemas/GridCellSchema.d.ts +25 -0
  106. package/dist/schemas/GridCellSchema.d.ts.map +1 -0
  107. package/dist/schemas/GridLayoutSchema.d.ts +23 -0
  108. package/dist/schemas/GridLayoutSchema.d.ts.map +1 -0
  109. package/dist/schemas/HtmlSchema.d.ts +14 -0
  110. package/dist/schemas/HtmlSchema.d.ts.map +1 -0
  111. package/dist/schemas/ImageSchema.d.ts +32 -0
  112. package/dist/schemas/ImageSchema.d.ts.map +1 -0
  113. package/dist/schemas/LogoSchema.d.ts +35 -0
  114. package/dist/schemas/LogoSchema.d.ts.map +1 -0
  115. package/dist/schemas/MarkdownSchema.d.ts +14 -0
  116. package/dist/schemas/MarkdownSchema.d.ts.map +1 -0
  117. package/dist/schemas/PageTemplateSchema.d.ts +31 -0
  118. package/dist/schemas/PageTemplateSchema.d.ts.map +1 -0
  119. package/dist/schemas/PrintConfigSchema.d.ts +31 -0
  120. package/dist/schemas/PrintConfigSchema.d.ts.map +1 -0
  121. package/dist/schemas/SectionSchema.d.ts +2 -1
  122. package/dist/schemas/SectionSchema.d.ts.map +1 -1
  123. package/dist/schemas/TextSchema.d.ts +37 -0
  124. package/dist/schemas/TextSchema.d.ts.map +1 -0
  125. package/dist/schemas/ViewModelSchema.d.ts +23 -0
  126. package/dist/schemas/ViewModelSchema.d.ts.map +1 -0
  127. package/dist/schemas/index.d.ts +15 -1
  128. package/dist/schemas/index.d.ts.map +1 -1
  129. package/dist/schemas/transformers/ComponentTransformer.d.ts +116 -0
  130. package/dist/schemas/transformers/ComponentTransformer.d.ts.map +1 -0
  131. package/dist/schemas/transformers/ReactNodeTransformer.d.ts +53 -0
  132. package/dist/schemas/transformers/ReactNodeTransformer.d.ts.map +1 -0
  133. package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts +66 -0
  134. package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts.map +1 -0
  135. package/dist/schemas/transformers/registry.d.ts +15 -0
  136. package/dist/schemas/transformers/registry.d.ts.map +1 -0
  137. package/dist/schemas/types/Serializable.d.ts +46 -0
  138. package/dist/schemas/types/Serializable.d.ts.map +1 -0
  139. package/dist/utils/htmlTransform.d.ts.map +1 -1
  140. package/dist/utils/reactUtils.d.ts +12 -3
  141. package/dist/utils/reactUtils.d.ts.map +1 -1
  142. package/package.json +17 -3
  143. package/src/{components/__tests__ → __tests__/components}/AccessibilityProvider.test.tsx +1 -1
  144. package/src/{components/__tests__ → __tests__/components}/Article.test.tsx +1 -1
  145. package/src/{components/__tests__ → __tests__/components}/Breadcrumbs.test.tsx +1 -1
  146. package/src/{components/__tests__ → __tests__/components}/Button.test.tsx +1 -1
  147. package/src/{components/__tests__ → __tests__/components}/CardListGrid.test.tsx +2 -2
  148. package/src/{components/__tests__ → __tests__/components}/ChoiceInputField.test.tsx +1 -1
  149. package/src/{components/__tests__ → __tests__/components}/Code.test.tsx +1 -1
  150. package/src/{components/__tests__ → __tests__/components}/Content.integration.test.tsx +1 -1
  151. package/src/{components/__tests__ → __tests__/components}/Content.test.tsx +1 -1
  152. package/src/{components/__tests__ → __tests__/components}/CoverImageHeader.test.tsx +2 -2
  153. package/src/{components/__tests__ → __tests__/components}/ErrorBoundary.test.tsx +1 -1
  154. package/src/{components/__tests__ → __tests__/components}/FeatureCard.integration.test.tsx +2 -2
  155. package/src/{components/__tests__ → __tests__/components}/FeatureGrid.integration.test.tsx +2 -2
  156. package/src/{components/__tests__ → __tests__/components}/FeatureGrid.test.tsx +2 -2
  157. package/src/{components/__tests__ → __tests__/components}/Footer.test.tsx +4 -4
  158. package/src/{components/__tests__ → __tests__/components}/FormBlock.test.tsx +1 -1
  159. package/src/{components/__tests__ → __tests__/components}/HeroBlock.integration.test.tsx +2 -2
  160. package/src/{components/__tests__ → __tests__/components}/HeroBlock.test.tsx +233 -7
  161. package/src/{components/__tests__ → __tests__/components}/Html.test.tsx +11 -2
  162. package/src/{components/__tests__ → __tests__/components}/HtmlInputField.test.tsx +3 -3
  163. package/src/__tests__/components/Logo.test.js +3 -3
  164. package/src/{components/__tests__ → __tests__/components}/Markdown.test.tsx +1 -1
  165. package/src/{components/__tests__ → __tests__/components}/PageBannerHeader.test.tsx +3 -3
  166. package/src/{components/__tests__ → __tests__/components}/PaletteSwitcher.test.tsx +3 -3
  167. package/src/{components/__tests__ → __tests__/components}/ProductCard.test.tsx +4 -4
  168. package/src/{components/__tests__ → __tests__/components}/SafeSpan.integration.test.tsx +2 -2
  169. package/src/{components/__tests__ → __tests__/components}/SafeSpan.simple.test.tsx +1 -1
  170. package/src/{components/__tests__ → __tests__/components}/SafeSpan.test.tsx +1 -1
  171. package/src/{components/__tests__ → __tests__/components}/Section.integration.test.tsx +1 -1
  172. package/src/{components/__tests__ → __tests__/components}/Section.test.tsx +1 -1
  173. package/src/{components/__tests__ → __tests__/components}/SelectInputField.test.tsx +1 -1
  174. package/src/{components/__tests__ → __tests__/components}/TextInputField.test.tsx +3 -3
  175. package/src/{components/__tests__ → __tests__/components}/ThemeSwitcher.test.tsx +3 -3
  176. package/src/__tests__/components/base/ModelView.test.tsx +220 -0
  177. package/src/__tests__/components/blocks/Code.performance.test.tsx +625 -0
  178. package/src/__tests__/components/blocks/Code.serialization.test.tsx +507 -0
  179. package/src/__tests__/components/blocks/HeroBlock.serialization.test.tsx +414 -0
  180. package/src/__tests__/components/blocks/Image.serialization.test.tsx +257 -0
  181. package/src/__tests__/components/blocks/Section.serialization.test.tsx +553 -0
  182. package/src/__tests__/components/blocks/Text.performance.test.tsx +442 -0
  183. package/src/__tests__/components/blocks/Text.serialization.test.tsx +491 -0
  184. package/src/__tests__/components/buttons/Button.serialization.test.tsx +443 -0
  185. package/src/__tests__/components/input/FormComponents.serialization.test.tsx +482 -0
  186. package/src/__tests__/components/input/SelectInputField.serialization.test.tsx +439 -0
  187. package/src/__tests__/components/input/TextInputField.serialization.test.tsx +359 -0
  188. package/src/{components/layout/CollapsibleLayout/__tests__ → __tests__/components/layout}/CollapsibleLayout.test.tsx +4 -4
  189. package/src/__tests__/components/layout/GridCell.serialization.test.tsx +403 -0
  190. package/src/__tests__/components/layout/GridLayout.serialization.test.tsx +311 -0
  191. package/src/__tests__/hooks/usePrintMode.test.ts +89 -0
  192. package/src/__tests__/schemas/PageTemplateSchema.test.ts +161 -0
  193. package/src/__tests__/schemas/PrintConfigSchema.test.ts +127 -0
  194. package/src/__tests__/schemas/ViewModelSchema.test.ts +80 -0
  195. package/src/__tests__/schemas/transformers/ComponentSerializationPatterns.test.tsx +602 -0
  196. package/src/__tests__/schemas/transformers/ComponentTransformer.htmlPatterns.test.ts +301 -0
  197. package/src/__tests__/schemas/transformers/ComponentTransformer.test.ts +521 -0
  198. package/src/__tests__/schemas/transformers/CrossBrowserCompatibility.test.ts +586 -0
  199. package/src/__tests__/schemas/transformers/MockSerializableComponent.ts +103 -0
  200. package/src/__tests__/schemas/transformers/RealWorldScenarios.test.tsx +1165 -0
  201. package/src/__tests__/schemas/transformers/SerializationErrorHandling.test.ts +602 -0
  202. package/src/__tests__/schemas/transformers/SerializationIntegration.test.tsx +691 -0
  203. package/src/__tests__/schemas/transformers/SerializationPerformance.test.ts +460 -0
  204. package/src/__tests__/schemas/transformers/TestAutomation.test.ts +597 -0
  205. package/src/{utils/__tests__ → __tests__/utils}/nested-dom-fix.test.tsx +1 -1
  206. package/src/components/ErrorBoundary.tsx +8 -8
  207. package/src/components/Html.tsx +147 -44
  208. package/src/components/Logo.tsx +198 -100
  209. package/src/components/Markdown.tsx +125 -16
  210. package/src/components/QwickApp.tsx +64 -31
  211. package/src/components/QwickIcon.tsx +59 -0
  212. package/src/components/SafeSpan.tsx +65 -10
  213. package/src/components/Scaffold.tsx +2 -8
  214. package/src/components/base/ModelView.tsx +199 -0
  215. package/src/components/base/index.ts +11 -0
  216. package/src/components/blocks/Article.tsx +57 -18
  217. package/src/components/blocks/Code.md +529 -0
  218. package/src/components/blocks/Code.tsx +102 -15
  219. package/src/components/blocks/Content.tsx +25 -77
  220. package/src/components/blocks/CoverImageHeader.tsx +9 -4
  221. package/src/components/blocks/FeatureCard.tsx +1 -2
  222. package/src/components/blocks/FeatureGrid.tsx +19 -1
  223. package/src/components/blocks/Footer.tsx +13 -1
  224. package/src/components/blocks/HeroBlock.tsx +87 -20
  225. package/src/components/blocks/Image.tsx +395 -0
  226. package/src/components/blocks/PageBannerHeader.tsx +14 -12
  227. package/src/components/blocks/ProductCard.tsx +51 -52
  228. package/src/components/blocks/Section.tsx +113 -8
  229. package/src/components/blocks/Text.tsx +285 -0
  230. package/src/components/blocks/index.ts +4 -0
  231. package/src/components/buttons/Button.tsx +184 -15
  232. package/src/components/forms/FormBlock.tsx +70 -17
  233. package/src/components/index.ts +5 -0
  234. package/src/components/input/ChoiceInputField.tsx +48 -18
  235. package/src/components/input/HtmlInputField.tsx +48 -18
  236. package/src/components/input/SelectInputField.tsx +48 -16
  237. package/src/components/input/SwitchInputField.tsx +48 -17
  238. package/src/components/input/TextField.tsx +41 -1
  239. package/src/components/input/TextInputField.tsx +52 -18
  240. package/src/components/layout/GridCell.tsx +118 -9
  241. package/src/components/layout/GridLayout.tsx +125 -24
  242. package/src/components/pages/FormPage.tsx +0 -1
  243. package/src/components/pages/Page.css +304 -332
  244. package/src/components/pages/Page.tsx +307 -255
  245. package/src/components/pages/index.ts +2 -2
  246. package/src/config/AppConfig.ts +133 -0
  247. package/src/config/AppConfigBuilder.ts +421 -0
  248. package/src/config/__tests__/AppConfig.test.ts +385 -0
  249. package/src/config/__tests__/AppConfigBuilder.test.ts +432 -0
  250. package/src/config/index.ts +24 -0
  251. package/src/config/types.ts +170 -0
  252. package/src/config.ts +25 -0
  253. package/src/contexts/PrintModeContext.tsx +332 -0
  254. package/src/contexts/QwickAppContext.tsx +2 -2
  255. package/src/contexts/ThemeContext.tsx +1 -2
  256. package/src/contexts/index.ts +2 -0
  257. package/src/hooks/index.ts +5 -1
  258. package/src/hooks/usePrintMode.ts +73 -0
  259. package/src/index.ts +3 -0
  260. package/src/schemas/CodeSchema.ts +3 -3
  261. package/src/schemas/CollapsibleLayoutSchema.ts +2 -1
  262. package/src/schemas/ContentSchema.ts +2 -1
  263. package/src/schemas/GridCellSchema.ts +164 -0
  264. package/src/schemas/GridLayoutSchema.ts +133 -0
  265. package/src/schemas/HtmlSchema.ts +47 -0
  266. package/src/schemas/ImageSchema.ts +235 -0
  267. package/src/schemas/LogoSchema.ts +241 -0
  268. package/src/schemas/MarkdownSchema.ts +47 -0
  269. package/src/schemas/PageTemplateSchema.ts +186 -0
  270. package/src/schemas/PrintConfigSchema.ts +207 -0
  271. package/src/schemas/README.md +661 -0
  272. package/src/schemas/SectionSchema.ts +2 -1
  273. package/src/schemas/TextSchema.ts +329 -0
  274. package/src/schemas/ViewModelSchema.ts +115 -0
  275. package/src/schemas/index.ts +21 -2
  276. package/src/schemas/transformers/ComponentTransformer.ts +403 -0
  277. package/src/schemas/transformers/ReactNodeTransformer.ts +236 -0
  278. package/src/schemas/transformers/registry.ts +72 -0
  279. package/src/schemas/types/Serializable.ts +51 -0
  280. package/src/stories/AccessibilityProvider.stories.tsx +253 -253
  281. package/src/stories/Article.stories.tsx +433 -433
  282. package/src/stories/Button.stories.tsx +1 -1
  283. package/src/stories/CardListGrid.stories.tsx +451 -451
  284. package/src/stories/ChoiceInputField.stories.tsx +503 -503
  285. package/src/stories/Code.stories.tsx +1 -1
  286. package/src/stories/CollapsibleLayout.stories.tsx +1414 -1414
  287. package/src/stories/Content.stories.tsx +393 -393
  288. package/src/stories/CoverImageHeader.stories.tsx +701 -701
  289. package/src/stories/DataBinding.advanced.stories.tsx +432 -432
  290. package/src/stories/DataProvider.stories.tsx +1192 -1192
  291. package/src/stories/FeatureCard.stories.tsx +557 -557
  292. package/src/stories/FeatureGrid.stories.tsx +594 -594
  293. package/src/stories/Footer.stories.tsx +640 -640
  294. package/src/stories/FormBlock.stories.tsx +760 -760
  295. package/src/stories/FormComponents.stories.tsx +349 -541
  296. package/src/stories/GridCell.stories.tsx +417 -0
  297. package/src/stories/GridLayout.stories.tsx +353 -0
  298. package/src/stories/HeroBlock.stories.tsx +862 -373
  299. package/src/stories/HtmlInputField.stories.tsx +474 -474
  300. package/src/stories/Image.stories.tsx +819 -0
  301. package/src/stories/Introduction.stories.tsx +667 -667
  302. package/src/stories/LayoutBlocks.stories.tsx +324 -324
  303. package/src/stories/Logo.stories.tsx +165 -6
  304. package/src/stories/Markdown.stories.tsx +137 -137
  305. package/src/stories/ModelView.stories.tsx +477 -0
  306. package/src/stories/Page.stories.tsx +688 -688
  307. package/src/stories/PageBannerHeader.stories.tsx +864 -864
  308. package/src/stories/PaletteSwitcher.stories.tsx +119 -119
  309. package/src/stories/ProductCard.stories.tsx +424 -424
  310. package/src/stories/QwickApp.stories.tsx +368 -368
  311. package/src/stories/ResponsiveMenu.stories.tsx +249 -249
  312. package/src/stories/SafeSpan.stories.tsx +531 -531
  313. package/src/stories/Section.stories.tsx +90 -2
  314. package/src/stories/SelectInputField.stories.tsx +524 -524
  315. package/src/stories/Text.stories.tsx +560 -0
  316. package/src/stories/TextInputField.stories.tsx +443 -443
  317. package/src/stories/ThemeSwitcher.stories.tsx +123 -123
  318. package/src/utils/htmlTransform.tsx +74 -53
  319. package/src/utils/reactUtils.tsx +57 -6
  320. package/dist/index.bundled.css +0 -12
  321. /package/src/{hooks/__tests__ → __tests__/hooks}/useDataBinding.test.tsx.disabled +0 -0
  322. /package/src/{schemas/__tests__ → __tests__/schemas}/builders.test.ts +0 -0
  323. /package/src/{utils/__tests__ → __tests__/utils}/createDataDrivenComponent.test.tsx.disabled +0 -0
  324. /package/src/{utils/__tests__ → __tests__/utils}/htmlTransform.test.tsx +0 -0
  325. /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
+ });