@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,586 @@
1
+ /**
2
+ * Cross-Browser Compatibility Tests for Component Serialization
3
+ *
4
+ * Tests serialization system behavior across different JavaScript engines,
5
+ * browser environments, and runtime conditions to ensure consistent
6
+ * functionality regardless of platform.
7
+ *
8
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
9
+ */
10
+
11
+ import React, { ReactElement } from 'react';
12
+ import { ComponentTransformer } from '../ComponentTransformer';
13
+ import { Serializable, SerializableConstructor } from '../../types/Serializable';
14
+
15
+ // Mock different browser environments
16
+ interface BrowserEnvironment {
17
+ name: string;
18
+ userAgent: string;
19
+ jsonSupport: {
20
+ parse: typeof JSON.parse;
21
+ stringify: typeof JSON.stringify;
22
+ };
23
+ features: {
24
+ es6: boolean;
25
+ weakMap: boolean;
26
+ symbol: boolean;
27
+ proxy: boolean;
28
+ };
29
+ }
30
+
31
+ // Browser environment simulations
32
+ const browserEnvironments: BrowserEnvironment[] = [
33
+ {
34
+ name: 'Chrome Latest',
35
+ userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
36
+ jsonSupport: { parse: JSON.parse, stringify: JSON.stringify },
37
+ features: { es6: true, weakMap: true, symbol: true, proxy: true }
38
+ },
39
+ {
40
+ name: 'Firefox Latest',
41
+ userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/120.0',
42
+ jsonSupport: { parse: JSON.parse, stringify: JSON.stringify },
43
+ features: { es6: true, weakMap: true, symbol: true, proxy: true }
44
+ },
45
+ {
46
+ name: 'Safari Latest',
47
+ userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Version/17.0 Safari/537.36',
48
+ jsonSupport: { parse: JSON.parse, stringify: JSON.stringify },
49
+ features: { es6: true, weakMap: true, symbol: true, proxy: true }
50
+ },
51
+ {
52
+ name: 'Edge Latest',
53
+ userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
54
+ jsonSupport: { parse: JSON.parse, stringify: JSON.stringify },
55
+ features: { es6: true, weakMap: true, symbol: true, proxy: true }
56
+ }
57
+ ];
58
+
59
+ // Test component for cross-browser testing
60
+ class CrossBrowserTestComponent implements Serializable {
61
+ constructor(public props: {
62
+ text?: string;
63
+ number?: number;
64
+ boolean?: boolean;
65
+ array?: any[];
66
+ object?: Record<string, any>;
67
+ date?: string;
68
+ unicode?: string;
69
+ specialChars?: string;
70
+ }) {}
71
+
72
+ static fromJson(jsonData: any): ReactElement {
73
+ return React.createElement('div', {
74
+ 'data-testid': 'cross-browser-test',
75
+ 'data-text': jsonData.text,
76
+ 'data-number': jsonData.number,
77
+ 'data-boolean': jsonData.boolean,
78
+ 'data-array': jsonData.array ? JSON.stringify(jsonData.array) : undefined,
79
+ 'data-object': jsonData.object ? JSON.stringify(jsonData.object) : undefined,
80
+ 'data-date': jsonData.date,
81
+ 'data-unicode': jsonData.unicode,
82
+ 'data-special-chars': jsonData.specialChars
83
+ }, [
84
+ jsonData.text ? React.createElement('span', { key: 'text' }, jsonData.text) : null,
85
+ jsonData.number !== undefined ? React.createElement('span', { key: 'number' }, jsonData.number.toString()) : null,
86
+ jsonData.boolean !== undefined ? React.createElement('span', { key: 'boolean' }, jsonData.boolean.toString()) : null,
87
+ jsonData.unicode ? React.createElement('span', { key: 'unicode' }, jsonData.unicode) : null
88
+ ].filter(Boolean));
89
+ }
90
+
91
+ toJson(): any {
92
+ return {
93
+ text: this.props.text,
94
+ number: this.props.number,
95
+ boolean: this.props.boolean,
96
+ array: this.props.array,
97
+ object: this.props.object,
98
+ date: this.props.date,
99
+ unicode: this.props.unicode,
100
+ specialChars: this.props.specialChars
101
+ };
102
+ }
103
+ }
104
+
105
+ describe('Cross-Browser Compatibility Tests', () => {
106
+ beforeEach(() => {
107
+ ComponentTransformer.clearRegistry();
108
+ ComponentTransformer.registerComponent('CrossBrowserTest', CrossBrowserTestComponent as SerializableConstructor);
109
+ });
110
+
111
+ afterEach(() => {
112
+ ComponentTransformer.clearRegistry();
113
+ });
114
+
115
+ describe('JSON Parsing and Serialization', () => {
116
+ it('should handle JSON parsing consistently across environments', () => {
117
+ const testData = {
118
+ tag: 'CrossBrowserTest',
119
+ version: '1.0.0',
120
+ data: {
121
+ text: 'Hello World',
122
+ number: 42,
123
+ boolean: true,
124
+ array: [1, 2, 3, 'four', true, null],
125
+ object: { nested: 'value', deep: { deeper: 'deepValue' } }
126
+ }
127
+ };
128
+
129
+ browserEnvironments.forEach(env => {
130
+ // Test JSON parsing with each environment's parser
131
+ const jsonString = env.jsonSupport.stringify(testData);
132
+ expect(() => {
133
+ const parsed = env.jsonSupport.parse(jsonString);
134
+ const result = ComponentTransformer.deserialize(parsed);
135
+ expect(React.isValidElement(result)).toBe(true);
136
+ }).not.toThrow();
137
+ });
138
+ });
139
+
140
+ it('should handle special JSON edge cases consistently', () => {
141
+ const edgeCases = [
142
+ { name: 'null', value: null },
143
+ { name: 'empty object', value: {} },
144
+ { name: 'empty array', value: [] },
145
+ { name: 'zero', value: 0 },
146
+ { name: 'false', value: false },
147
+ { name: 'empty string', value: '' },
148
+ { name: 'whitespace string', value: ' \n\t ' },
149
+ ];
150
+
151
+ edgeCases.forEach(({ name, value }) => {
152
+ const testData = {
153
+ tag: 'CrossBrowserTest',
154
+ version: '1.0.0',
155
+ data: { [name.replace(/\s+/g, '_')]: value }
156
+ };
157
+
158
+ browserEnvironments.forEach(env => {
159
+ expect(() => {
160
+ const jsonString = env.jsonSupport.stringify(testData);
161
+ const parsed = env.jsonSupport.parse(jsonString);
162
+ const result = ComponentTransformer.deserialize(parsed);
163
+ expect(React.isValidElement(result)).toBe(true);
164
+ }).not.toThrow(`${name} should work in ${env.name}`);
165
+ });
166
+ });
167
+ });
168
+
169
+ it('should handle large numbers consistently', () => {
170
+ const numberTests = [
171
+ { name: 'small integer', value: 42 },
172
+ { name: 'large integer', value: 9007199254740991 }, // Number.MAX_SAFE_INTEGER
173
+ { name: 'small float', value: 3.14159 },
174
+ { name: 'very small float', value: 0.000000001 },
175
+ { name: 'negative number', value: -123456.789 },
176
+ { name: 'zero', value: 0 },
177
+ { name: 'negative zero', value: -0 }
178
+ ];
179
+
180
+ numberTests.forEach(({ name, value }) => {
181
+ const testData = {
182
+ tag: 'CrossBrowserTest',
183
+ version: '1.0.0',
184
+ data: { number: value }
185
+ };
186
+
187
+ browserEnvironments.forEach(env => {
188
+ const jsonString = env.jsonSupport.stringify(testData);
189
+ const parsed = env.jsonSupport.parse(jsonString);
190
+ const result = ComponentTransformer.deserialize(parsed);
191
+
192
+ expect(React.isValidElement(result)).toBe(true);
193
+
194
+ const element = result as ReactElement;
195
+ const numberValue = parseFloat(element.props['data-number']);
196
+
197
+ if (name === 'negative zero') {
198
+ // Negative zero becomes positive zero in JSON
199
+ expect(numberValue).toBe(0);
200
+ } else {
201
+ expect(numberValue).toBeCloseTo(value, 10);
202
+ }
203
+ });
204
+ });
205
+ });
206
+ });
207
+
208
+ describe('Unicode and Character Encoding', () => {
209
+ it('should handle Unicode characters consistently', () => {
210
+ const unicodeTests = [
211
+ { name: 'emoji', text: '🚀🎉💻🌟⭐' },
212
+ { name: 'chinese', text: '你好世界' },
213
+ { name: 'arabic', text: 'مرحبا بالعالم' },
214
+ { name: 'russian', text: 'Привет мир' },
215
+ { name: 'greek', text: 'Γεια σου κόσμε' },
216
+ { name: 'mathematical', text: '∑∏∆√∞≈≠±×÷' },
217
+ { name: 'currency', text: '$€£¥₹₿' },
218
+ { name: 'mixed', text: 'Hello 世界 🌍 مرحبا Привет!' }
219
+ ];
220
+
221
+ unicodeTests.forEach(({ name, text }) => {
222
+ const testData = {
223
+ tag: 'CrossBrowserTest',
224
+ version: '1.0.0',
225
+ data: { unicode: text }
226
+ };
227
+
228
+ browserEnvironments.forEach(env => {
229
+ const jsonString = env.jsonSupport.stringify(testData);
230
+ const parsed = env.jsonSupport.parse(jsonString);
231
+ const result = ComponentTransformer.deserialize(parsed);
232
+
233
+ expect(React.isValidElement(result)).toBe(true);
234
+
235
+ const element = result as ReactElement;
236
+ expect(element.props['data-unicode']).toBe(text);
237
+ });
238
+ });
239
+ });
240
+
241
+ it('should handle special characters and escaping', () => {
242
+ const specialCharTests = [
243
+ { name: 'quotes', text: 'He said "Hello \'World\'"' },
244
+ { name: 'backslashes', text: 'C:\\Users\\Name\\File.txt' },
245
+ { name: 'control chars', text: 'Line 1\nLine 2\tTabbed\rCarriage Return' },
246
+ { name: 'html entities', text: '<script>alert("xss")</script>&lt;&gt;&amp;' },
247
+ { name: 'json-like', text: '{"fake": "json", "array": [1,2,3]}' },
248
+ { name: 'regex special', text: '^$.*+?()[]{}|\\' }
249
+ ];
250
+
251
+ specialCharTests.forEach(({ name, text }) => {
252
+ const testData = {
253
+ tag: 'CrossBrowserTest',
254
+ version: '1.0.0',
255
+ data: { specialChars: text }
256
+ };
257
+
258
+ browserEnvironments.forEach(env => {
259
+ expect(() => {
260
+ const jsonString = env.jsonSupport.stringify(testData);
261
+ const parsed = env.jsonSupport.parse(jsonString);
262
+ const result = ComponentTransformer.deserialize(parsed);
263
+
264
+ expect(React.isValidElement(result)).toBe(true);
265
+
266
+ const element = result as ReactElement;
267
+ expect(element.props['data-special-chars']).toBe(text);
268
+ }).not.toThrow(`${name} should work in ${env.name}`);
269
+ });
270
+ });
271
+ });
272
+ });
273
+
274
+ describe('Date and Time Handling', () => {
275
+ it('should handle date strings consistently', () => {
276
+ const dateTests = [
277
+ { name: 'ISO string', date: '2025-01-01T12:00:00.000Z' },
278
+ { name: 'ISO with timezone', date: '2025-01-01T12:00:00+05:30' },
279
+ { name: 'short date', date: '2025-01-01' },
280
+ { name: 'human readable', date: 'January 1, 2025' },
281
+ { name: 'timestamp string', date: '1735732800000' }
282
+ ];
283
+
284
+ dateTests.forEach(({ name, date }) => {
285
+ const testData = {
286
+ tag: 'CrossBrowserTest',
287
+ version: '1.0.0',
288
+ data: { date }
289
+ };
290
+
291
+ browserEnvironments.forEach(env => {
292
+ expect(() => {
293
+ const jsonString = env.jsonSupport.stringify(testData);
294
+ const parsed = env.jsonSupport.parse(jsonString);
295
+ const result = ComponentTransformer.deserialize(parsed);
296
+
297
+ expect(React.isValidElement(result)).toBe(true);
298
+
299
+ const element = result as ReactElement;
300
+ expect(element.props['data-date']).toBe(date);
301
+ }).not.toThrow(`${name} should work in ${env.name}`);
302
+ });
303
+ });
304
+ });
305
+ });
306
+
307
+ describe('Array and Object Handling', () => {
308
+ it('should handle complex nested structures consistently', () => {
309
+ const nestedTests = [
310
+ {
311
+ name: 'deeply nested object',
312
+ data: {
313
+ level1: {
314
+ level2: {
315
+ level3: {
316
+ level4: {
317
+ value: 'deep value'
318
+ }
319
+ }
320
+ }
321
+ }
322
+ }
323
+ },
324
+ {
325
+ name: 'mixed array types',
326
+ data: {
327
+ array: [
328
+ 'string',
329
+ 42,
330
+ true,
331
+ null,
332
+ { nested: 'object' },
333
+ ['nested', 'array'],
334
+ undefined // Will be converted to null in JSON
335
+ ]
336
+ }
337
+ },
338
+ {
339
+ name: 'sparse array',
340
+ data: {
341
+ sparse: [1, , , 4, , 6] // Sparse array with holes
342
+ }
343
+ }
344
+ ];
345
+
346
+ nestedTests.forEach(({ name, data }) => {
347
+ const testData = {
348
+ tag: 'CrossBrowserTest',
349
+ version: '1.0.0',
350
+ data
351
+ };
352
+
353
+ browserEnvironments.forEach(env => {
354
+ expect(() => {
355
+ const jsonString = env.jsonSupport.stringify(testData);
356
+ const parsed = env.jsonSupport.parse(jsonString);
357
+ const result = ComponentTransformer.deserialize(parsed);
358
+
359
+ expect(React.isValidElement(result)).toBe(true);
360
+ }).not.toThrow(`${name} should work in ${env.name}`);
361
+ });
362
+ });
363
+ });
364
+
365
+ it('should handle object property order consistently', () => {
366
+ const testData = {
367
+ tag: 'CrossBrowserTest',
368
+ version: '1.0.0',
369
+ data: {
370
+ z_property: 'last',
371
+ a_property: 'first',
372
+ m_property: 'middle'
373
+ }
374
+ };
375
+
376
+ browserEnvironments.forEach(env => {
377
+ const jsonString = env.jsonSupport.stringify(testData);
378
+ const parsed = env.jsonSupport.parse(jsonString);
379
+ const result = ComponentTransformer.deserialize(parsed);
380
+
381
+ expect(React.isValidElement(result)).toBe(true);
382
+
383
+ // Property order might differ, but values should be preserved
384
+ const element = result as ReactElement;
385
+ const objectData = JSON.parse(element.props['data-object'] || '{}');
386
+ expect(objectData.z_property).toBe('last');
387
+ expect(objectData.a_property).toBe('first');
388
+ expect(objectData.m_property).toBe('middle');
389
+ });
390
+ });
391
+ });
392
+
393
+ describe('Error Handling Consistency', () => {
394
+ it('should handle malformed JSON consistently', () => {
395
+ const malformedJsonTests = [
396
+ '{"unclosed": object',
397
+ '{key: "missing quotes"}',
398
+ '[1, 2, 3,]', // Trailing comma
399
+ '{"duplicate": "key1", "duplicate": "key2"}' // Actually valid JSON
400
+ ];
401
+
402
+ malformedJsonTests.forEach((malformedJson, index) => {
403
+ if (index === 3) return; // Skip the valid JSON case
404
+
405
+ browserEnvironments.forEach(env => {
406
+ expect(() => {
407
+ env.jsonSupport.parse(malformedJson);
408
+ }).toThrow();
409
+
410
+ expect(() => {
411
+ ComponentTransformer.deserialize(malformedJson);
412
+ }).toThrow(/Invalid JSON input/);
413
+ });
414
+ });
415
+ });
416
+
417
+ it('should handle component errors consistently', () => {
418
+ const invalidComponent = {
419
+ tag: 'NonExistentComponent',
420
+ version: '1.0.0',
421
+ data: {}
422
+ };
423
+
424
+ browserEnvironments.forEach(env => {
425
+ expect(() => {
426
+ const jsonString = env.jsonSupport.stringify(invalidComponent);
427
+ const parsed = env.jsonSupport.parse(jsonString);
428
+ ComponentTransformer.deserialize(parsed);
429
+ }).toThrow('Unknown component: NonExistentComponent');
430
+ });
431
+ });
432
+ });
433
+
434
+ describe('Performance Consistency', () => {
435
+ it('should maintain consistent performance across browsers', () => {
436
+ const largeTestData = {
437
+ tag: 'CrossBrowserTest',
438
+ version: '1.0.0',
439
+ data: {
440
+ array: Array.from({ length: 1000 }, (_, i) => ({
441
+ id: i,
442
+ text: `Item ${i}`,
443
+ nested: { value: i * 2 }
444
+ }))
445
+ }
446
+ };
447
+
448
+ const performanceResults: { [browser: string]: number } = {};
449
+
450
+ browserEnvironments.forEach(env => {
451
+ const startTime = performance.now();
452
+
453
+ const jsonString = env.jsonSupport.stringify(largeTestData);
454
+ const parsed = env.jsonSupport.parse(jsonString);
455
+ const result = ComponentTransformer.deserialize(parsed);
456
+
457
+ const endTime = performance.now();
458
+ performanceResults[env.name] = endTime - startTime;
459
+
460
+ expect(React.isValidElement(result)).toBe(true);
461
+ });
462
+
463
+ // Verify that performance is within reasonable bounds
464
+ const times = Object.values(performanceResults);
465
+ const avgTime = times.reduce((a, b) => a + b, 0) / times.length;
466
+ const maxTime = Math.max(...times);
467
+ const minTime = Math.min(...times);
468
+
469
+ console.log('Cross-browser performance:', performanceResults);
470
+
471
+ // No browser should be more than 3x slower than the fastest
472
+ expect(maxTime / minTime).toBeLessThan(3);
473
+
474
+ // Average time should be reasonable (< 100ms for this test)
475
+ expect(avgTime).toBeLessThan(100);
476
+ });
477
+ });
478
+
479
+ describe('Memory Usage Consistency', () => {
480
+ it('should handle memory usage consistently', () => {
481
+ const memoryTestData = Array.from({ length: 100 }, (_, i) => ({
482
+ tag: 'CrossBrowserTest',
483
+ version: '1.0.0',
484
+ data: {
485
+ text: `Memory test item ${i}`,
486
+ array: Array.from({ length: 100 }, (_, j) => `item-${i}-${j}`)
487
+ }
488
+ }));
489
+
490
+ browserEnvironments.forEach(env => {
491
+ const initialMemory = process.memoryUsage().heapUsed;
492
+
493
+ // Process the data multiple times
494
+ for (let iteration = 0; iteration < 10; iteration++) {
495
+ memoryTestData.forEach(testItem => {
496
+ const jsonString = env.jsonSupport.stringify(testItem);
497
+ const parsed = env.jsonSupport.parse(jsonString);
498
+ const result = ComponentTransformer.deserialize(parsed);
499
+
500
+ expect(React.isValidElement(result)).toBe(true);
501
+ });
502
+ }
503
+
504
+ const finalMemory = process.memoryUsage().heapUsed;
505
+ const memoryGrowth = (finalMemory - initialMemory) / (1024 * 1024); // MB
506
+
507
+ // Memory growth should be reasonable (< 50MB for this test)
508
+ expect(memoryGrowth).toBeLessThan(50);
509
+
510
+ console.log(`${env.name} memory growth: ${memoryGrowth.toFixed(2)}MB`);
511
+ });
512
+ });
513
+ });
514
+
515
+ describe('Edge Case Compatibility', () => {
516
+ it('should handle boundary values consistently', () => {
517
+ const boundaryTests = [
518
+ { name: 'max safe integer', value: Number.MAX_SAFE_INTEGER },
519
+ { name: 'min safe integer', value: Number.MIN_SAFE_INTEGER },
520
+ { name: 'max value', value: Number.MAX_VALUE },
521
+ { name: 'min value', value: Number.MIN_VALUE },
522
+ { name: 'positive infinity', value: Number.POSITIVE_INFINITY },
523
+ { name: 'negative infinity', value: Number.NEGATIVE_INFINITY },
524
+ { name: 'NaN', value: Number.NaN }
525
+ ];
526
+
527
+ boundaryTests.forEach(({ name, value }) => {
528
+ const testData = {
529
+ tag: 'CrossBrowserTest',
530
+ version: '1.0.0',
531
+ data: { number: value }
532
+ };
533
+
534
+ browserEnvironments.forEach(env => {
535
+ if (name.includes('infinity') || name === 'NaN') {
536
+ // JSON doesn't support these values - they become null
537
+ expect(() => {
538
+ const jsonString = env.jsonSupport.stringify(testData);
539
+ expect(jsonString).toContain('null');
540
+ }).not.toThrow();
541
+ } else {
542
+ expect(() => {
543
+ const jsonString = env.jsonSupport.stringify(testData);
544
+ const parsed = env.jsonSupport.parse(jsonString);
545
+ const result = ComponentTransformer.deserialize(parsed);
546
+
547
+ expect(React.isValidElement(result)).toBe(true);
548
+ }).not.toThrow(`${name} should work in ${env.name}`);
549
+ }
550
+ });
551
+ });
552
+ });
553
+
554
+ it('should handle string length limits consistently', () => {
555
+ const lengthTests = [
556
+ { name: 'empty string', length: 0 },
557
+ { name: 'short string', length: 10 },
558
+ { name: 'medium string', length: 1000 },
559
+ { name: 'long string', length: 10000 },
560
+ { name: 'very long string', length: 100000 }
561
+ ];
562
+
563
+ lengthTests.forEach(({ name, length }) => {
564
+ const longString = 'x'.repeat(length);
565
+ const testData = {
566
+ tag: 'CrossBrowserTest',
567
+ version: '1.0.0',
568
+ data: { text: longString }
569
+ };
570
+
571
+ browserEnvironments.forEach(env => {
572
+ expect(() => {
573
+ const jsonString = env.jsonSupport.stringify(testData);
574
+ const parsed = env.jsonSupport.parse(jsonString);
575
+ const result = ComponentTransformer.deserialize(parsed);
576
+
577
+ expect(React.isValidElement(result)).toBe(true);
578
+
579
+ const element = result as ReactElement;
580
+ expect(element.props['data-text']).toBe(longString);
581
+ }).not.toThrow(`${name} should work in ${env.name}`);
582
+ });
583
+ });
584
+ });
585
+ });
586
+ });
@@ -0,0 +1,103 @@
1
+ /**
2
+ * MockSerializableComponent - Test helper component implementing new SerializableConstructor interface
3
+ *
4
+ * NOTE: This is not a test file - it's a helper module for testing.
5
+ * Jest should not run this as a test suite.
6
+ *
7
+ * Demonstrates component self-declaration pattern with static tagName and version properties
8
+ * Used for testing the updated ComponentTransformer architecture
9
+ *
10
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
11
+ */
12
+
13
+ import React, { ReactElement } from 'react';
14
+ import { Serializable, SerializableConstructor } from '../../../schemas';
15
+
16
+ /**
17
+ * Mock component implementing the new Serializable interface with self-declaration
18
+ */
19
+ export class MockSerializableComponent implements Serializable {
20
+ static readonly tagName = 'MockComponent';
21
+ static readonly version = '1.0.0';
22
+
23
+ constructor(public props: {
24
+ title?: string;
25
+ content?: string;
26
+ variant?: string;
27
+ children?: React.ReactNode;
28
+ }) {}
29
+
30
+ static fromJson(jsonData: any): ReactElement {
31
+ return React.createElement('div', {
32
+ className: `mock-component ${jsonData.variant || 'default'}`,
33
+ 'data-testid': 'mock-component'
34
+ }, [
35
+ jsonData.title && React.createElement('h3', { key: 'title' }, jsonData.title),
36
+ jsonData.content && React.createElement('p', { key: 'content' }, jsonData.content),
37
+ jsonData.children
38
+ ].filter(Boolean));
39
+ }
40
+
41
+ toJson(): any {
42
+ return {
43
+ title: this.props.title,
44
+ content: this.props.content,
45
+ variant: this.props.variant,
46
+ children: this.props.children
47
+ };
48
+ }
49
+ }
50
+
51
+ // Type assertion to ensure it meets the interface requirements
52
+ export const MockSerializableComponentClass = MockSerializableComponent as unknown as SerializableConstructor;
53
+
54
+ /**
55
+ * Alternative mock component with different tagName and version for testing conflicts
56
+ */
57
+ export class AlternativeMockComponent implements Serializable {
58
+ static readonly tagName = 'AlternativeComponent';
59
+ static readonly version = '2.1.0';
60
+
61
+ constructor(public props: {
62
+ label?: string;
63
+ type?: string;
64
+ active?: boolean;
65
+ }) {}
66
+
67
+ static fromJson(jsonData: any): ReactElement {
68
+ return React.createElement('button', {
69
+ className: `alt-mock ${jsonData.type || 'default'}`,
70
+ 'data-active': jsonData.active,
71
+ 'data-testid': 'alternative-mock'
72
+ }, jsonData.label || 'Alternative Component');
73
+ }
74
+
75
+ toJson(): any {
76
+ return {
77
+ label: this.props.label,
78
+ type: this.props.type,
79
+ active: this.props.active
80
+ };
81
+ }
82
+ }
83
+
84
+ export const AlternativeMockComponentClass = AlternativeMockComponent as unknown as SerializableConstructor;
85
+
86
+ /**
87
+ * Mock component missing required static properties (for error testing)
88
+ */
89
+ export class InvalidMockComponent implements Serializable {
90
+ // Missing static tagName and version properties intentionally
91
+
92
+ constructor(public props: any) {}
93
+
94
+ static fromJson(jsonData: any): ReactElement {
95
+ return React.createElement('div', {}, 'Invalid Component');
96
+ }
97
+
98
+ toJson(): any {
99
+ return {};
100
+ }
101
+ }
102
+
103
+ export const InvalidMockComponentClass = InvalidMockComponent as any; // Intentionally not typed as SerializableConstructor