@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,553 @@
1
+ /**
2
+ * Section Component Serialization Tests
3
+ *
4
+ * Tests the Serializable interface implementation for the Section component,
5
+ * focusing on container/layout component serialization with children support.
6
+ *
7
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
8
+ */
9
+
10
+ import React from 'react';
11
+ import { render, screen } from '@testing-library/react';
12
+ import '@testing-library/jest-dom';
13
+ import { Section } from '../../../components/blocks/Section';
14
+ import { Code } from '../../../components/blocks/Code';
15
+ import { ComponentTransformer } from '../../../schemas/transformers/ComponentTransformer';
16
+ import { ThemeProvider, PaletteProvider } from '../../../contexts';
17
+
18
+ // Test wrapper for components that need theme context
19
+ const TestWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
20
+ <ThemeProvider>
21
+ <PaletteProvider>
22
+ {children}
23
+ </PaletteProvider>
24
+ </ThemeProvider>
25
+ );
26
+
27
+ describe('Section Component Serialization', () => {
28
+ beforeEach(() => {
29
+ // Clear the component registry before each test
30
+ ComponentTransformer.clearRegistry();
31
+ });
32
+
33
+ afterEach(() => {
34
+ // Clean up the registry after each test
35
+ ComponentTransformer.clearRegistry();
36
+ });
37
+
38
+ describe('Component Registration', () => {
39
+ it('should register with correct tagName and version', () => {
40
+ expect(Section.tagName).toBe('Section');
41
+ expect(Section.version).toBe('1.0.0');
42
+
43
+ // Register the component
44
+ ComponentTransformer.registerComponent(Section as any);
45
+
46
+ // Verify it's registered
47
+ const registeredComponents = ComponentTransformer.getRegisteredComponents();
48
+ expect(registeredComponents).toContain('Section');
49
+ });
50
+
51
+ it('should implement Serializable interface correctly', () => {
52
+ const sectionInstance = new Section({ children: 'Test content' });
53
+
54
+ // Should have toJson method
55
+ expect(typeof sectionInstance.toJson).toBe('function');
56
+
57
+ // Should have static fromJson method
58
+ expect(typeof Section.fromJson).toBe('function');
59
+
60
+ // Should have static tagName and version
61
+ expect(Section.tagName).toBeDefined();
62
+ expect(Section.version).toBeDefined();
63
+ });
64
+ });
65
+
66
+ describe('Serialization (toJson)', () => {
67
+ it('should serialize basic props correctly', () => {
68
+ const sectionInstance = new Section({
69
+ children: 'Basic section content',
70
+ background: '#f5f5f5',
71
+ color: '#333333',
72
+ padding: 'medium'
73
+ });
74
+ const serializedData = sectionInstance.toJson();
75
+
76
+ // Note: children will be serialized to string by ComponentTransformer
77
+ expect(serializedData.background).toBe('#f5f5f5');
78
+ expect(serializedData.color).toBe('#333333');
79
+ expect(serializedData.padding).toBe('medium');
80
+ expect(serializedData.contentMaxWidth).toBeUndefined();
81
+ expect(serializedData.component).toBeUndefined();
82
+ expect(serializedData.dataSource).toBeUndefined();
83
+ expect(serializedData.bindingOptions).toBeUndefined();
84
+ });
85
+
86
+ it('should serialize all Section props correctly', () => {
87
+ const props = {
88
+ children: 'Full featured section',
89
+ background: 'var(--theme-primary)',
90
+ color: 'white',
91
+ padding: 'large' as const,
92
+ contentMaxWidth: 'md' as const,
93
+ component: 'article' as const
94
+ };
95
+
96
+ const sectionInstance = new Section(props);
97
+ const serializedData = sectionInstance.toJson();
98
+
99
+ expect(serializedData.background).toBe('var(--theme-primary)');
100
+ expect(serializedData.color).toBe('white');
101
+ expect(serializedData.padding).toBe('large');
102
+ expect(serializedData.contentMaxWidth).toBe('md');
103
+ expect(serializedData.component).toBe('article');
104
+ });
105
+
106
+ it('should serialize ReactNode children using ComponentTransformer', () => {
107
+ const reactNodeChildren = (
108
+ <div>
109
+ <h1>Title</h1>
110
+ <p>Paragraph content</p>
111
+ </div>
112
+ );
113
+ const sectionInstance = new Section({ children: reactNodeChildren });
114
+ const serializedData = sectionInstance.toJson();
115
+
116
+ // Children should be serialized using ComponentTransformer.serialize
117
+ expect(serializedData.children).toBeDefined();
118
+ // Since ComponentTransformer.serialize returns a string, we expect that
119
+ expect(typeof serializedData.children).toBe('string');
120
+ });
121
+
122
+ it('should serialize data binding props', () => {
123
+ const props = {
124
+ children: 'Section with data binding',
125
+ dataSource: 'sections.hero',
126
+ bindingOptions: { cache: true, strict: false }
127
+ };
128
+
129
+ const sectionInstance = new Section(props);
130
+ const serializedData = sectionInstance.toJson();
131
+
132
+ expect(serializedData.dataSource).toBe('sections.hero');
133
+ expect(serializedData.bindingOptions).toEqual({ cache: true, strict: false });
134
+ });
135
+
136
+ it('should handle empty/undefined children', () => {
137
+ const sectionInstance = new Section({ children: undefined });
138
+ const serializedData = sectionInstance.toJson();
139
+
140
+ expect(serializedData.children).toBeUndefined();
141
+ });
142
+
143
+ it('should serialize complex nested components', () => {
144
+ const nestedChildren = (
145
+ <div>
146
+ <h2>Section Title</h2>
147
+ <Code language="javascript">console.log('Hello');</Code>
148
+ <p>Regular paragraph</p>
149
+ </div>
150
+ );
151
+
152
+ const sectionInstance = new Section({ children: nestedChildren });
153
+ const serializedData = sectionInstance.toJson();
154
+
155
+ // Should serialize the entire nested structure
156
+ expect(serializedData.children).toBeDefined();
157
+ expect(typeof serializedData.children).toBe('string');
158
+ });
159
+ });
160
+
161
+ describe('Deserialization (fromJson)', () => {
162
+ it('should deserialize basic data to React element', () => {
163
+ const jsonData = {
164
+ children: 'Simple section content',
165
+ background: '#ffffff',
166
+ color: '#000000',
167
+ padding: 'small'
168
+ };
169
+
170
+ const reactElement = Section.fromJson(jsonData);
171
+
172
+ // Should return a React element
173
+ expect(React.isValidElement(reactElement)).toBe(true);
174
+ expect(reactElement.type).toBe(Section);
175
+ expect(reactElement.props).toEqual(jsonData);
176
+ });
177
+
178
+ it('should deserialize minimal data', () => {
179
+ const jsonData = {
180
+ children: 'Minimal section'
181
+ };
182
+
183
+ const reactElement = Section.fromJson(jsonData);
184
+
185
+ expect(React.isValidElement(reactElement)).toBe(true);
186
+ expect(reactElement.props.children).toBe('Minimal section');
187
+ });
188
+
189
+ it('should deserialize all Section properties', () => {
190
+ const jsonData = {
191
+ children: 'Full section content',
192
+ background: 'linear-gradient(45deg, #fe6b8b, #ff8e53)',
193
+ color: 'white',
194
+ padding: 'extra-large',
195
+ contentMaxWidth: 'xl',
196
+ component: 'main'
197
+ };
198
+
199
+ const reactElement = Section.fromJson(jsonData);
200
+
201
+ expect(reactElement.props).toEqual(jsonData);
202
+ });
203
+
204
+ it('should handle data binding configuration in deserialization', () => {
205
+ const jsonData = {
206
+ children: 'Section with CMS binding',
207
+ dataSource: 'pages.home.hero',
208
+ bindingOptions: { cache: false, cacheTTL: 30000 }
209
+ };
210
+
211
+ const reactElement = Section.fromJson(jsonData);
212
+
213
+ expect(reactElement.props.dataSource).toBe('pages.home.hero');
214
+ expect(reactElement.props.bindingOptions).toEqual({ cache: false, cacheTTL: 30000 });
215
+ });
216
+ });
217
+
218
+ describe('Round-trip Serialization', () => {
219
+ it('should preserve all props through serialize → deserialize cycle', () => {
220
+ const originalProps = {
221
+ children: 'Complete section content',
222
+ background: '#f8f9fa',
223
+ color: '#212529',
224
+ padding: 'large' as const,
225
+ contentMaxWidth: 'lg' as const,
226
+ component: 'section' as const
227
+ };
228
+
229
+ // Create instance → serialize → deserialize
230
+ const sectionInstance = new Section(originalProps);
231
+ const serializedData = sectionInstance.toJson();
232
+ const deserializedElement = Section.fromJson(serializedData);
233
+
234
+ // Compare props
235
+ expect(deserializedElement.props.background).toBe(originalProps.background);
236
+ expect(deserializedElement.props.color).toBe(originalProps.color);
237
+ expect(deserializedElement.props.padding).toBe(originalProps.padding);
238
+ expect(deserializedElement.props.contentMaxWidth).toBe(originalProps.contentMaxWidth);
239
+ expect(deserializedElement.props.component).toBe(originalProps.component);
240
+ });
241
+
242
+ it('should handle ReactNode children in round-trip', () => {
243
+ const reactNodeChildren = (
244
+ <div>
245
+ <h1>Main Title</h1>
246
+ <div>
247
+ <p>First paragraph</p>
248
+ <p>Second paragraph</p>
249
+ </div>
250
+ </div>
251
+ );
252
+
253
+ const sectionInstance = new Section({ children: reactNodeChildren });
254
+ const serializedData = sectionInstance.toJson();
255
+ const deserializedElement = Section.fromJson(serializedData);
256
+
257
+ // ReactNode children should be serialized to string by ComponentTransformer
258
+ expect(deserializedElement.props.children).toBeDefined();
259
+ });
260
+
261
+ it('should maintain functionality after round-trip', () => {
262
+ const originalProps = {
263
+ children: 'Functional section test',
264
+ background: '#e9ecef',
265
+ color: '#495057',
266
+ padding: 'medium' as const,
267
+ contentMaxWidth: 'md' as const
268
+ };
269
+
270
+ // Round-trip
271
+ const sectionInstance = new Section(originalProps);
272
+ const serializedData = sectionInstance.toJson();
273
+ const deserializedElement = Section.fromJson(serializedData);
274
+
275
+ // Render the deserialized element
276
+ render(
277
+ <TestWrapper>
278
+ {deserializedElement}
279
+ </TestWrapper>
280
+ );
281
+
282
+ // Should render correctly with original functionality
283
+ expect(screen.getByText(/Functional section test/)).toBeInTheDocument();
284
+ });
285
+
286
+ it('should handle empty and edge cases in round-trip', () => {
287
+ const edgeCaseProps = {
288
+ children: '',
289
+ background: '',
290
+ color: '',
291
+ padding: 'none' as const,
292
+ contentMaxWidth: false as const,
293
+ component: 'div' as const
294
+ };
295
+
296
+ const sectionInstance = new Section(edgeCaseProps);
297
+ const serializedData = sectionInstance.toJson();
298
+ const deserializedElement = Section.fromJson(serializedData);
299
+
300
+ // Should handle empty values gracefully - empty string children are preserved through serialization
301
+ expect(deserializedElement.props.children).toBeDefined();
302
+ expect(deserializedElement.props.background).toBe('');
303
+ expect(deserializedElement.props.color).toBe('');
304
+ expect(deserializedElement.props.padding).toBe('none');
305
+
306
+ // Render should work without errors
307
+ expect(() => {
308
+ render(
309
+ <TestWrapper>
310
+ {deserializedElement}
311
+ </TestWrapper>
312
+ );
313
+ }).not.toThrow();
314
+ });
315
+ });
316
+
317
+ describe('ComponentTransformer Integration', () => {
318
+ beforeEach(() => {
319
+ // Register the Section component for these tests
320
+ ComponentTransformer.registerComponent(Section as any);
321
+ });
322
+
323
+ it('should work with ComponentTransformer serialize/deserialize', () => {
324
+ const sectionElement = (
325
+ <Section
326
+ background="#f0f8ff"
327
+ color="#191970"
328
+ padding="large"
329
+ contentMaxWidth="lg"
330
+ >
331
+ <h1>Test Section</h1>
332
+ <p>Section content for testing</p>
333
+ </Section>
334
+ );
335
+
336
+ // Serialize using ComponentTransformer
337
+ const serializedString = ComponentTransformer.serialize(sectionElement);
338
+ expect(typeof serializedString).toBe('string');
339
+
340
+ const serializedData = JSON.parse(serializedString);
341
+ expect(serializedData.tag).toBe('Section');
342
+ expect(serializedData.version).toBe('1.0.0');
343
+ expect(serializedData.data.background).toBe('#f0f8ff');
344
+ expect(serializedData.data.color).toBe('#191970');
345
+ expect(serializedData.data.padding).toBe('large');
346
+ expect(serializedData.data.contentMaxWidth).toBe('lg');
347
+ });
348
+
349
+ it('should deserialize via ComponentTransformer correctly', () => {
350
+ const originalElement = (
351
+ <Section
352
+ background="var(--theme-surface)"
353
+ padding="medium"
354
+ component="article"
355
+ >
356
+ <h2>Article Section</h2>
357
+ <p>Article content here</p>
358
+ </Section>
359
+ );
360
+
361
+ // Round-trip via ComponentTransformer
362
+ const serializedString = ComponentTransformer.serialize(originalElement);
363
+ const deserializedElement = ComponentTransformer.deserialize(serializedString);
364
+
365
+ // Render both to verify they work
366
+ render(
367
+ <TestWrapper>
368
+ {originalElement}
369
+ </TestWrapper>
370
+ );
371
+
372
+ render(
373
+ <TestWrapper>
374
+ {deserializedElement as React.ReactElement}
375
+ </TestWrapper>
376
+ );
377
+
378
+ // Both should render content (exact structure may vary due to serialization)
379
+ expect(screen.getAllByText(/Article/).length).toBeGreaterThanOrEqual(1);
380
+ });
381
+
382
+ it('should handle nested Section with other components', () => {
383
+ // Register Code component for this test
384
+ ComponentTransformer.registerComponent(Code as any);
385
+
386
+ const nestedStructure = (
387
+ <Section background="#f8f9fa" padding="large">
388
+ <h1>Code Examples Section</h1>
389
+ <Code language="javascript" title="example.js">
390
+ console.log('Hello World');
391
+ </Code>
392
+ <Section background="#ffffff" padding="small">
393
+ <p>Nested section content</p>
394
+ </Section>
395
+ </Section>
396
+ );
397
+
398
+ // Should serialize nested components
399
+ const serializedString = ComponentTransformer.serialize(nestedStructure);
400
+ const deserializedStructure = ComponentTransformer.deserialize(serializedString);
401
+
402
+ // Render the deserialized structure
403
+ render(
404
+ <TestWrapper>
405
+ {deserializedStructure as React.ReactElement}
406
+ </TestWrapper>
407
+ );
408
+
409
+ // Should contain elements from both Section and Code components
410
+ const parsedData = JSON.parse(serializedString);
411
+ expect(parsedData).toBeDefined();
412
+ // Since this is a complex nested structure, we just verify it serializes without error
413
+ });
414
+
415
+ it('should maintain data binding capabilities after deserialization', () => {
416
+ const dataBindingProps = {
417
+ children: 'CMS-driven section',
418
+ background: 'var(--theme-primary)',
419
+ dataSource: 'sections.hero',
420
+ bindingOptions: { cache: true, strict: false }
421
+ };
422
+
423
+ const sectionElement = <Section {...dataBindingProps} />;
424
+
425
+ // Serialize and deserialize
426
+ const serialized = ComponentTransformer.serialize(sectionElement);
427
+ const deserialized = ComponentTransformer.deserialize(serialized) as React.ReactElement;
428
+
429
+ // Should preserve data binding props
430
+ expect(deserialized.props.dataSource).toBe('sections.hero');
431
+ expect(deserialized.props.bindingOptions).toEqual({ cache: true, strict: false });
432
+ });
433
+ });
434
+
435
+ describe('Children Serialization Edge Cases', () => {
436
+ beforeEach(() => {
437
+ ComponentTransformer.registerComponent(Section as any);
438
+ ComponentTransformer.registerComponent(Code as any);
439
+ });
440
+
441
+ it('should handle array of children', () => {
442
+ const arrayChildren = [
443
+ <h1 key="title">Title</h1>,
444
+ <p key="p1">Paragraph 1</p>,
445
+ <p key="p2">Paragraph 2</p>
446
+ ];
447
+
448
+ const sectionInstance = new Section({ children: arrayChildren });
449
+ const serializedData = sectionInstance.toJson();
450
+
451
+ expect(serializedData.children).toBeDefined();
452
+ expect(typeof serializedData.children).toBe('string');
453
+ });
454
+
455
+ it('should handle mixed content types as children', () => {
456
+ const mixedChildren = (
457
+ <>
458
+ Plain text
459
+ <span>Span element</span>
460
+ {42}
461
+ {true}
462
+ <Code language="javascript">const x = 1;</Code>
463
+ {null}
464
+ {undefined}
465
+ </>
466
+ );
467
+
468
+ const sectionInstance = new Section({ children: mixedChildren });
469
+
470
+ expect(() => {
471
+ const serializedData = sectionInstance.toJson();
472
+ expect(serializedData.children).toBeDefined();
473
+ }).not.toThrow();
474
+ });
475
+
476
+ it('should handle deeply nested component structures', () => {
477
+ const deeplyNested = (
478
+ <div>
479
+ <Section background="#f1f1f1">
480
+ <div>
481
+ <Section background="#e1e1e1">
482
+ <Code language="typescript">
483
+ interface User {'{'}
484
+ id: number;
485
+ {'}'}
486
+ </Code>
487
+ </Section>
488
+ </div>
489
+ </Section>
490
+ </div>
491
+ );
492
+
493
+ const sectionInstance = new Section({ children: deeplyNested });
494
+
495
+ expect(() => {
496
+ const serializedData = sectionInstance.toJson();
497
+ expect(serializedData.children).toBeDefined();
498
+ }).not.toThrow();
499
+ });
500
+ });
501
+
502
+ describe('Error Handling', () => {
503
+ it('should handle invalid JSON data gracefully', () => {
504
+ // Test with malformed data
505
+ expect(() => {
506
+ Section.fromJson(null);
507
+ }).not.toThrow();
508
+
509
+ expect(() => {
510
+ Section.fromJson({});
511
+ }).not.toThrow();
512
+
513
+ expect(() => {
514
+ Section.fromJson({ invalidProp: 'value' });
515
+ }).not.toThrow();
516
+ });
517
+
518
+ it('should handle serialization of invalid props', () => {
519
+ const invalidProps = {
520
+ children: null as any,
521
+ background: null as any,
522
+ padding: 'invalid' as any
523
+ };
524
+
525
+ const sectionInstance = new Section(invalidProps);
526
+
527
+ // Should not throw during serialization
528
+ expect(() => {
529
+ const serialized = sectionInstance.toJson();
530
+ expect(serialized).toBeDefined();
531
+ }).not.toThrow();
532
+ });
533
+
534
+ it('should handle complex children serialization errors gracefully', () => {
535
+ // Create children with potential serialization issues
536
+ const problematicChildren = (
537
+ <div>
538
+ {/* Function as child - should be handled gracefully */}
539
+ {(() => 'Dynamic content')()}
540
+ {/* Circular reference objects should be handled by ComponentTransformer */}
541
+ <span>Normal content</span>
542
+ </div>
543
+ );
544
+
545
+ const sectionInstance = new Section({ children: problematicChildren });
546
+
547
+ expect(() => {
548
+ const serialized = sectionInstance.toJson();
549
+ expect(serialized.children).toBeDefined();
550
+ }).not.toThrow();
551
+ });
552
+ });
553
+ });