@qwickapps/react-framework 1.3.5 → 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 (320) hide show
  1. package/README.md +1681 -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,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
+ });