@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,507 @@
1
+ /**
2
+ * Code Component Serialization Tests
3
+ *
4
+ * Tests the Serializable interface implementation for the Code component,
5
+ * serving as the template pattern for all other component serialization implementations.
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 { Code } from '../../../components/blocks/Code';
14
+ import { ComponentTransformer } from '../../../schemas/transformers/ComponentTransformer';
15
+ import { ThemeProvider, PaletteProvider } from '../../../contexts';
16
+
17
+ // Test wrapper for components that need theme context
18
+ const TestWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
19
+ <ThemeProvider>
20
+ <PaletteProvider>
21
+ {children}
22
+ </PaletteProvider>
23
+ </ThemeProvider>
24
+ );
25
+
26
+ // Sample code content for testing
27
+ const sampleJavaScript = `function greet(name) {
28
+ return \`Hello, \${name}!\`;
29
+ }
30
+
31
+ console.log(greet('World'));`;
32
+
33
+ const sampleTypeScript = `interface User {
34
+ id: number;
35
+ name: string;
36
+ }
37
+
38
+ const getUser = (id: number): User => {
39
+ return { id, name: 'Test User' };
40
+ };`;
41
+
42
+ describe('Code Component Serialization', () => {
43
+ beforeEach(() => {
44
+ // Clear the component registry before each test
45
+ ComponentTransformer.clearRegistry();
46
+ });
47
+
48
+ afterEach(() => {
49
+ // Clean up the registry after each test
50
+ ComponentTransformer.clearRegistry();
51
+ });
52
+
53
+ describe('Component Registration', () => {
54
+ it('should register with correct tagName and version', () => {
55
+ expect(Code.tagName).toBe('Code');
56
+ expect(Code.version).toBe('1.0.0');
57
+
58
+ // Register the component
59
+ ComponentTransformer.registerComponent(Code as any);
60
+
61
+ // Verify it's registered
62
+ const registeredComponents = ComponentTransformer.getRegisteredComponents();
63
+ expect(registeredComponents).toContain('Code');
64
+ });
65
+
66
+ it('should implement Serializable interface correctly', () => {
67
+ const codeInstance = new Code({ children: sampleJavaScript });
68
+
69
+ // Should have toJson method
70
+ expect(typeof codeInstance.toJson).toBe('function');
71
+
72
+ // Should have static fromJson method
73
+ expect(typeof Code.fromJson).toBe('function');
74
+
75
+ // Should have static tagName and version
76
+ expect(Code.tagName).toBeDefined();
77
+ expect(Code.version).toBeDefined();
78
+ });
79
+ });
80
+
81
+ describe('Serialization (toJson)', () => {
82
+ it('should serialize string children correctly', () => {
83
+ const codeInstance = new Code({ children: sampleJavaScript });
84
+ const serializedData = codeInstance.toJson();
85
+
86
+ expect(serializedData).toEqual({
87
+ children: sampleJavaScript,
88
+ language: undefined,
89
+ showCopy: undefined,
90
+ showLineNumbers: undefined,
91
+ title: undefined,
92
+ wrapLines: undefined,
93
+ codeBackground: undefined,
94
+ dataSource: undefined,
95
+ bindingOptions: undefined
96
+ });
97
+ });
98
+
99
+ it('should serialize all props correctly', () => {
100
+ const props = {
101
+ children: sampleTypeScript,
102
+ language: 'typescript',
103
+ showCopy: true,
104
+ showLineNumbers: true,
105
+ title: 'example.ts',
106
+ wrapLines: false,
107
+ codeBackground: '#f5f5f5'
108
+ };
109
+
110
+ const codeInstance = new Code(props);
111
+ const serializedData = codeInstance.toJson();
112
+
113
+ expect(serializedData).toEqual({
114
+ children: sampleTypeScript,
115
+ language: 'typescript',
116
+ showCopy: true,
117
+ showLineNumbers: true,
118
+ title: 'example.ts',
119
+ wrapLines: false,
120
+ codeBackground: '#f5f5f5',
121
+ dataSource: undefined,
122
+ bindingOptions: undefined
123
+ });
124
+ });
125
+
126
+ it('should serialize ReactNode children as string', () => {
127
+ const reactNodeChildren = <span>Hello World</span>;
128
+ const codeInstance = new Code({ children: reactNodeChildren });
129
+ const serializedData = codeInstance.toJson();
130
+
131
+ // ReactNode children should be converted to string using extractTextFromReactNode
132
+ expect(typeof serializedData.children).toBe('string');
133
+ expect(serializedData.children).toBe('Hello World');
134
+ });
135
+
136
+ it('should serialize data binding props', () => {
137
+ const props = {
138
+ children: sampleJavaScript,
139
+ dataSource: 'codes.example',
140
+ bindingOptions: { cache: true, strict: false }
141
+ };
142
+
143
+ const codeInstance = new Code(props);
144
+ const serializedData = codeInstance.toJson();
145
+
146
+ expect(serializedData.dataSource).toBe('codes.example');
147
+ expect(serializedData.bindingOptions).toEqual({ cache: true, strict: false });
148
+ });
149
+
150
+ it('should handle empty children', () => {
151
+ const codeInstance = new Code({ children: '' });
152
+ const serializedData = codeInstance.toJson();
153
+
154
+ expect(serializedData.children).toBe('');
155
+ });
156
+
157
+ it('should handle complex ReactNode children', () => {
158
+ const complexChildren = (
159
+ <div>
160
+ <span>Line 1</span>
161
+ <br />
162
+ <span>Line 2</span>
163
+ </div>
164
+ );
165
+
166
+ const codeInstance = new Code({ children: complexChildren });
167
+ const serializedData = codeInstance.toJson();
168
+
169
+ // Should extract text from complex ReactNode structure
170
+ expect(typeof serializedData.children).toBe('string');
171
+ expect(serializedData.children).toContain('Line 1');
172
+ expect(serializedData.children).toContain('Line 2');
173
+ });
174
+ });
175
+
176
+ describe('Deserialization (fromJson)', () => {
177
+ it('should deserialize basic data to React element', () => {
178
+ const jsonData = {
179
+ children: sampleJavaScript,
180
+ language: 'javascript',
181
+ showCopy: true,
182
+ title: 'example.js'
183
+ };
184
+
185
+ const reactElement = Code.fromJson(jsonData);
186
+
187
+ // Should return a React element
188
+ expect(React.isValidElement(reactElement)).toBe(true);
189
+ expect(reactElement.type).toBe(Code);
190
+ expect(reactElement.props).toEqual(jsonData);
191
+ });
192
+
193
+ it('should deserialize minimal data', () => {
194
+ const jsonData = {
195
+ children: 'console.log("hello");'
196
+ };
197
+
198
+ const reactElement = Code.fromJson(jsonData);
199
+
200
+ expect(React.isValidElement(reactElement)).toBe(true);
201
+ expect(reactElement.props.children).toBe('console.log("hello");');
202
+ });
203
+
204
+ it('should deserialize all code properties', () => {
205
+ const jsonData = {
206
+ children: sampleTypeScript,
207
+ language: 'typescript',
208
+ showCopy: false,
209
+ showLineNumbers: true,
210
+ title: 'UserService.ts',
211
+ wrapLines: true,
212
+ codeBackground: '#2d2d2d'
213
+ };
214
+
215
+ const reactElement = Code.fromJson(jsonData);
216
+
217
+ expect(reactElement.props).toEqual(jsonData);
218
+ });
219
+
220
+ it('should handle data binding configuration in deserialization', () => {
221
+ const jsonData = {
222
+ children: sampleJavaScript,
223
+ dataSource: 'api.codes.example',
224
+ bindingOptions: { cache: false, cacheTTL: 60000 }
225
+ };
226
+
227
+ const reactElement = Code.fromJson(jsonData);
228
+
229
+ expect(reactElement.props.dataSource).toBe('api.codes.example');
230
+ expect(reactElement.props.bindingOptions).toEqual({ cache: false, cacheTTL: 60000 });
231
+ });
232
+ });
233
+
234
+ describe('Round-trip Serialization', () => {
235
+ it('should preserve all props through serialize → deserialize cycle', () => {
236
+ const originalProps = {
237
+ children: sampleTypeScript,
238
+ language: 'typescript',
239
+ showCopy: true,
240
+ showLineNumbers: false,
241
+ title: 'Component.tsx',
242
+ wrapLines: true,
243
+ codeBackground: '#ffffff'
244
+ };
245
+
246
+ // Create instance → serialize → deserialize
247
+ const codeInstance = new Code(originalProps);
248
+ const serializedData = codeInstance.toJson();
249
+ const deserializedElement = Code.fromJson(serializedData);
250
+
251
+ // Compare props (excluding undefined values from serialization)
252
+ expect(deserializedElement.props.children).toBe(originalProps.children);
253
+ expect(deserializedElement.props.language).toBe(originalProps.language);
254
+ expect(deserializedElement.props.showCopy).toBe(originalProps.showCopy);
255
+ expect(deserializedElement.props.showLineNumbers).toBe(originalProps.showLineNumbers);
256
+ expect(deserializedElement.props.title).toBe(originalProps.title);
257
+ expect(deserializedElement.props.wrapLines).toBe(originalProps.wrapLines);
258
+ expect(deserializedElement.props.codeBackground).toBe(originalProps.codeBackground);
259
+ });
260
+
261
+ it('should handle ReactNode children in round-trip', () => {
262
+ const reactNodeChildren = (
263
+ <div>
264
+ <code>const x = 1;</code>
265
+ <br />
266
+ <code>console.log(x);</code>
267
+ </div>
268
+ );
269
+
270
+ const codeInstance = new Code({ children: reactNodeChildren });
271
+ const serializedData = codeInstance.toJson();
272
+ const deserializedElement = Code.fromJson(serializedData);
273
+
274
+ // ReactNode children should be converted to string and back
275
+ expect(typeof deserializedElement.props.children).toBe('string');
276
+ expect(deserializedElement.props.children).toContain('const x = 1;');
277
+ expect(deserializedElement.props.children).toContain('console.log(x);');
278
+ });
279
+
280
+ it('should maintain functionality after round-trip', () => {
281
+ const originalProps = {
282
+ children: sampleJavaScript,
283
+ language: 'javascript',
284
+ showCopy: true,
285
+ showLineNumbers: true,
286
+ title: 'test.js'
287
+ };
288
+
289
+ // Round-trip
290
+ const codeInstance = new Code(originalProps);
291
+ const serializedData = codeInstance.toJson();
292
+ const deserializedElement = Code.fromJson(serializedData);
293
+
294
+ // Render the deserialized element
295
+ render(
296
+ <TestWrapper>
297
+ {deserializedElement}
298
+ </TestWrapper>
299
+ );
300
+
301
+ // Should render correctly with all original functionality
302
+ expect(screen.getByText(/function greet/)).toBeInTheDocument();
303
+ expect(screen.getByText('test.js')).toBeInTheDocument();
304
+ expect(screen.getByText('1')).toBeInTheDocument(); // Line numbers
305
+ expect(screen.getByRole('button', { name: /copy code/i })).toBeInTheDocument();
306
+ });
307
+
308
+ it('should handle empty and edge cases in round-trip', () => {
309
+ const edgeCaseProps = {
310
+ children: '',
311
+ language: '',
312
+ showCopy: false,
313
+ showLineNumbers: false,
314
+ title: '',
315
+ wrapLines: false
316
+ };
317
+
318
+ const codeInstance = new Code(edgeCaseProps);
319
+ const serializedData = codeInstance.toJson();
320
+ const deserializedElement = Code.fromJson(serializedData);
321
+
322
+ // Should handle empty values gracefully
323
+ expect(deserializedElement.props.children).toBe('');
324
+ expect(deserializedElement.props.language).toBe('');
325
+ expect(deserializedElement.props.title).toBe('');
326
+
327
+ // Render should work
328
+ render(
329
+ <TestWrapper>
330
+ {deserializedElement}
331
+ </TestWrapper>
332
+ );
333
+
334
+ // Should show empty state
335
+ expect(screen.getByText('No code content provided')).toBeInTheDocument();
336
+ });
337
+ });
338
+
339
+ describe('ComponentTransformer Integration', () => {
340
+ beforeEach(() => {
341
+ // Register the Code component for these tests
342
+ ComponentTransformer.registerComponent(Code as any);
343
+ });
344
+
345
+ it('should work with ComponentTransformer serialize/deserialize', () => {
346
+ const codeElement = (
347
+ <Code
348
+ language="javascript"
349
+ showCopy={true}
350
+ title="example.js"
351
+ >
352
+ {sampleJavaScript}
353
+ </Code>
354
+ );
355
+
356
+ // Serialize using ComponentTransformer
357
+ const serializedString = ComponentTransformer.serialize(codeElement);
358
+ expect(typeof serializedString).toBe('string');
359
+
360
+ const serializedData = JSON.parse(serializedString);
361
+ expect(serializedData.tag).toBe('Code');
362
+ expect(serializedData.version).toBe('1.0.0');
363
+ expect(serializedData.data.children).toBe(sampleJavaScript);
364
+ expect(serializedData.data.language).toBe('javascript');
365
+ expect(serializedData.data.title).toBe('example.js');
366
+ });
367
+
368
+ it('should deserialize via ComponentTransformer correctly', () => {
369
+ const originalElement = (
370
+ <Code
371
+ language="typescript"
372
+ showLineNumbers={true}
373
+ title="Component.tsx"
374
+ >
375
+ {sampleTypeScript}
376
+ </Code>
377
+ );
378
+
379
+ // Round-trip via ComponentTransformer
380
+ const serializedString = ComponentTransformer.serialize(originalElement);
381
+ const deserializedElement = ComponentTransformer.deserialize(serializedString);
382
+
383
+ // Render both to verify they work the same
384
+ const { container: originalContainer } = render(
385
+ <TestWrapper>
386
+ {originalElement}
387
+ </TestWrapper>
388
+ );
389
+
390
+ const { container: deserializedContainer } = render(
391
+ <TestWrapper>
392
+ {deserializedElement as React.ReactElement}
393
+ </TestWrapper>
394
+ );
395
+
396
+ // Should have similar structure (exact comparison may vary due to React internals)
397
+ expect(screen.getAllByText(/interface User/).length).toBe(2); // Both should render
398
+ expect(screen.getAllByText('Component.tsx').length).toBe(2); // Both should show title
399
+ expect(screen.getAllByText('1').length).toBe(2); // Both should show line numbers
400
+ });
401
+
402
+ it('should handle nested Code components', () => {
403
+ const nestedStructure = (
404
+ <div>
405
+ <Code language="javascript" title="Script 1">{sampleJavaScript}</Code>
406
+ <Code language="typescript" title="Script 2">{sampleTypeScript}</Code>
407
+ </div>
408
+ );
409
+
410
+ // Should serialize nested components
411
+ const serializedString = ComponentTransformer.serialize(nestedStructure);
412
+ const deserializedStructure = ComponentTransformer.deserialize(serializedString);
413
+
414
+ // Render the deserialized structure
415
+ render(
416
+ <TestWrapper>
417
+ {deserializedStructure as React.ReactElement}
418
+ </TestWrapper>
419
+ );
420
+
421
+ // Both Code components should be rendered with their content
422
+ // Note: titles might not appear if components are deserialized as unregistered
423
+ // but the code content should be present
424
+ expect(screen.getByText(/function greet/)).toBeInTheDocument();
425
+ expect(screen.getByText(/interface User/)).toBeInTheDocument();
426
+
427
+ // The serialized structure should contain the component data
428
+ const parsedData = JSON.parse(serializedString);
429
+ expect(parsedData).toBeDefined();
430
+ // Since this is a complex nested structure, we just verify it serializes without error
431
+ });
432
+
433
+ it('should maintain data binding capabilities after deserialization', () => {
434
+ const dataBindingProps = {
435
+ children: sampleJavaScript,
436
+ dataSource: 'codes.example',
437
+ bindingOptions: { cache: true, strict: false }
438
+ };
439
+
440
+ const codeElement = <Code {...dataBindingProps} />;
441
+
442
+ // Serialize and deserialize
443
+ const serialized = ComponentTransformer.serialize(codeElement);
444
+ const deserialized = ComponentTransformer.deserialize(serialized) as React.ReactElement;
445
+
446
+ // Should preserve data binding props
447
+ expect(deserialized.props.dataSource).toBe('codes.example');
448
+ expect(deserialized.props.bindingOptions).toEqual({ cache: true, strict: false });
449
+ });
450
+ });
451
+
452
+ describe('Error Handling', () => {
453
+ it('should handle invalid JSON data gracefully', () => {
454
+ // Test with malformed data
455
+ expect(() => {
456
+ Code.fromJson(null);
457
+ }).not.toThrow();
458
+
459
+ expect(() => {
460
+ Code.fromJson({});
461
+ }).not.toThrow();
462
+
463
+ expect(() => {
464
+ Code.fromJson({ invalidProp: 'value' });
465
+ }).not.toThrow();
466
+ });
467
+
468
+ it('should handle serialization of invalid props', () => {
469
+ const invalidProps = {
470
+ children: undefined as any,
471
+ language: null as any,
472
+ showCopy: 'invalid' as any
473
+ };
474
+
475
+ const codeInstance = new Code(invalidProps);
476
+
477
+ // Should not throw during serialization
478
+ expect(() => {
479
+ const serialized = codeInstance.toJson();
480
+ expect(serialized).toBeDefined();
481
+ }).not.toThrow();
482
+ });
483
+
484
+ it('should handle complex React children gracefully', () => {
485
+ const complexChildren = (
486
+ <div>
487
+ <span>Text</span>
488
+ {null}
489
+ {undefined}
490
+ {false}
491
+ {0}
492
+ <div>
493
+ <p>Nested content</p>
494
+ {['array', 'of', 'strings']}
495
+ </div>
496
+ </div>
497
+ );
498
+
499
+ const codeInstance = new Code({ children: complexChildren });
500
+
501
+ expect(() => {
502
+ const serialized = codeInstance.toJson();
503
+ expect(typeof serialized.children).toBe('string');
504
+ }).not.toThrow();
505
+ });
506
+ });
507
+ });