@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.
- package/README.md +1688 -2
- package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts +66 -0
- package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.d.ts +7 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/Html.d.ts +28 -18
- package/dist/components/Html.d.ts.map +1 -1
- package/dist/components/Logo.d.ts +12 -35
- package/dist/components/Logo.d.ts.map +1 -1
- package/dist/components/Markdown.d.ts +18 -13
- package/dist/components/Markdown.d.ts.map +1 -1
- package/dist/components/QwickApp.d.ts +16 -3
- package/dist/components/QwickApp.d.ts.map +1 -1
- package/dist/components/QwickIcon.d.ts +23 -0
- package/dist/components/QwickIcon.d.ts.map +1 -0
- package/dist/components/SafeSpan.d.ts +12 -5
- package/dist/components/SafeSpan.d.ts.map +1 -1
- package/dist/components/Scaffold.d.ts.map +1 -1
- package/dist/components/base/ModelView.d.ts +101 -0
- package/dist/components/base/ModelView.d.ts.map +1 -0
- package/dist/components/base/index.d.ts +11 -0
- package/dist/components/base/index.d.ts.map +1 -0
- package/dist/components/blocks/Article.d.ts +12 -2
- package/dist/components/blocks/Article.d.ts.map +1 -1
- package/dist/components/blocks/Code.d.ts +13 -2
- package/dist/components/blocks/Code.d.ts.map +1 -1
- package/dist/components/blocks/Content.d.ts.map +1 -1
- package/dist/components/blocks/CoverImageHeader.d.ts.map +1 -1
- package/dist/components/blocks/FeatureCard.d.ts.map +1 -1
- package/dist/components/blocks/FeatureGrid.d.ts.map +1 -1
- package/dist/components/blocks/Footer.d.ts.map +1 -1
- package/dist/components/blocks/HeroBlock.d.ts +27 -13
- package/dist/components/blocks/HeroBlock.d.ts.map +1 -1
- package/dist/components/blocks/Image.d.ts +41 -0
- package/dist/components/blocks/Image.d.ts.map +1 -0
- package/dist/components/blocks/PageBannerHeader.d.ts.map +1 -1
- package/dist/components/blocks/ProductCard.d.ts.map +1 -1
- package/dist/components/blocks/Section.d.ts +16 -2
- package/dist/components/blocks/Section.d.ts.map +1 -1
- package/dist/components/blocks/Text.d.ts +41 -0
- package/dist/components/blocks/Text.d.ts.map +1 -0
- package/dist/components/blocks/index.d.ts +4 -0
- package/dist/components/blocks/index.d.ts.map +1 -1
- package/dist/components/buttons/Button.d.ts +23 -7
- package/dist/components/buttons/Button.d.ts.map +1 -1
- package/dist/components/forms/FormBlock.d.ts +19 -13
- package/dist/components/forms/FormBlock.d.ts.map +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/input/ChoiceInputField.d.ts +17 -11
- package/dist/components/input/ChoiceInputField.d.ts.map +1 -1
- package/dist/components/input/HtmlInputField.d.ts +17 -11
- package/dist/components/input/HtmlInputField.d.ts.map +1 -1
- package/dist/components/input/SelectInputField.d.ts +16 -10
- package/dist/components/input/SelectInputField.d.ts.map +1 -1
- package/dist/components/input/SwitchInputField.d.ts +16 -10
- package/dist/components/input/SwitchInputField.d.ts.map +1 -1
- package/dist/components/input/TextField.d.ts.map +1 -1
- package/dist/components/input/TextInputField.d.ts +16 -11
- package/dist/components/input/TextInputField.d.ts.map +1 -1
- package/dist/components/layout/GridCell.d.ts +23 -6
- package/dist/components/layout/GridCell.d.ts.map +1 -1
- package/dist/components/layout/GridLayout.d.ts +24 -23
- package/dist/components/layout/GridLayout.d.ts.map +1 -1
- package/dist/components/pages/FormPage.d.ts.map +1 -1
- package/dist/components/pages/Page.d.ts +49 -87
- package/dist/components/pages/Page.d.ts.map +1 -1
- package/dist/components/pages/index.d.ts +2 -2
- package/dist/components/pages/index.d.ts.map +1 -1
- package/dist/config/AppConfig.d.ts +49 -0
- package/dist/config/AppConfig.d.ts.map +1 -0
- package/dist/config/AppConfigBuilder.d.ts +75 -0
- package/dist/config/AppConfigBuilder.d.ts.map +1 -0
- package/dist/config/index.d.ts +13 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/types.d.ts +130 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.esm.js +451 -0
- package/dist/config.js +455 -0
- package/dist/contexts/PrintModeContext.d.ts +27 -0
- package/dist/contexts/PrintModeContext.d.ts.map +1 -0
- package/dist/contexts/QwickAppContext.d.ts +2 -2
- package/dist/contexts/QwickAppContext.d.ts.map +1 -1
- package/dist/contexts/ThemeContext.d.ts.map +1 -1
- package/dist/contexts/index.d.ts +2 -0
- package/dist/contexts/index.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/usePrintMode.d.ts +39 -0
- package/dist/hooks/usePrintMode.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +20722 -16021
- package/dist/index.js +20725 -16010
- package/dist/schemas/CodeSchema.d.ts +2 -1
- package/dist/schemas/CodeSchema.d.ts.map +1 -1
- package/dist/schemas/CollapsibleLayoutSchema.d.ts +2 -1
- package/dist/schemas/CollapsibleLayoutSchema.d.ts.map +1 -1
- package/dist/schemas/ContentSchema.d.ts +2 -1
- package/dist/schemas/ContentSchema.d.ts.map +1 -1
- package/dist/schemas/GridCellSchema.d.ts +25 -0
- package/dist/schemas/GridCellSchema.d.ts.map +1 -0
- package/dist/schemas/GridLayoutSchema.d.ts +23 -0
- package/dist/schemas/GridLayoutSchema.d.ts.map +1 -0
- package/dist/schemas/HtmlSchema.d.ts +14 -0
- package/dist/schemas/HtmlSchema.d.ts.map +1 -0
- package/dist/schemas/ImageSchema.d.ts +32 -0
- package/dist/schemas/ImageSchema.d.ts.map +1 -0
- package/dist/schemas/LogoSchema.d.ts +35 -0
- package/dist/schemas/LogoSchema.d.ts.map +1 -0
- package/dist/schemas/MarkdownSchema.d.ts +14 -0
- package/dist/schemas/MarkdownSchema.d.ts.map +1 -0
- package/dist/schemas/PageTemplateSchema.d.ts +31 -0
- package/dist/schemas/PageTemplateSchema.d.ts.map +1 -0
- package/dist/schemas/PrintConfigSchema.d.ts +31 -0
- package/dist/schemas/PrintConfigSchema.d.ts.map +1 -0
- package/dist/schemas/SectionSchema.d.ts +2 -1
- package/dist/schemas/SectionSchema.d.ts.map +1 -1
- package/dist/schemas/TextSchema.d.ts +37 -0
- package/dist/schemas/TextSchema.d.ts.map +1 -0
- package/dist/schemas/ViewModelSchema.d.ts +23 -0
- package/dist/schemas/ViewModelSchema.d.ts.map +1 -0
- package/dist/schemas/index.d.ts +15 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/transformers/ComponentTransformer.d.ts +116 -0
- package/dist/schemas/transformers/ComponentTransformer.d.ts.map +1 -0
- package/dist/schemas/transformers/ReactNodeTransformer.d.ts +53 -0
- package/dist/schemas/transformers/ReactNodeTransformer.d.ts.map +1 -0
- package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts +66 -0
- package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts.map +1 -0
- package/dist/schemas/transformers/registry.d.ts +15 -0
- package/dist/schemas/transformers/registry.d.ts.map +1 -0
- package/dist/schemas/types/Serializable.d.ts +46 -0
- package/dist/schemas/types/Serializable.d.ts.map +1 -0
- package/dist/utils/htmlTransform.d.ts.map +1 -1
- package/dist/utils/reactUtils.d.ts +12 -3
- package/dist/utils/reactUtils.d.ts.map +1 -1
- package/package.json +17 -3
- package/src/{components/__tests__ → __tests__/components}/AccessibilityProvider.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Article.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Breadcrumbs.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Button.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/CardListGrid.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/ChoiceInputField.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Code.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Content.integration.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Content.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/CoverImageHeader.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/ErrorBoundary.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/FeatureCard.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/FeatureGrid.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/FeatureGrid.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/Footer.test.tsx +4 -4
- package/src/{components/__tests__ → __tests__/components}/FormBlock.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/HeroBlock.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/HeroBlock.test.tsx +233 -7
- package/src/{components/__tests__ → __tests__/components}/Html.test.tsx +11 -2
- package/src/{components/__tests__ → __tests__/components}/HtmlInputField.test.tsx +3 -3
- package/src/__tests__/components/Logo.test.js +3 -3
- package/src/{components/__tests__ → __tests__/components}/Markdown.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/PageBannerHeader.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/PaletteSwitcher.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/ProductCard.test.tsx +4 -4
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.simple.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Section.integration.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Section.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/SelectInputField.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/TextInputField.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/ThemeSwitcher.test.tsx +3 -3
- package/src/__tests__/components/base/ModelView.test.tsx +220 -0
- package/src/__tests__/components/blocks/Code.performance.test.tsx +625 -0
- package/src/__tests__/components/blocks/Code.serialization.test.tsx +507 -0
- package/src/__tests__/components/blocks/HeroBlock.serialization.test.tsx +414 -0
- package/src/__tests__/components/blocks/Image.serialization.test.tsx +257 -0
- package/src/__tests__/components/blocks/Section.serialization.test.tsx +553 -0
- package/src/__tests__/components/blocks/Text.performance.test.tsx +442 -0
- package/src/__tests__/components/blocks/Text.serialization.test.tsx +491 -0
- package/src/__tests__/components/buttons/Button.serialization.test.tsx +443 -0
- package/src/__tests__/components/input/FormComponents.serialization.test.tsx +482 -0
- package/src/__tests__/components/input/SelectInputField.serialization.test.tsx +439 -0
- package/src/__tests__/components/input/TextInputField.serialization.test.tsx +359 -0
- package/src/{components/layout/CollapsibleLayout/__tests__ → __tests__/components/layout}/CollapsibleLayout.test.tsx +4 -4
- package/src/__tests__/components/layout/GridCell.serialization.test.tsx +403 -0
- package/src/__tests__/components/layout/GridLayout.serialization.test.tsx +311 -0
- package/src/__tests__/hooks/usePrintMode.test.ts +89 -0
- package/src/__tests__/schemas/PageTemplateSchema.test.ts +161 -0
- package/src/__tests__/schemas/PrintConfigSchema.test.ts +127 -0
- package/src/__tests__/schemas/ViewModelSchema.test.ts +80 -0
- package/src/__tests__/schemas/transformers/ComponentSerializationPatterns.test.tsx +602 -0
- package/src/__tests__/schemas/transformers/ComponentTransformer.htmlPatterns.test.ts +301 -0
- package/src/__tests__/schemas/transformers/ComponentTransformer.test.ts +521 -0
- package/src/__tests__/schemas/transformers/CrossBrowserCompatibility.test.ts +586 -0
- package/src/__tests__/schemas/transformers/MockSerializableComponent.ts +103 -0
- package/src/__tests__/schemas/transformers/RealWorldScenarios.test.tsx +1165 -0
- package/src/__tests__/schemas/transformers/SerializationErrorHandling.test.ts +602 -0
- package/src/__tests__/schemas/transformers/SerializationIntegration.test.tsx +691 -0
- package/src/__tests__/schemas/transformers/SerializationPerformance.test.ts +460 -0
- package/src/__tests__/schemas/transformers/TestAutomation.test.ts +597 -0
- package/src/{utils/__tests__ → __tests__/utils}/nested-dom-fix.test.tsx +1 -1
- package/src/components/ErrorBoundary.tsx +8 -8
- package/src/components/Html.tsx +147 -44
- package/src/components/Logo.tsx +198 -100
- package/src/components/Markdown.tsx +125 -16
- package/src/components/QwickApp.tsx +64 -31
- package/src/components/QwickIcon.tsx +59 -0
- package/src/components/SafeSpan.tsx +65 -10
- package/src/components/Scaffold.tsx +2 -8
- package/src/components/base/ModelView.tsx +199 -0
- package/src/components/base/index.ts +11 -0
- package/src/components/blocks/Article.tsx +57 -18
- package/src/components/blocks/Code.md +529 -0
- package/src/components/blocks/Code.tsx +102 -15
- package/src/components/blocks/Content.tsx +25 -77
- package/src/components/blocks/CoverImageHeader.tsx +9 -4
- package/src/components/blocks/FeatureCard.tsx +1 -2
- package/src/components/blocks/FeatureGrid.tsx +19 -1
- package/src/components/blocks/Footer.tsx +13 -1
- package/src/components/blocks/HeroBlock.tsx +87 -20
- package/src/components/blocks/Image.tsx +395 -0
- package/src/components/blocks/PageBannerHeader.tsx +14 -12
- package/src/components/blocks/ProductCard.tsx +51 -52
- package/src/components/blocks/Section.tsx +113 -8
- package/src/components/blocks/Text.tsx +285 -0
- package/src/components/blocks/index.ts +4 -0
- package/src/components/buttons/Button.tsx +184 -15
- package/src/components/forms/FormBlock.tsx +70 -17
- package/src/components/index.ts +5 -0
- package/src/components/input/ChoiceInputField.tsx +48 -18
- package/src/components/input/HtmlInputField.tsx +48 -18
- package/src/components/input/SelectInputField.tsx +48 -16
- package/src/components/input/SwitchInputField.tsx +48 -17
- package/src/components/input/TextField.tsx +41 -1
- package/src/components/input/TextInputField.tsx +52 -18
- package/src/components/layout/GridCell.tsx +118 -9
- package/src/components/layout/GridLayout.tsx +125 -24
- package/src/components/pages/FormPage.tsx +0 -1
- package/src/components/pages/Page.css +304 -332
- package/src/components/pages/Page.tsx +307 -255
- package/src/components/pages/index.ts +2 -2
- package/src/config/AppConfig.ts +133 -0
- package/src/config/AppConfigBuilder.ts +421 -0
- package/src/config/__tests__/AppConfig.test.ts +385 -0
- package/src/config/__tests__/AppConfigBuilder.test.ts +432 -0
- package/src/config/index.ts +24 -0
- package/src/config/types.ts +170 -0
- package/src/config.ts +25 -0
- package/src/contexts/PrintModeContext.tsx +332 -0
- package/src/contexts/QwickAppContext.tsx +2 -2
- package/src/contexts/ThemeContext.tsx +1 -2
- package/src/contexts/index.ts +2 -0
- package/src/hooks/index.ts +5 -1
- package/src/hooks/usePrintMode.ts +73 -0
- package/src/index.ts +3 -0
- package/src/schemas/CodeSchema.ts +3 -3
- package/src/schemas/CollapsibleLayoutSchema.ts +2 -1
- package/src/schemas/ContentSchema.ts +2 -1
- package/src/schemas/GridCellSchema.ts +164 -0
- package/src/schemas/GridLayoutSchema.ts +133 -0
- package/src/schemas/HtmlSchema.ts +47 -0
- package/src/schemas/ImageSchema.ts +235 -0
- package/src/schemas/LogoSchema.ts +241 -0
- package/src/schemas/MarkdownSchema.ts +47 -0
- package/src/schemas/PageTemplateSchema.ts +186 -0
- package/src/schemas/PrintConfigSchema.ts +207 -0
- package/src/schemas/README.md +661 -0
- package/src/schemas/SectionSchema.ts +2 -1
- package/src/schemas/TextSchema.ts +329 -0
- package/src/schemas/ViewModelSchema.ts +115 -0
- package/src/schemas/index.ts +21 -2
- package/src/schemas/transformers/ComponentTransformer.ts +403 -0
- package/src/schemas/transformers/ReactNodeTransformer.ts +236 -0
- package/src/schemas/transformers/registry.ts +72 -0
- package/src/schemas/types/Serializable.ts +51 -0
- package/src/stories/AccessibilityProvider.stories.tsx +253 -253
- package/src/stories/Article.stories.tsx +433 -433
- package/src/stories/Button.stories.tsx +1 -1
- package/src/stories/CardListGrid.stories.tsx +451 -451
- package/src/stories/ChoiceInputField.stories.tsx +503 -503
- package/src/stories/Code.stories.tsx +1 -1
- package/src/stories/CollapsibleLayout.stories.tsx +1414 -1414
- package/src/stories/Content.stories.tsx +393 -393
- package/src/stories/CoverImageHeader.stories.tsx +701 -701
- package/src/stories/DataBinding.advanced.stories.tsx +432 -432
- package/src/stories/DataProvider.stories.tsx +1192 -1192
- package/src/stories/FeatureCard.stories.tsx +557 -557
- package/src/stories/FeatureGrid.stories.tsx +594 -594
- package/src/stories/Footer.stories.tsx +640 -640
- package/src/stories/FormBlock.stories.tsx +760 -760
- package/src/stories/FormComponents.stories.tsx +349 -541
- package/src/stories/GridCell.stories.tsx +417 -0
- package/src/stories/GridLayout.stories.tsx +353 -0
- package/src/stories/HeroBlock.stories.tsx +862 -373
- package/src/stories/HtmlInputField.stories.tsx +474 -474
- package/src/stories/Image.stories.tsx +819 -0
- package/src/stories/Introduction.stories.tsx +667 -667
- package/src/stories/LayoutBlocks.stories.tsx +324 -324
- package/src/stories/Logo.stories.tsx +165 -6
- package/src/stories/Markdown.stories.tsx +137 -137
- package/src/stories/ModelView.stories.tsx +477 -0
- package/src/stories/Page.stories.tsx +688 -688
- package/src/stories/PageBannerHeader.stories.tsx +864 -864
- package/src/stories/PaletteSwitcher.stories.tsx +119 -119
- package/src/stories/ProductCard.stories.tsx +424 -424
- package/src/stories/QwickApp.stories.tsx +368 -368
- package/src/stories/ResponsiveMenu.stories.tsx +249 -249
- package/src/stories/SafeSpan.stories.tsx +531 -531
- package/src/stories/Section.stories.tsx +90 -2
- package/src/stories/SelectInputField.stories.tsx +524 -524
- package/src/stories/Text.stories.tsx +560 -0
- package/src/stories/TextInputField.stories.tsx +443 -443
- package/src/stories/ThemeSwitcher.stories.tsx +123 -123
- package/src/utils/htmlTransform.tsx +74 -53
- package/src/utils/reactUtils.tsx +57 -6
- package/dist/index.bundled.css +0 -12
- /package/src/{hooks/__tests__ → __tests__/hooks}/useDataBinding.test.tsx.disabled +0 -0
- /package/src/{schemas/__tests__ → __tests__/schemas}/builders.test.ts +0 -0
- /package/src/{utils/__tests__ → __tests__/utils}/createDataDrivenComponent.test.tsx.disabled +0 -0
- /package/src/{utils/__tests__ → __tests__/utils}/htmlTransform.test.tsx +0 -0
- /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
|
+
});
|