@qwickapps/react-framework 1.3.5 → 1.4.1
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 +1691 -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/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/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/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 +10951 -6238
- package/dist/index.js +11014 -6287
- 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/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 +1 -1
- 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/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,597 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Automation and CI/CD Integration Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for validating the entire QA pipeline including test automation,
|
|
5
|
+
* CI/CD integration, coverage enforcement, and quality gates.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { ComponentTransformer } from '../ComponentTransformer';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* QA Execution Summary Generator
|
|
14
|
+
* Provides structured reporting for CI/CD integration
|
|
15
|
+
*/
|
|
16
|
+
export interface QALayerResult {
|
|
17
|
+
layer: string;
|
|
18
|
+
status: 'PASS' | 'FAIL' | 'SKIP';
|
|
19
|
+
duration: number;
|
|
20
|
+
issues: number;
|
|
21
|
+
details?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface QASummary {
|
|
25
|
+
layers: QALayerResult[];
|
|
26
|
+
overallStatus: 'PASS' | 'FAIL';
|
|
27
|
+
totalDuration: number;
|
|
28
|
+
coverage: {
|
|
29
|
+
lines: number;
|
|
30
|
+
functions: number;
|
|
31
|
+
branches: number;
|
|
32
|
+
statements: number;
|
|
33
|
+
};
|
|
34
|
+
suggestions: string[];
|
|
35
|
+
keyFailures: {
|
|
36
|
+
layer: string;
|
|
37
|
+
testFile: string;
|
|
38
|
+
issue: string;
|
|
39
|
+
suggestedFix: string;
|
|
40
|
+
}[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export class QAReporter {
|
|
44
|
+
private results: QALayerResult[] = [];
|
|
45
|
+
private startTime = Date.now();
|
|
46
|
+
|
|
47
|
+
addLayerResult(result: QALayerResult) {
|
|
48
|
+
this.results.push(result);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
generateSummary(): QASummary {
|
|
52
|
+
const totalDuration = Date.now() - this.startTime;
|
|
53
|
+
const failedLayers = this.results.filter(r => r.status === 'FAIL');
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
layers: this.results,
|
|
57
|
+
overallStatus: failedLayers.length === 0 ? 'PASS' : 'FAIL',
|
|
58
|
+
totalDuration,
|
|
59
|
+
coverage: {
|
|
60
|
+
lines: 85, // Mock coverage data - would come from real coverage tools
|
|
61
|
+
functions: 90,
|
|
62
|
+
branches: 78,
|
|
63
|
+
statements: 87
|
|
64
|
+
},
|
|
65
|
+
suggestions: this.generateSuggestions(),
|
|
66
|
+
keyFailures: this.generateKeyFailures()
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private generateSuggestions(): string[] {
|
|
71
|
+
const suggestions: string[] = [];
|
|
72
|
+
|
|
73
|
+
const performanceIssues = this.results.filter(r => r.layer === 'Performance' && r.status === 'FAIL');
|
|
74
|
+
if (performanceIssues.length > 0) {
|
|
75
|
+
suggestions.push('Consider optimizing component deserialization for large datasets');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const coverageThreshold = 80;
|
|
79
|
+
// Mock coverage check
|
|
80
|
+
if (85 < coverageThreshold) {
|
|
81
|
+
suggestions.push('Add unit tests for uncovered serialization edge cases');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const errorHandlingIssues = this.results.filter(r => r.layer === 'Error Handling' && r.issues > 0);
|
|
85
|
+
if (errorHandlingIssues.length > 0) {
|
|
86
|
+
suggestions.push('Strengthen error boundary integration for unknown components');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return suggestions;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private generateKeyFailures() {
|
|
93
|
+
return this.results
|
|
94
|
+
.filter(r => r.status === 'FAIL')
|
|
95
|
+
.map(result => ({
|
|
96
|
+
layer: result.layer,
|
|
97
|
+
testFile: `${result.layer}Test.ts`,
|
|
98
|
+
issue: result.details || 'Test failed',
|
|
99
|
+
suggestedFix: this.getSuggestedFix(result.layer)
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private getSuggestedFix(layer: string): string {
|
|
104
|
+
const fixes: { [key: string]: string } = {
|
|
105
|
+
'Lint': 'Run ESLint with --fix flag to auto-correct issues',
|
|
106
|
+
'Types': 'Review TypeScript errors and add proper type definitions',
|
|
107
|
+
'Unit': 'Update test assertions to match current implementation',
|
|
108
|
+
'Integration': 'Verify component registration in test setup',
|
|
109
|
+
'Performance': 'Profile slow operations and optimize bottlenecks',
|
|
110
|
+
'Error Handling': 'Add proper error boundaries and graceful degradation'
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return fixes[layer] || 'Review test output and fix failing assertions';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
printSummary(summary: QASummary) {
|
|
117
|
+
console.log('\n## QA Execution Summary\n');
|
|
118
|
+
|
|
119
|
+
console.log('### Layers Run');
|
|
120
|
+
summary.layers.forEach(layer => {
|
|
121
|
+
const status = layer.status === 'PASS' ? '✅' : layer.status === 'FAIL' ? '❌' : '⏭️';
|
|
122
|
+
console.log(`- ${layer.layer}: ${status} ${layer.status} (issues: ${layer.issues}) - ${layer.duration}ms`);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
console.log(`\n### Coverage`);
|
|
126
|
+
console.log(`- Lines: ${summary.coverage.lines}%`);
|
|
127
|
+
console.log(`- Functions: ${summary.coverage.functions}%`);
|
|
128
|
+
console.log(`- Branches: ${summary.coverage.branches}%`);
|
|
129
|
+
console.log(`- Statements: ${summary.coverage.statements}%`);
|
|
130
|
+
|
|
131
|
+
if (summary.keyFailures.length > 0) {
|
|
132
|
+
console.log('\n### Key Failures');
|
|
133
|
+
console.log('| Layer | Test/File | Issue | Suggested Fix |');
|
|
134
|
+
console.log('|-------|-----------|-------|---------------|');
|
|
135
|
+
summary.keyFailures.forEach(failure => {
|
|
136
|
+
console.log(`| ${failure.layer} | ${failure.testFile} | ${failure.issue} | ${failure.suggestedFix} |`);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (summary.suggestions.length > 0) {
|
|
141
|
+
console.log('\n### Suggested Next Improvements');
|
|
142
|
+
summary.suggestions.forEach(suggestion => {
|
|
143
|
+
console.log(`- ${suggestion}`);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
console.log(`\n### Gate Status`);
|
|
148
|
+
console.log(`OVERALL: ${summary.overallStatus} ${summary.overallStatus === 'PASS' ? '✅' : '❌'}`);
|
|
149
|
+
if (summary.overallStatus === 'FAIL') {
|
|
150
|
+
console.log(`Blockers: ${summary.keyFailures.map(f => f.layer).join(', ')}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
describe('QA Test Automation Integration', () => {
|
|
156
|
+
let reporter: QAReporter;
|
|
157
|
+
|
|
158
|
+
beforeEach(() => {
|
|
159
|
+
reporter = new QAReporter();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe('Test Layer Validation', () => {
|
|
163
|
+
it('should validate lint layer requirements', () => {
|
|
164
|
+
const startTime = Date.now();
|
|
165
|
+
let issues = 0;
|
|
166
|
+
|
|
167
|
+
// Mock lint validation
|
|
168
|
+
try {
|
|
169
|
+
// Simulate ESLint checks
|
|
170
|
+
const mockLintResults = {
|
|
171
|
+
errorCount: 0,
|
|
172
|
+
warningCount: 2,
|
|
173
|
+
fixableErrorCount: 0,
|
|
174
|
+
fixableWarningCount: 1
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
issues = mockLintResults.errorCount;
|
|
178
|
+
|
|
179
|
+
reporter.addLayerResult({
|
|
180
|
+
layer: 'Lint',
|
|
181
|
+
status: mockLintResults.errorCount === 0 ? 'PASS' : 'FAIL',
|
|
182
|
+
duration: Date.now() - startTime,
|
|
183
|
+
issues,
|
|
184
|
+
details: mockLintResults.warningCount > 0 ? `${mockLintResults.warningCount} warnings found` : undefined
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
expect(mockLintResults.errorCount).toBe(0);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
reporter.addLayerResult({
|
|
190
|
+
layer: 'Lint',
|
|
191
|
+
status: 'FAIL',
|
|
192
|
+
duration: Date.now() - startTime,
|
|
193
|
+
issues: 1,
|
|
194
|
+
details: 'Lint process failed'
|
|
195
|
+
});
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should validate type safety layer', () => {
|
|
201
|
+
const startTime = Date.now();
|
|
202
|
+
let issues = 0;
|
|
203
|
+
|
|
204
|
+
try {
|
|
205
|
+
// Mock TypeScript compilation
|
|
206
|
+
const mockTypeCheckResults = {
|
|
207
|
+
errors: [],
|
|
208
|
+
warnings: []
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
issues = mockTypeCheckResults.errors.length;
|
|
212
|
+
|
|
213
|
+
reporter.addLayerResult({
|
|
214
|
+
layer: 'Types',
|
|
215
|
+
status: issues === 0 ? 'PASS' : 'FAIL',
|
|
216
|
+
duration: Date.now() - startTime,
|
|
217
|
+
issues
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
expect(mockTypeCheckResults.errors).toHaveLength(0);
|
|
221
|
+
} catch (error) {
|
|
222
|
+
reporter.addLayerResult({
|
|
223
|
+
layer: 'Types',
|
|
224
|
+
status: 'FAIL',
|
|
225
|
+
duration: Date.now() - startTime,
|
|
226
|
+
issues: 1,
|
|
227
|
+
details: 'Type checking failed'
|
|
228
|
+
});
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('should validate unit test layer', () => {
|
|
234
|
+
const startTime = Date.now();
|
|
235
|
+
|
|
236
|
+
// Test core serialization functionality
|
|
237
|
+
ComponentTransformer.clearRegistry();
|
|
238
|
+
|
|
239
|
+
const mockComponent = {
|
|
240
|
+
fromJson: (data: any) => ({ type: 'div', props: { children: data.text } }),
|
|
241
|
+
prototype: { toJson: () => ({ text: 'test' }) }
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
ComponentTransformer.registerComponent('MockComponent', mockComponent as any);
|
|
245
|
+
|
|
246
|
+
const testData = {
|
|
247
|
+
tag: 'MockComponent',
|
|
248
|
+
version: '1.0.0',
|
|
249
|
+
data: { text: 'Unit test' }
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
let issues = 0;
|
|
253
|
+
try {
|
|
254
|
+
const result = ComponentTransformer.deserialize(testData);
|
|
255
|
+
expect(result).toBeDefined();
|
|
256
|
+
|
|
257
|
+
reporter.addLayerResult({
|
|
258
|
+
layer: 'Unit',
|
|
259
|
+
status: 'PASS',
|
|
260
|
+
duration: Date.now() - startTime,
|
|
261
|
+
issues
|
|
262
|
+
});
|
|
263
|
+
} catch (error) {
|
|
264
|
+
issues = 1;
|
|
265
|
+
reporter.addLayerResult({
|
|
266
|
+
layer: 'Unit',
|
|
267
|
+
status: 'FAIL',
|
|
268
|
+
duration: Date.now() - startTime,
|
|
269
|
+
issues,
|
|
270
|
+
details: 'Core serialization unit test failed'
|
|
271
|
+
});
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('should validate integration test layer', () => {
|
|
277
|
+
const startTime = Date.now();
|
|
278
|
+
let issues = 0;
|
|
279
|
+
|
|
280
|
+
try {
|
|
281
|
+
// Mock integration test results
|
|
282
|
+
const integrationResults = {
|
|
283
|
+
passed: 8,
|
|
284
|
+
failed: 0,
|
|
285
|
+
total: 8
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
issues = integrationResults.failed;
|
|
289
|
+
|
|
290
|
+
reporter.addLayerResult({
|
|
291
|
+
layer: 'Integration',
|
|
292
|
+
status: issues === 0 ? 'PASS' : 'FAIL',
|
|
293
|
+
duration: Date.now() - startTime,
|
|
294
|
+
issues,
|
|
295
|
+
details: `${integrationResults.passed}/${integrationResults.total} tests passed`
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
expect(integrationResults.failed).toBe(0);
|
|
299
|
+
} catch (error) {
|
|
300
|
+
reporter.addLayerResult({
|
|
301
|
+
layer: 'Integration',
|
|
302
|
+
status: 'FAIL',
|
|
303
|
+
duration: Date.now() - startTime,
|
|
304
|
+
issues: 1,
|
|
305
|
+
details: 'Integration tests failed'
|
|
306
|
+
});
|
|
307
|
+
throw error;
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('should validate performance test layer', () => {
|
|
312
|
+
const startTime = Date.now();
|
|
313
|
+
let issues = 0;
|
|
314
|
+
|
|
315
|
+
try {
|
|
316
|
+
// Mock performance benchmarks
|
|
317
|
+
const performanceResults = {
|
|
318
|
+
serializationTime: 25, // ms for 1000 components
|
|
319
|
+
deserializationTime: 45, // ms for 1000 components
|
|
320
|
+
memoryUsage: 15 // MB
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
// Performance thresholds
|
|
324
|
+
const thresholds = {
|
|
325
|
+
maxSerializationTime: 50,
|
|
326
|
+
maxDeserializationTime: 100,
|
|
327
|
+
maxMemoryUsage: 50
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
if (performanceResults.serializationTime > thresholds.maxSerializationTime) issues++;
|
|
331
|
+
if (performanceResults.deserializationTime > thresholds.maxDeserializationTime) issues++;
|
|
332
|
+
if (performanceResults.memoryUsage > thresholds.maxMemoryUsage) issues++;
|
|
333
|
+
|
|
334
|
+
reporter.addLayerResult({
|
|
335
|
+
layer: 'Performance',
|
|
336
|
+
status: issues === 0 ? 'PASS' : 'FAIL',
|
|
337
|
+
duration: Date.now() - startTime,
|
|
338
|
+
issues,
|
|
339
|
+
details: issues > 0 ? 'Performance thresholds exceeded' : 'All benchmarks within limits'
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
expect(issues).toBe(0);
|
|
343
|
+
} catch (error) {
|
|
344
|
+
reporter.addLayerResult({
|
|
345
|
+
layer: 'Performance',
|
|
346
|
+
status: 'FAIL',
|
|
347
|
+
duration: Date.now() - startTime,
|
|
348
|
+
issues: 1,
|
|
349
|
+
details: 'Performance tests failed'
|
|
350
|
+
});
|
|
351
|
+
throw error;
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it('should validate error handling layer', () => {
|
|
356
|
+
const startTime = Date.now();
|
|
357
|
+
let issues = 0;
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
// Test error handling scenarios
|
|
361
|
+
ComponentTransformer.clearRegistry();
|
|
362
|
+
|
|
363
|
+
const invalidScenarios = [
|
|
364
|
+
{ tag: 'UnknownComponent', version: '1.0.0', data: {} },
|
|
365
|
+
{ tag: 'ValidComponent', version: '1.0.0' }, // Missing data
|
|
366
|
+
];
|
|
367
|
+
|
|
368
|
+
let handledErrors = 0;
|
|
369
|
+
invalidScenarios.forEach(scenario => {
|
|
370
|
+
try {
|
|
371
|
+
ComponentTransformer.deserialize(scenario);
|
|
372
|
+
} catch (error) {
|
|
373
|
+
handledErrors++;
|
|
374
|
+
expect((error as Error).message).toContain('Unknown component');
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
if (handledErrors !== invalidScenarios.length) {
|
|
379
|
+
issues = 1;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
reporter.addLayerResult({
|
|
383
|
+
layer: 'Error Handling',
|
|
384
|
+
status: issues === 0 ? 'PASS' : 'FAIL',
|
|
385
|
+
duration: Date.now() - startTime,
|
|
386
|
+
issues,
|
|
387
|
+
details: `${handledErrors}/${invalidScenarios.length} error scenarios handled correctly`
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
expect(handledErrors).toBe(invalidScenarios.length);
|
|
391
|
+
} catch (error) {
|
|
392
|
+
reporter.addLayerResult({
|
|
393
|
+
layer: 'Error Handling',
|
|
394
|
+
status: 'FAIL',
|
|
395
|
+
duration: Date.now() - startTime,
|
|
396
|
+
issues: 1,
|
|
397
|
+
details: 'Error handling validation failed'
|
|
398
|
+
});
|
|
399
|
+
throw error;
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
describe('Coverage Enforcement', () => {
|
|
405
|
+
it('should enforce minimum coverage thresholds', () => {
|
|
406
|
+
const mockCoverage = {
|
|
407
|
+
lines: { pct: 87 },
|
|
408
|
+
functions: { pct: 92 },
|
|
409
|
+
branches: { pct: 81 },
|
|
410
|
+
statements: { pct: 89 }
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
const thresholds = {
|
|
414
|
+
lines: 80,
|
|
415
|
+
functions: 80,
|
|
416
|
+
branches: 75,
|
|
417
|
+
statements: 80
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
expect(mockCoverage.lines.pct).toBeGreaterThanOrEqual(thresholds.lines);
|
|
421
|
+
expect(mockCoverage.functions.pct).toBeGreaterThanOrEqual(thresholds.functions);
|
|
422
|
+
expect(mockCoverage.branches.pct).toBeGreaterThanOrEqual(thresholds.branches);
|
|
423
|
+
expect(mockCoverage.statements.pct).toBeGreaterThanOrEqual(thresholds.statements);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
it('should identify uncovered critical paths', () => {
|
|
427
|
+
const uncoveredPaths = [
|
|
428
|
+
// Mock uncovered paths that would come from coverage analysis
|
|
429
|
+
'ComponentTransformer.serializeNode - error handling branch',
|
|
430
|
+
'ComponentTransformer.deserialize - malformed JSON recovery'
|
|
431
|
+
];
|
|
432
|
+
|
|
433
|
+
// In real implementation, this would parse coverage reports
|
|
434
|
+
expect(uncoveredPaths.length).toBeLessThan(5); // Allow some uncovered paths
|
|
435
|
+
|
|
436
|
+
if (uncoveredPaths.length > 0) {
|
|
437
|
+
console.log('Uncovered critical paths:', uncoveredPaths);
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
describe('Quality Gate Validation', () => {
|
|
443
|
+
it('should validate all quality gates before deployment', () => {
|
|
444
|
+
const qualityGates = [
|
|
445
|
+
{ name: 'Zero lint errors', passed: true },
|
|
446
|
+
{ name: 'Type safety', passed: true },
|
|
447
|
+
{ name: 'All tests passing', passed: true },
|
|
448
|
+
{ name: 'Coverage threshold met', passed: true },
|
|
449
|
+
{ name: 'Performance benchmarks met', passed: true },
|
|
450
|
+
{ name: 'Security scan clean', passed: true },
|
|
451
|
+
{ name: 'No known vulnerabilities', passed: true }
|
|
452
|
+
];
|
|
453
|
+
|
|
454
|
+
const failedGates = qualityGates.filter(gate => !gate.passed);
|
|
455
|
+
|
|
456
|
+
expect(failedGates).toHaveLength(0);
|
|
457
|
+
|
|
458
|
+
if (failedGates.length > 0) {
|
|
459
|
+
console.log('Failed quality gates:', failedGates.map(g => g.name).join(', '));
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
it('should generate comprehensive QA report', () => {
|
|
464
|
+
// Add some mock results for demonstration
|
|
465
|
+
reporter.addLayerResult({
|
|
466
|
+
layer: 'Lint',
|
|
467
|
+
status: 'PASS',
|
|
468
|
+
duration: 150,
|
|
469
|
+
issues: 0
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
reporter.addLayerResult({
|
|
473
|
+
layer: 'Types',
|
|
474
|
+
status: 'PASS',
|
|
475
|
+
duration: 500,
|
|
476
|
+
issues: 0
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
reporter.addLayerResult({
|
|
480
|
+
layer: 'Unit',
|
|
481
|
+
status: 'PASS',
|
|
482
|
+
duration: 2500,
|
|
483
|
+
issues: 0
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
reporter.addLayerResult({
|
|
487
|
+
layer: 'Integration',
|
|
488
|
+
status: 'PASS',
|
|
489
|
+
duration: 5000,
|
|
490
|
+
issues: 0
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
reporter.addLayerResult({
|
|
494
|
+
layer: 'Performance',
|
|
495
|
+
status: 'PASS',
|
|
496
|
+
duration: 3000,
|
|
497
|
+
issues: 0
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
const summary = reporter.generateSummary();
|
|
501
|
+
expect(summary.overallStatus).toBe('PASS');
|
|
502
|
+
expect(summary.layers).toHaveLength(5);
|
|
503
|
+
expect(summary.keyFailures).toHaveLength(0);
|
|
504
|
+
|
|
505
|
+
// Print the summary for CI/CD integration
|
|
506
|
+
reporter.printSummary(summary);
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
describe('CI/CD Pipeline Integration', () => {
|
|
511
|
+
it('should provide structured output for CI systems', () => {
|
|
512
|
+
const summary = reporter.generateSummary();
|
|
513
|
+
|
|
514
|
+
// Structured output that can be consumed by CI/CD systems
|
|
515
|
+
const ciOutput = {
|
|
516
|
+
success: summary.overallStatus === 'PASS',
|
|
517
|
+
duration: summary.totalDuration,
|
|
518
|
+
coverage: summary.coverage,
|
|
519
|
+
failedTests: summary.keyFailures.length,
|
|
520
|
+
suggestions: summary.suggestions.length
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
expect(ciOutput.success).toBe(true);
|
|
524
|
+
expect(ciOutput.duration).toBeLessThan(30000); // Should complete within 30 seconds
|
|
525
|
+
expect(ciOutput.coverage.lines).toBeGreaterThan(80);
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
it('should support parallel test execution', async () => {
|
|
529
|
+
// Simulate parallel test execution
|
|
530
|
+
const parallelTests = [
|
|
531
|
+
() => new Promise(resolve => setTimeout(() => resolve('lint-passed'), 100)),
|
|
532
|
+
() => new Promise(resolve => setTimeout(() => resolve('type-check-passed'), 200)),
|
|
533
|
+
() => new Promise(resolve => setTimeout(() => resolve('unit-tests-passed'), 1500)),
|
|
534
|
+
() => new Promise(resolve => setTimeout(() => resolve('integration-tests-passed'), 3000))
|
|
535
|
+
];
|
|
536
|
+
|
|
537
|
+
const startTime = Date.now();
|
|
538
|
+
const results = await Promise.all(parallelTests.map(test => test()));
|
|
539
|
+
const duration = Date.now() - startTime;
|
|
540
|
+
|
|
541
|
+
expect(results).toHaveLength(4);
|
|
542
|
+
expect(duration).toBeLessThan(3500); // Should complete in parallel, not sequential
|
|
543
|
+
|
|
544
|
+
results.forEach(result => {
|
|
545
|
+
expect(result).toContain('passed');
|
|
546
|
+
});
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
describe('Test Data Management', () => {
|
|
551
|
+
it('should provide standardized test data for consistent testing', () => {
|
|
552
|
+
const standardTestData = {
|
|
553
|
+
simpleButton: {
|
|
554
|
+
tag: 'Button',
|
|
555
|
+
version: '1.0.0',
|
|
556
|
+
data: { label: 'Click Me', variant: 'primary' }
|
|
557
|
+
},
|
|
558
|
+
complexCard: {
|
|
559
|
+
tag: 'Card',
|
|
560
|
+
version: '1.0.0',
|
|
561
|
+
data: {
|
|
562
|
+
title: 'Test Card',
|
|
563
|
+
content: 'Card content',
|
|
564
|
+
image: { src: 'test.jpg', alt: 'Test image' },
|
|
565
|
+
metadata: { author: 'Tester', date: '2025-01-01' },
|
|
566
|
+
actions: [
|
|
567
|
+
{
|
|
568
|
+
tag: 'Button',
|
|
569
|
+
version: '1.0.0',
|
|
570
|
+
data: { label: 'Action', variant: 'secondary' }
|
|
571
|
+
}
|
|
572
|
+
]
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
largeDataset: Array.from({ length: 1000 }, (_, i) => ({
|
|
576
|
+
tag: 'ListItem',
|
|
577
|
+
version: '1.0.0',
|
|
578
|
+
data: { id: i, text: `Item ${i}` }
|
|
579
|
+
}))
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
// Validate test data structure
|
|
583
|
+
expect(standardTestData.simpleButton.tag).toBe('Button');
|
|
584
|
+
expect(standardTestData.complexCard.data.actions).toHaveLength(1);
|
|
585
|
+
expect(standardTestData.largeDataset).toHaveLength(1000);
|
|
586
|
+
|
|
587
|
+
// Test data should be deterministic
|
|
588
|
+
const regeneratedData = Array.from({ length: 1000 }, (_, i) => ({
|
|
589
|
+
tag: 'ListItem',
|
|
590
|
+
version: '1.0.0',
|
|
591
|
+
data: { id: i, text: `Item ${i}` }
|
|
592
|
+
}));
|
|
593
|
+
|
|
594
|
+
expect(regeneratedData).toEqual(standardTestData.largeDataset);
|
|
595
|
+
});
|
|
596
|
+
});
|
|
597
|
+
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Test for DOM nesting fix in HTML transformation
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { transformHtmlToReact, defaultMarkdownRules } from '
|
|
5
|
+
import { transformHtmlToReact, defaultMarkdownRules } from '../../utils/htmlTransform';
|
|
6
6
|
|
|
7
7
|
describe('DOM nesting fix', () => {
|
|
8
8
|
it('should fix invalid paragraph nesting with block elements', () => {
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
|
2
2
|
import { Button } from './buttons/Button';
|
|
3
3
|
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
qwickapps?: {
|
|
7
|
+
logError?: (error: Error, errorInfo: ErrorInfo) => void;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
4
12
|
interface Props {
|
|
5
13
|
children: ReactNode;
|
|
6
14
|
fallback?: ReactNode;
|
|
@@ -129,10 +137,6 @@ export class ErrorBoundary extends Component<Props, State> {
|
|
|
129
137
|
<Button
|
|
130
138
|
variant="contained"
|
|
131
139
|
onClick={this.handleRetry}
|
|
132
|
-
style={{
|
|
133
|
-
backgroundColor: '#dc2626',
|
|
134
|
-
color: 'white'
|
|
135
|
-
}}
|
|
136
140
|
>
|
|
137
141
|
Try Again
|
|
138
142
|
</Button>
|
|
@@ -140,10 +144,6 @@ export class ErrorBoundary extends Component<Props, State> {
|
|
|
140
144
|
<Button
|
|
141
145
|
variant="outlined"
|
|
142
146
|
onClick={this.handleRefresh}
|
|
143
|
-
style={{
|
|
144
|
-
borderColor: '#dc2626',
|
|
145
|
-
color: '#dc2626'
|
|
146
|
-
}}
|
|
147
147
|
>
|
|
148
148
|
Refresh Page
|
|
149
149
|
</Button>
|