@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,439 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SelectInputField Serialization Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests the serialization and deserialization functionality of the SelectInputField component.
|
|
5
|
+
* Ensures that dropdown options and selection state are properly preserved through JSON serialization cycles.
|
|
6
|
+
*
|
|
7
|
+
* Test Coverage:
|
|
8
|
+
* - Basic select field serialization/deserialization
|
|
9
|
+
* - Complex option arrays with value/label pairs
|
|
10
|
+
* - Form validation and error state handling
|
|
11
|
+
* - Disabled options and accessibility features
|
|
12
|
+
* - Performance benchmarks for option-heavy dropdowns
|
|
13
|
+
*
|
|
14
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import React from 'react';
|
|
18
|
+
import { render } from '@testing-library/react';
|
|
19
|
+
import { ComponentTransformer } from '../../../schemas/transformers/ComponentTransformer';
|
|
20
|
+
import { SelectInputField } from '../../../components/input/SelectInputField';
|
|
21
|
+
|
|
22
|
+
// Ensure the component is registered
|
|
23
|
+
import '../../../schemas/transformers/registry';
|
|
24
|
+
|
|
25
|
+
describe('SelectInputField Serialization', () => {
|
|
26
|
+
// Performance tracking
|
|
27
|
+
const performanceData: Array<{ operation: string; duration: number }> = [];
|
|
28
|
+
|
|
29
|
+
afterAll(() => {
|
|
30
|
+
// Log performance summary
|
|
31
|
+
console.log('\n📊 SelectInputField Serialization Performance Summary:');
|
|
32
|
+
performanceData.forEach(({ operation, duration }) => {
|
|
33
|
+
console.log(` • ${operation}: ${duration.toFixed(3)}ms`);
|
|
34
|
+
});
|
|
35
|
+
const avgDuration = performanceData.reduce((sum, { duration }) => sum + duration, 0) / performanceData.length;
|
|
36
|
+
console.log(` • Average: ${avgDuration.toFixed(3)}ms\n`);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const measurePerformance = (operation: string, fn: () => void) => {
|
|
40
|
+
const start = performance.now();
|
|
41
|
+
fn();
|
|
42
|
+
const duration = performance.now() - start;
|
|
43
|
+
performanceData.push({ operation, duration });
|
|
44
|
+
return duration;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
describe('Basic Select Field', () => {
|
|
48
|
+
it('serializes and deserializes basic select field correctly', () => {
|
|
49
|
+
const originalProps = {
|
|
50
|
+
label: 'Country',
|
|
51
|
+
value: 'us',
|
|
52
|
+
options: [
|
|
53
|
+
{ value: 'us', label: 'United States' },
|
|
54
|
+
{ value: 'ca', label: 'Canada' },
|
|
55
|
+
{ value: 'uk', label: 'United Kingdom' }
|
|
56
|
+
],
|
|
57
|
+
required: true,
|
|
58
|
+
placeholder: 'Select a country'
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
let serializedData: any;
|
|
62
|
+
let deserializedElement: React.ReactElement;
|
|
63
|
+
let reserializedData: any;
|
|
64
|
+
|
|
65
|
+
// Test serialization
|
|
66
|
+
const serializationTime = measurePerformance('Basic Serialization', () => {
|
|
67
|
+
const element = <SelectInputField {...originalProps} />;
|
|
68
|
+
const serialized = ComponentTransformer.serialize(element);
|
|
69
|
+
serializedData = JSON.parse(serialized);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
expect(serializedData).toBeDefined();
|
|
73
|
+
expect(serializedData.tag).toBe('SelectInputField');
|
|
74
|
+
expect(serializedData.data.label).toBe(originalProps.label);
|
|
75
|
+
expect(serializedData.data.value).toBe(originalProps.value);
|
|
76
|
+
expect(serializedData.data.required).toBe(originalProps.required);
|
|
77
|
+
expect(serializedData.data.placeholder).toBe(originalProps.placeholder);
|
|
78
|
+
expect(serializedData.data.options).toEqual(originalProps.options);
|
|
79
|
+
|
|
80
|
+
// Test deserialization
|
|
81
|
+
const deserializationTime = measurePerformance('Basic Deserialization', () => {
|
|
82
|
+
deserializedElement = ComponentTransformer.deserialize(JSON.stringify(serializedData)) as React.ReactElement;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(React.isValidElement(deserializedElement)).toBe(true);
|
|
86
|
+
expect(deserializedElement.type).toBe(SelectInputField);
|
|
87
|
+
|
|
88
|
+
// Test re-serialization (round-trip)
|
|
89
|
+
const reserializationTime = measurePerformance('Basic Re-serialization', () => {
|
|
90
|
+
const reserialized = ComponentTransformer.serialize(deserializedElement);
|
|
91
|
+
reserializedData = JSON.parse(reserialized);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
expect(reserializedData).toEqual(serializedData);
|
|
95
|
+
|
|
96
|
+
// Performance assertions
|
|
97
|
+
expect(serializationTime).toBeLessThan(1); // Should be under 1ms
|
|
98
|
+
expect(deserializationTime).toBeLessThan(1);
|
|
99
|
+
expect(reserializationTime).toBeLessThan(1);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('renders serialized select field correctly', () => {
|
|
103
|
+
const originalProps = {
|
|
104
|
+
label: 'Priority Level',
|
|
105
|
+
value: 'high',
|
|
106
|
+
options: [
|
|
107
|
+
{ value: 'low', label: 'Low Priority' },
|
|
108
|
+
{ value: 'medium', label: 'Medium Priority' },
|
|
109
|
+
{ value: 'high', label: 'High Priority' }
|
|
110
|
+
]
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const element = <SelectInputField {...originalProps} />;
|
|
114
|
+
const serialized = ComponentTransformer.serialize(element);
|
|
115
|
+
const serializedData = JSON.parse(serialized);
|
|
116
|
+
const deserializedElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
|
|
117
|
+
|
|
118
|
+
const { getByText, getByDisplayValue } = render(deserializedElement);
|
|
119
|
+
|
|
120
|
+
expect(getByText('Priority Level')).toBeInTheDocument();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('Complex Option Arrays', () => {
|
|
125
|
+
it('serializes complex options with disabled states correctly', () => {
|
|
126
|
+
const originalProps = {
|
|
127
|
+
label: 'Service Plan',
|
|
128
|
+
value: 'pro',
|
|
129
|
+
options: [
|
|
130
|
+
{ value: 'free', label: 'Free Plan', disabled: false },
|
|
131
|
+
{ value: 'starter', label: 'Starter Plan', disabled: false },
|
|
132
|
+
{ value: 'pro', label: 'Professional Plan', disabled: false },
|
|
133
|
+
{ value: 'enterprise', label: 'Enterprise Plan', disabled: true }
|
|
134
|
+
]
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const element = <SelectInputField {...originalProps} />;
|
|
138
|
+
|
|
139
|
+
let serializedData: any;
|
|
140
|
+
measurePerformance('Complex Options Serialization', () => {
|
|
141
|
+
const serialized = ComponentTransformer.serialize(element);
|
|
142
|
+
serializedData = JSON.parse(serialized);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
expect(serializedData.data.options).toHaveLength(4);
|
|
146
|
+
expect(serializedData.data.options[3].disabled).toBe(true);
|
|
147
|
+
expect(serializedData.data.options[0].disabled).toBe(false);
|
|
148
|
+
|
|
149
|
+
const deserializedElement = ComponentTransformer.deserialize(JSON.stringify(serializedData)) as React.ReactElement;
|
|
150
|
+
const reserialized = ComponentTransformer.serialize(deserializedElement);
|
|
151
|
+
const reserializedData = JSON.parse(reserialized);
|
|
152
|
+
|
|
153
|
+
expect(reserializedData.data.options).toEqual(originalProps.options);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('handles numeric values in options correctly', () => {
|
|
157
|
+
const originalProps = {
|
|
158
|
+
label: 'Age Range',
|
|
159
|
+
value: 25,
|
|
160
|
+
options: [
|
|
161
|
+
{ value: 18, label: '18-24 years' },
|
|
162
|
+
{ value: 25, label: '25-34 years' },
|
|
163
|
+
{ value: 35, label: '35-44 years' },
|
|
164
|
+
{ value: 45, label: '45+ years' }
|
|
165
|
+
]
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const element = <SelectInputField {...originalProps} />;
|
|
169
|
+
const serialized = ComponentTransformer.serialize(element);
|
|
170
|
+
const serializedData = JSON.parse(serialized);
|
|
171
|
+
|
|
172
|
+
expect(serializedData.data.value).toBe(25);
|
|
173
|
+
expect(serializedData.data.options[1].value).toBe(25);
|
|
174
|
+
|
|
175
|
+
const deserializedElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
|
|
176
|
+
const reserialized = ComponentTransformer.serialize(deserializedElement);
|
|
177
|
+
const reserializedData = JSON.parse(reserialized);
|
|
178
|
+
|
|
179
|
+
expect(reserializedData.data.value).toBe(25);
|
|
180
|
+
expect(reserializedData.data.options[1].value).toBe(25);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
describe('Form Validation Properties', () => {
|
|
185
|
+
it('preserves validation and error state through serialization', () => {
|
|
186
|
+
const originalProps = {
|
|
187
|
+
label: 'Required Selection',
|
|
188
|
+
value: '',
|
|
189
|
+
options: [
|
|
190
|
+
{ value: 'option1', label: 'Option 1' },
|
|
191
|
+
{ value: 'option2', label: 'Option 2' }
|
|
192
|
+
],
|
|
193
|
+
required: true,
|
|
194
|
+
error: 'Please select an option',
|
|
195
|
+
helperText: 'Choose from the available options'
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const element = <SelectInputField {...originalProps} />;
|
|
199
|
+
|
|
200
|
+
let serializedData: any;
|
|
201
|
+
measurePerformance('Validation Serialization', () => {
|
|
202
|
+
const serialized = ComponentTransformer.serialize(element);
|
|
203
|
+
serializedData = JSON.parse(serialized);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
expect(serializedData.data.required).toBe(true);
|
|
207
|
+
expect(serializedData.data.error).toBe(originalProps.error);
|
|
208
|
+
expect(serializedData.data.helperText).toBe(originalProps.helperText);
|
|
209
|
+
|
|
210
|
+
const deserializedElement = ComponentTransformer.deserialize(JSON.stringify(serializedData)) as React.ReactElement;
|
|
211
|
+
const { getByLabelText, getByText } = render(deserializedElement);
|
|
212
|
+
|
|
213
|
+
expect(getByText('Required Selection')).toBeInTheDocument();
|
|
214
|
+
expect(getByText('Please select an option')).toBeInTheDocument();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('handles disabled select field correctly', () => {
|
|
218
|
+
const originalProps = {
|
|
219
|
+
label: 'Locked Selection',
|
|
220
|
+
value: 'locked',
|
|
221
|
+
options: [
|
|
222
|
+
{ value: 'locked', label: 'Locked Option' },
|
|
223
|
+
{ value: 'other', label: 'Other Option' }
|
|
224
|
+
],
|
|
225
|
+
disabled: true,
|
|
226
|
+
helperText: 'This selection cannot be changed'
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const element = <SelectInputField {...originalProps} />;
|
|
230
|
+
const serialized = ComponentTransformer.serialize(element);
|
|
231
|
+
const serializedData = JSON.parse(serialized);
|
|
232
|
+
|
|
233
|
+
expect(serializedData.data.disabled).toBe(true);
|
|
234
|
+
|
|
235
|
+
const deserializedElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
|
|
236
|
+
const reserialized = ComponentTransformer.serialize(deserializedElement);
|
|
237
|
+
const reserializedData = JSON.parse(reserialized);
|
|
238
|
+
|
|
239
|
+
expect(reserializedData.data.disabled).toBe(true);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
describe('Edge Cases and Error Handling', () => {
|
|
244
|
+
it('handles empty options array correctly', () => {
|
|
245
|
+
const originalProps = {
|
|
246
|
+
label: 'Empty Select',
|
|
247
|
+
value: '',
|
|
248
|
+
options: [],
|
|
249
|
+
placeholder: 'No options available'
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const element = <SelectInputField {...originalProps} />;
|
|
253
|
+
const serialized = ComponentTransformer.serialize(element);
|
|
254
|
+
const serializedData = JSON.parse(serialized);
|
|
255
|
+
|
|
256
|
+
expect(serializedData.data.options).toEqual([]);
|
|
257
|
+
|
|
258
|
+
const deserializedElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
|
|
259
|
+
const { getByText } = render(deserializedElement);
|
|
260
|
+
|
|
261
|
+
expect(getByText('No options provided for select field')).toBeInTheDocument();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('handles special characters in option labels', () => {
|
|
265
|
+
const specialOptions = [
|
|
266
|
+
{ value: 'unicode', label: 'Unicode: åäö 中文 🚀' },
|
|
267
|
+
{ value: 'quotes', label: 'With "quotes" and \'apostrophes\'' },
|
|
268
|
+
{ value: 'html', label: 'HTML: <div>tags</div> & entities' }
|
|
269
|
+
];
|
|
270
|
+
|
|
271
|
+
const originalProps = {
|
|
272
|
+
label: 'Special Characters',
|
|
273
|
+
value: 'unicode',
|
|
274
|
+
options: specialOptions
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
const element = <SelectInputField {...originalProps} />;
|
|
278
|
+
const serialized = ComponentTransformer.serialize(element);
|
|
279
|
+
const serializedData = JSON.parse(serialized);
|
|
280
|
+
|
|
281
|
+
expect(serializedData.data.options).toEqual(specialOptions);
|
|
282
|
+
|
|
283
|
+
const deserializedElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
|
|
284
|
+
const reserialized = ComponentTransformer.serialize(deserializedElement);
|
|
285
|
+
const reserializedData = JSON.parse(reserialized);
|
|
286
|
+
|
|
287
|
+
expect(reserializedData.data.options).toEqual(specialOptions);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('handles undefined/null values gracefully', () => {
|
|
291
|
+
const originalProps = {
|
|
292
|
+
label: 'Nullable Field',
|
|
293
|
+
value: '',
|
|
294
|
+
options: [
|
|
295
|
+
{ value: '', label: 'None' },
|
|
296
|
+
{ value: 'some', label: 'Some Value' }
|
|
297
|
+
],
|
|
298
|
+
placeholder: undefined,
|
|
299
|
+
helperText: undefined,
|
|
300
|
+
error: undefined
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
const element = <SelectInputField {...originalProps} />;
|
|
304
|
+
const serialized = ComponentTransformer.serialize(element);
|
|
305
|
+
const serializedData = JSON.parse(serialized);
|
|
306
|
+
|
|
307
|
+
// Undefined values should not appear in serialized data
|
|
308
|
+
expect(serializedData.data.placeholder).toBeUndefined();
|
|
309
|
+
expect(serializedData.data.helperText).toBeUndefined();
|
|
310
|
+
expect(serializedData.data.error).toBeUndefined();
|
|
311
|
+
|
|
312
|
+
const deserializedElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
|
|
313
|
+
expect(React.isValidElement(deserializedElement)).toBe(true);
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
describe('Large Option Sets Performance', () => {
|
|
318
|
+
it('handles large option arrays efficiently', () => {
|
|
319
|
+
// Generate 1000 options
|
|
320
|
+
const largeOptions = Array.from({ length: 1000 }, (_, i) => ({
|
|
321
|
+
value: `option_${i}`,
|
|
322
|
+
label: `Option ${i + 1}`,
|
|
323
|
+
disabled: i % 100 === 99 // Every 100th option is disabled
|
|
324
|
+
}));
|
|
325
|
+
|
|
326
|
+
const originalProps = {
|
|
327
|
+
label: 'Large Select',
|
|
328
|
+
value: 'option_500',
|
|
329
|
+
options: largeOptions
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
let serializedData: any;
|
|
333
|
+
let deserializedElement: React.ReactElement;
|
|
334
|
+
|
|
335
|
+
// Test serialization performance with large dataset
|
|
336
|
+
const serializationTime = measurePerformance('Large Options Serialization (1000 items)', () => {
|
|
337
|
+
const element = <SelectInputField {...originalProps} />;
|
|
338
|
+
const serialized = ComponentTransformer.serialize(element);
|
|
339
|
+
serializedData = JSON.parse(serialized);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// Test deserialization performance
|
|
343
|
+
const deserializationTime = measurePerformance('Large Options Deserialization (1000 items)', () => {
|
|
344
|
+
deserializedElement = ComponentTransformer.deserialize(JSON.stringify(serializedData)) as React.ReactElement;
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
expect(serializedData.data.options).toHaveLength(1000);
|
|
348
|
+
expect(serializationTime).toBeLessThan(10); // Should handle 1000 options in under 10ms
|
|
349
|
+
expect(deserializationTime).toBeLessThan(10);
|
|
350
|
+
|
|
351
|
+
// Verify random sample correctness
|
|
352
|
+
const randomIndex = Math.floor(Math.random() * 1000);
|
|
353
|
+
const originalOption = largeOptions[randomIndex];
|
|
354
|
+
const serializedOption = serializedData.data.options[randomIndex];
|
|
355
|
+
|
|
356
|
+
expect(serializedOption.value).toBe(originalOption.value);
|
|
357
|
+
expect(serializedOption.label).toBe(originalOption.label);
|
|
358
|
+
expect(serializedOption.disabled).toBe(originalOption.disabled);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
describe('Performance Benchmarks', () => {
|
|
363
|
+
it('meets performance targets for bulk operations', () => {
|
|
364
|
+
const testConfigurations = Array.from({ length: 50 }, (_, i) => ({
|
|
365
|
+
label: `Select Field ${i + 1}`,
|
|
366
|
+
value: `option_${i % 5}`,
|
|
367
|
+
options: Array.from({ length: 10 }, (_, j) => ({
|
|
368
|
+
value: `option_${j}`,
|
|
369
|
+
label: `Option ${j + 1}`,
|
|
370
|
+
disabled: j === 9
|
|
371
|
+
})),
|
|
372
|
+
required: i % 2 === 0
|
|
373
|
+
}));
|
|
374
|
+
|
|
375
|
+
let elements: React.ReactElement[];
|
|
376
|
+
let serializedData: any[];
|
|
377
|
+
let deserializedElements: React.ReactElement[];
|
|
378
|
+
|
|
379
|
+
// Bulk serialization
|
|
380
|
+
const bulkSerializationTime = measurePerformance('Bulk Serialization (50 selects)', () => {
|
|
381
|
+
elements = testConfigurations.map(props => <SelectInputField {...props} />);
|
|
382
|
+
serializedData = elements.map(element => {
|
|
383
|
+
const serialized = ComponentTransformer.serialize(element);
|
|
384
|
+
return JSON.parse(serialized);
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// Bulk deserialization
|
|
389
|
+
const bulkDeserializationTime = measurePerformance('Bulk Deserialization (50 selects)', () => {
|
|
390
|
+
deserializedElements = serializedData.map(data => ComponentTransformer.deserialize(JSON.stringify(data)) as React.ReactElement);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
expect(serializedData).toHaveLength(50);
|
|
394
|
+
expect(deserializedElements).toHaveLength(50);
|
|
395
|
+
expect(bulkSerializationTime).toBeLessThan(25); // Should handle 50 selects in under 25ms
|
|
396
|
+
expect(bulkDeserializationTime).toBeLessThan(25);
|
|
397
|
+
|
|
398
|
+
// Verify random sample correctness
|
|
399
|
+
const randomIndex = Math.floor(Math.random() * 50);
|
|
400
|
+
const originalConfig = testConfigurations[randomIndex];
|
|
401
|
+
const serializedConfig = serializedData[randomIndex];
|
|
402
|
+
|
|
403
|
+
expect(serializedConfig.data.label).toBe(originalConfig.label);
|
|
404
|
+
expect(serializedConfig.data.options).toEqual(originalConfig.options);
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
describe('Data Integrity', () => {
|
|
409
|
+
it('maintains referential integrity through multiple serialization cycles', () => {
|
|
410
|
+
const originalProps = {
|
|
411
|
+
label: 'Cycle Test Select',
|
|
412
|
+
value: 'middle',
|
|
413
|
+
options: [
|
|
414
|
+
{ value: 'first', label: 'First Option' },
|
|
415
|
+
{ value: 'middle', label: 'Middle Option' },
|
|
416
|
+
{ value: 'last', label: 'Last Option', disabled: true }
|
|
417
|
+
],
|
|
418
|
+
required: true
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
let currentElement = <SelectInputField {...originalProps} />;
|
|
422
|
+
let lastSerializedData: any;
|
|
423
|
+
|
|
424
|
+
// Perform 10 serialize-deserialize cycles
|
|
425
|
+
for (let cycle = 0; cycle < 10; cycle++) {
|
|
426
|
+
const serialized = ComponentTransformer.serialize(currentElement);
|
|
427
|
+
const serializedData = JSON.parse(serialized);
|
|
428
|
+
currentElement = ComponentTransformer.deserialize(serialized) as React.ReactElement;
|
|
429
|
+
lastSerializedData = serializedData;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Verify data integrity after 10 cycles
|
|
433
|
+
expect(lastSerializedData.data.label).toBe(originalProps.label);
|
|
434
|
+
expect(lastSerializedData.data.value).toBe(originalProps.value);
|
|
435
|
+
expect(lastSerializedData.data.options).toEqual(originalProps.options);
|
|
436
|
+
expect(lastSerializedData.data.required).toBe(originalProps.required);
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
});
|