@qwickapps/react-framework 1.3.5 → 1.4.1

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 +1691 -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,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 = {