@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,359 @@
1
+ /**
2
+ * TextInputField Serialization Tests
3
+ *
4
+ * Tests the serialization and deserialization functionality of the TextInputField component.
5
+ * Ensures that all component properties are properly preserved through JSON serialization cycles.
6
+ *
7
+ * Test Coverage:
8
+ * - Basic text input serialization/deserialization
9
+ * - Multiline textarea field handling
10
+ * - Form validation properties (required, error, helperText)
11
+ * - Input type variations (text, email, password, etc.)
12
+ * - Performance benchmarks for serialization operations
13
+ *
14
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
15
+ */
16
+
17
+ import React from 'react';
18
+ import { render } from '@testing-library/react';
19
+ import '@testing-library/jest-dom';
20
+ import { ComponentTransformer } from '../../../schemas/transformers/ComponentTransformer';
21
+ import { TextInputField } from '../../../components/input/TextInputField';
22
+
23
+ // Ensure the component is registered
24
+ import '../../../schemas/transformers/registry';
25
+
26
+ describe('TextInputField Serialization', () => {
27
+ // Performance tracking
28
+ const performanceData: Array<{ operation: string; duration: number }> = [];
29
+
30
+ beforeEach(() => {
31
+ // Clear component registry for clean tests
32
+ ComponentTransformer.clearRegistry();
33
+
34
+ // Register TextInputField component
35
+ ComponentTransformer.registerComponent(TextInputField as any);
36
+ });
37
+
38
+ afterEach(() => {
39
+ ComponentTransformer.clearRegistry();
40
+ });
41
+
42
+ afterAll(() => {
43
+ // Log performance summary
44
+ console.log('\n📊 TextInputField Serialization Performance Summary:');
45
+ performanceData.forEach(({ operation, duration }) => {
46
+ console.log(` • ${operation}: ${duration.toFixed(3)}ms`);
47
+ });
48
+ const avgDuration = performanceData.reduce((sum, { duration }) => sum + duration, 0) / performanceData.length;
49
+ console.log(` • Average: ${avgDuration.toFixed(3)}ms\n`);
50
+ });
51
+
52
+ const measurePerformance = (operation: string, fn: () => void) => {
53
+ const start = performance.now();
54
+ fn();
55
+ const duration = performance.now() - start;
56
+ performanceData.push({ operation, duration });
57
+ return duration;
58
+ };
59
+
60
+ describe('Basic Text Input Field', () => {
61
+ it('serializes and deserializes basic text input correctly', () => {
62
+ const originalProps = {
63
+ label: 'Full Name',
64
+ value: 'John Doe',
65
+ placeholder: 'Enter your full name',
66
+ required: true,
67
+ disabled: false,
68
+ type: 'text'
69
+ };
70
+
71
+ let serializedData: any;
72
+ let deserializedElement: React.ReactElement;
73
+ let reserializedData: any;
74
+
75
+ // Test serialization
76
+ const serializationTime = measurePerformance('Basic Serialization', () => {
77
+ const element = <TextInputField {...originalProps} />;
78
+ const serialized = ComponentTransformer.serialize(element);
79
+ serializedData = JSON.parse(serialized);
80
+ });
81
+
82
+ expect(serializedData).toBeDefined();
83
+ expect(serializedData.tag).toBe('TextInputField');
84
+ expect(serializedData.data.label).toBe(originalProps.label);
85
+ expect(serializedData.data.value).toBe(originalProps.value);
86
+ expect(serializedData.data.placeholder).toBe(originalProps.placeholder);
87
+ expect(serializedData.data.required).toBe(originalProps.required);
88
+ expect(serializedData.data.disabled).toBe(originalProps.disabled);
89
+ expect(serializedData.data.type).toBe(originalProps.type);
90
+
91
+ // Test deserialization
92
+ const deserializationTime = measurePerformance('Basic Deserialization', () => {
93
+ deserializedElement = ComponentTransformer.deserialize(JSON.stringify(serializedData)) as React.ReactElement;
94
+ });
95
+
96
+ expect(React.isValidElement(deserializedElement)).toBe(true);
97
+ expect(deserializedElement.type).toBe(TextInputField);
98
+
99
+ // Test re-serialization (round-trip)
100
+ const reserializationTime = measurePerformance('Basic Re-serialization', () => {
101
+ const reserialized = ComponentTransformer.serialize(deserializedElement);
102
+ reserializedData = JSON.parse(reserialized);
103
+ });
104
+
105
+ expect(reserializedData.data).toEqual(serializedData.data);
106
+
107
+ // Performance assertions
108
+ expect(serializationTime).toBeLessThan(1); // Should be under 1ms
109
+ expect(deserializationTime).toBeLessThan(1);
110
+ expect(reserializationTime).toBeLessThan(1);
111
+ });
112
+
113
+ it('renders serialized component correctly', () => {
114
+ const originalProps = {
115
+ label: 'Email Address',
116
+ value: 'user@example.com',
117
+ type: 'email',
118
+ required: true
119
+ };
120
+
121
+ const element = <TextInputField {...originalProps} />;
122
+ const serialized = ComponentTransformer.serialize(element);
123
+ const deserializedElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
124
+
125
+ const { getByDisplayValue, getByLabelText } = render(deserializedElement);
126
+
127
+ expect(getByLabelText('Email Address *')).toBeInTheDocument();
128
+ expect(getByDisplayValue('user@example.com')).toBeInTheDocument();
129
+ });
130
+ });
131
+
132
+ describe('Multiline Textarea Field', () => {
133
+ it('serializes multiline textarea properties correctly', () => {
134
+ const originalProps = {
135
+ label: 'Description',
136
+ value: 'This is a multi-line\ndescription with\nline breaks.',
137
+ multiline: true,
138
+ rows: 4,
139
+ maxRows: 8,
140
+ placeholder: 'Enter your description...'
141
+ };
142
+
143
+ const element = <TextInputField {...originalProps} />;
144
+
145
+ let serializedData: any;
146
+ measurePerformance('Multiline Serialization', () => {
147
+ const serialized = ComponentTransformer.serialize(element);
148
+ serializedData = JSON.parse(serialized);
149
+ });
150
+
151
+ expect(serializedData.data.multiline).toBe(true);
152
+ expect(serializedData.data.rows).toBe(4);
153
+ expect(serializedData.data.maxRows).toBe(8);
154
+ expect(serializedData.data.value).toBe(originalProps.value);
155
+
156
+ const deserializedElement = ComponentTransformer.deserialize(JSON.stringify(serializedData)) as React.ReactElement;
157
+ const reserializedString = ComponentTransformer.serialize(deserializedElement);
158
+ const reserializedData = JSON.parse(reserializedString);
159
+
160
+ expect(reserializedData.data.multiline).toBe(true);
161
+ expect(reserializedData.data.rows).toBe(4);
162
+ expect(reserializedData.data.maxRows).toBe(8);
163
+ });
164
+ });
165
+
166
+ describe('Form Validation Properties', () => {
167
+ it('preserves validation and error state through serialization', () => {
168
+ const originalProps = {
169
+ label: 'Username',
170
+ value: 'invalid-username!',
171
+ required: true,
172
+ error: 'Username can only contain letters and numbers',
173
+ helperText: 'Choose a unique username'
174
+ };
175
+
176
+ const element = <TextInputField {...originalProps} />;
177
+
178
+ let serializedData: any;
179
+ measurePerformance('Validation Serialization', () => {
180
+ const serialized = ComponentTransformer.serialize(element);
181
+ serializedData = JSON.parse(serialized);
182
+ });
183
+
184
+ expect(serializedData.data.required).toBe(true);
185
+ expect(serializedData.data.error).toBe(originalProps.error);
186
+ expect(serializedData.data.helperText).toBe(originalProps.helperText);
187
+
188
+ const deserializedElement = ComponentTransformer.deserialize(JSON.stringify(serializedData)) as React.ReactElement;
189
+ const { getByLabelText, getByText } = render(deserializedElement);
190
+
191
+ expect(getByLabelText('Username *')).toBeInTheDocument();
192
+ expect(getByText('Username can only contain letters and numbers')).toBeInTheDocument();
193
+ });
194
+
195
+ it('handles disabled state correctly', () => {
196
+ const originalProps = {
197
+ label: 'Locked Field',
198
+ value: 'Cannot be changed',
199
+ disabled: true,
200
+ helperText: 'This field is read-only'
201
+ };
202
+
203
+ const element = <TextInputField {...originalProps} />;
204
+ const serialized = ComponentTransformer.serialize(element);
205
+ const serializedData = JSON.parse(serialized);
206
+
207
+ expect(serializedData.data.disabled).toBe(true);
208
+
209
+ const deserializedElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
210
+ const { getByDisplayValue } = render(deserializedElement);
211
+
212
+ const inputElement = getByDisplayValue('Cannot be changed') as HTMLInputElement;
213
+ expect(inputElement.disabled).toBe(true);
214
+ });
215
+ });
216
+
217
+ describe('Input Type Variations', () => {
218
+ const inputTypes = ['text', 'email', 'password', 'number', 'tel', 'url'];
219
+
220
+ inputTypes.forEach(inputType => {
221
+ it(`serializes ${inputType} input type correctly`, () => {
222
+ const originalProps = {
223
+ label: `${inputType.charAt(0).toUpperCase() + inputType.slice(1)} Field`,
224
+ value: inputType === 'number' ? '42' : `sample-${inputType}`,
225
+ type: inputType,
226
+ placeholder: `Enter ${inputType}`
227
+ };
228
+
229
+ const element = <TextInputField {...originalProps} />;
230
+ const serialized = ComponentTransformer.serialize(element);
231
+ const serializedData = JSON.parse(serialized);
232
+
233
+ expect(serializedData.data.type).toBe(inputType);
234
+
235
+ const deserializedElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
236
+ const reserializedString = ComponentTransformer.serialize(deserializedElement);
237
+ const reserializedData = JSON.parse(reserializedString);
238
+
239
+ expect(reserializedData.data.type).toBe(inputType);
240
+ });
241
+ });
242
+ });
243
+
244
+ describe('Edge Cases and Error Handling', () => {
245
+ it('handles empty/undefined values correctly', () => {
246
+ const originalProps = {
247
+ label: 'Optional Field',
248
+ value: '',
249
+ placeholder: undefined,
250
+ helperText: undefined,
251
+ error: undefined
252
+ };
253
+
254
+ const element = <TextInputField {...originalProps} />;
255
+ const serialized = ComponentTransformer.serialize(element);
256
+ const serializedData = JSON.parse(serialized);
257
+
258
+ expect(serializedData.data.value).toBe('');
259
+ // Undefined values should not appear in serialized data
260
+ expect(serializedData.data.placeholder).toBeUndefined();
261
+ expect(serializedData.data.helperText).toBeUndefined();
262
+ expect(serializedData.data.error).toBeUndefined();
263
+
264
+ const deserializedElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
265
+ expect(React.isValidElement(deserializedElement)).toBe(true);
266
+ });
267
+
268
+ it('handles special characters in text values', () => {
269
+ const specialText = 'Special chars: åäö 中文 🚀 "quotes" <tags> & symbols!';
270
+ const originalProps = {
271
+ label: 'Unicode Test',
272
+ value: specialText,
273
+ placeholder: 'Special chars: åäö 中文 🚀'
274
+ };
275
+
276
+ const element = <TextInputField {...originalProps} />;
277
+ const serialized = ComponentTransformer.serialize(element);
278
+ const serializedData = JSON.parse(serialized);
279
+
280
+ expect(serializedData.data.value).toBe(specialText);
281
+
282
+ const deserializedElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
283
+ const { getByDisplayValue } = render(deserializedElement);
284
+
285
+ expect(getByDisplayValue(specialText)).toBeInTheDocument();
286
+ });
287
+ });
288
+
289
+ describe('Performance Benchmarks', () => {
290
+ it('meets performance targets for bulk operations', () => {
291
+ const testConfigurations = Array.from({ length: 100 }, (_, i) => ({
292
+ label: `Field ${i + 1}`,
293
+ value: `Value ${i + 1}`,
294
+ type: ['text', 'email', 'password'][i % 3],
295
+ required: i % 2 === 0,
296
+ multiline: i % 5 === 0,
297
+ rows: i % 5 === 0 ? 3 : undefined
298
+ }));
299
+
300
+ let elements: React.ReactElement[];
301
+ let serializedData: any[];
302
+ let deserializedElements: React.ReactElement[];
303
+
304
+ // Bulk serialization
305
+ const bulkSerializationTime = measurePerformance('Bulk Serialization (100 items)', () => {
306
+ elements = testConfigurations.map(props => <TextInputField {...props} />);
307
+ serializedData = elements.map(element => JSON.parse(ComponentTransformer.serialize(element)));
308
+ });
309
+
310
+ // Bulk deserialization
311
+ const bulkDeserializationTime = measurePerformance('Bulk Deserialization (100 items)', () => {
312
+ deserializedElements = serializedData.map(data => ComponentTransformer.deserialize(JSON.stringify(data)) as React.ReactElement);
313
+ });
314
+
315
+ expect(serializedData).toHaveLength(100);
316
+ expect(deserializedElements).toHaveLength(100);
317
+ expect(bulkSerializationTime).toBeLessThan(50); // Should handle 100 items in under 50ms
318
+ expect(bulkDeserializationTime).toBeLessThan(50);
319
+
320
+ // Verify random sample correctness
321
+ const randomIndex = Math.floor(Math.random() * 100);
322
+ const originalConfig = testConfigurations[randomIndex];
323
+ const serializedConfig = serializedData[randomIndex];
324
+
325
+ expect(serializedConfig.data.label).toBe(originalConfig.label);
326
+ expect(serializedConfig.data.value).toBe(originalConfig.value);
327
+ expect(serializedConfig.data.type).toBe(originalConfig.type);
328
+ });
329
+ });
330
+
331
+ describe('Data Integrity', () => {
332
+ it('maintains referential integrity through multiple serialization cycles', () => {
333
+ const originalProps = {
334
+ label: 'Cycle Test Field',
335
+ value: 'Original Value',
336
+ required: true,
337
+ multiline: true,
338
+ rows: 5
339
+ };
340
+
341
+ let currentElement = <TextInputField {...originalProps} />;
342
+ let lastSerializedData: any;
343
+
344
+ // Perform 10 serialize-deserialize cycles
345
+ for (let cycle = 0; cycle < 10; cycle++) {
346
+ const serializedString = ComponentTransformer.serialize(currentElement);
347
+ lastSerializedData = JSON.parse(serializedString);
348
+ currentElement = ComponentTransformer.deserialize(serializedString) as React.ReactElement;
349
+ }
350
+
351
+ // Verify data integrity after 10 cycles
352
+ expect(lastSerializedData.data.label).toBe(originalProps.label);
353
+ expect(lastSerializedData.data.value).toBe(originalProps.value);
354
+ expect(lastSerializedData.data.required).toBe(originalProps.required);
355
+ expect(lastSerializedData.data.multiline).toBe(originalProps.multiline);
356
+ expect(lastSerializedData.data.rows).toBe(originalProps.rows);
357
+ });
358
+ });
359
+ });
@@ -19,11 +19,11 @@ import React from 'react';
19
19
  import { render, screen, fireEvent, waitFor, act } from '@testing-library/react';
20
20
  import userEvent from '@testing-library/user-event';
21
21
  import '@testing-library/jest-dom';
22
- import CollapsibleLayout, { CollapsibleLayoutView, useCollapsibleState } from '../CollapsibleLayout';
23
- import { DataProvider } from '../../../../contexts/DataContext';
22
+ import CollapsibleLayout, { CollapsibleLayoutView, useCollapsibleState } from '../../../components/layout/CollapsibleLayout';
23
+ import { DataProvider } from '../../../contexts/DataContext';
24
24
  import { JsonDataProvider } from '@qwickapps/schema';
25
- import { ThemeProvider, PaletteProvider } from '../../../../contexts';
26
- import { CollapsibleLayoutProps } from '../../../../types/CollapsibleLayout';
25
+ import { ThemeProvider, PaletteProvider } from '../../../contexts';
26
+ import { CollapsibleLayoutProps } from '../../../types/CollapsibleLayout';
27
27
 
28
28
  // Test data for data binding
29
29
  const sampleCmsData = {