@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,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
+ });