@qwickapps/react-framework 1.3.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/LICENSE +44 -0
- package/README.md +794 -0
- package/dist/components/AccessibilityChecker.d.ts +12 -0
- package/dist/components/AccessibilityChecker.d.ts.map +1 -0
- package/dist/components/Html.d.ts +48 -0
- package/dist/components/Html.d.ts.map +1 -0
- package/dist/components/Logo.d.ts +79 -0
- package/dist/components/Logo.d.ts.map +1 -0
- package/dist/components/Markdown.d.ts +47 -0
- package/dist/components/Markdown.d.ts.map +1 -0
- package/dist/components/QwickApp.d.ts +56 -0
- package/dist/components/QwickApp.d.ts.map +1 -0
- package/dist/components/QwickAppsLogo.d.ts +25 -0
- package/dist/components/QwickAppsLogo.d.ts.map +1 -0
- package/dist/components/ResponsiveMenu.d.ts +38 -0
- package/dist/components/ResponsiveMenu.d.ts.map +1 -0
- package/dist/components/SafeSpan.d.ts +23 -0
- package/dist/components/SafeSpan.d.ts.map +1 -0
- package/dist/components/Scaffold.d.ts +57 -0
- package/dist/components/Scaffold.d.ts.map +1 -0
- package/dist/components/blocks/Article.d.ts +23 -0
- package/dist/components/blocks/Article.d.ts.map +1 -0
- package/dist/components/blocks/CardListGrid.d.ts +23 -0
- package/dist/components/blocks/CardListGrid.d.ts.map +1 -0
- package/dist/components/blocks/Code.d.ts +21 -0
- package/dist/components/blocks/Code.d.ts.map +1 -0
- package/dist/components/blocks/Content.d.ts +24 -0
- package/dist/components/blocks/Content.d.ts.map +1 -0
- package/dist/components/blocks/CoverImageHeader.d.ts +44 -0
- package/dist/components/blocks/CoverImageHeader.d.ts.map +1 -0
- package/dist/components/blocks/FeatureCard.d.ts +66 -0
- package/dist/components/blocks/FeatureCard.d.ts.map +1 -0
- package/dist/components/blocks/FeatureGrid.d.ts +48 -0
- package/dist/components/blocks/FeatureGrid.d.ts.map +1 -0
- package/dist/components/blocks/Footer.d.ts +56 -0
- package/dist/components/blocks/Footer.d.ts.map +1 -0
- package/dist/components/blocks/HeroBlock.d.ts +33 -0
- package/dist/components/blocks/HeroBlock.d.ts.map +1 -0
- package/dist/components/blocks/PageBannerHeader.d.ts +30 -0
- package/dist/components/blocks/PageBannerHeader.d.ts.map +1 -0
- package/dist/components/blocks/ProductCard.d.ts +57 -0
- package/dist/components/blocks/ProductCard.d.ts.map +1 -0
- package/dist/components/blocks/Section.d.ts +40 -0
- package/dist/components/blocks/Section.d.ts.map +1 -0
- package/dist/components/blocks/index.d.ts +37 -0
- package/dist/components/blocks/index.d.ts.map +1 -0
- package/dist/components/buttons/Button.d.ts +38 -0
- package/dist/components/buttons/Button.d.ts.map +1 -0
- package/dist/components/buttons/PaletteSwitcher.d.ts +24 -0
- package/dist/components/buttons/PaletteSwitcher.d.ts.map +1 -0
- package/dist/components/buttons/ThemeSwitcher.d.ts +24 -0
- package/dist/components/buttons/ThemeSwitcher.d.ts.map +1 -0
- package/dist/components/buttons/index.d.ts +11 -0
- package/dist/components/buttons/index.d.ts.map +1 -0
- package/dist/components/forms/FormBlock.d.ts +45 -0
- package/dist/components/forms/FormBlock.d.ts.map +1 -0
- package/dist/components/forms/index.d.ts +8 -0
- package/dist/components/forms/index.d.ts.map +1 -0
- package/dist/components/index.d.ts +32 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/input/ChoiceInputField.d.ts +30 -0
- package/dist/components/input/ChoiceInputField.d.ts.map +1 -0
- package/dist/components/input/HtmlInputField.d.ts +29 -0
- package/dist/components/input/HtmlInputField.d.ts.map +1 -0
- package/dist/components/input/SelectInputField.d.ts +29 -0
- package/dist/components/input/SelectInputField.d.ts.map +1 -0
- package/dist/components/input/TextField.d.ts +18 -0
- package/dist/components/input/TextField.d.ts.map +1 -0
- package/dist/components/input/TextInputField.d.ts +32 -0
- package/dist/components/input/TextInputField.d.ts.map +1 -0
- package/dist/components/input/index.d.ts +17 -0
- package/dist/components/input/index.d.ts.map +1 -0
- package/dist/components/layout/GridCell.d.ts +16 -0
- package/dist/components/layout/GridCell.d.ts.map +1 -0
- package/dist/components/layout/GridCellWrapper.d.ts +46 -0
- package/dist/components/layout/GridCellWrapper.d.ts.map +1 -0
- package/dist/components/layout/GridLayout.d.ts +38 -0
- package/dist/components/layout/GridLayout.d.ts.map +1 -0
- package/dist/components/layout/index.d.ts +12 -0
- package/dist/components/layout/index.d.ts.map +1 -0
- package/dist/components/menu/Menu.d.ts +1 -0
- package/dist/components/menu/Menu.d.ts.map +1 -0
- package/dist/components/menu/MenuItem.d.ts +31 -0
- package/dist/components/menu/MenuItem.d.ts.map +1 -0
- package/dist/components/menu/index.d.ts +7 -0
- package/dist/components/menu/index.d.ts.map +1 -0
- package/dist/components/pages/FormPage.d.ts +66 -0
- package/dist/components/pages/FormPage.d.ts.map +1 -0
- package/dist/components/pages/Page.d.ts +124 -0
- package/dist/components/pages/Page.d.ts.map +1 -0
- package/dist/components/pages/index.d.ts +11 -0
- package/dist/components/pages/index.d.ts.map +1 -0
- package/dist/contexts/DataContext.d.ts +139 -0
- package/dist/contexts/DataContext.d.ts.map +1 -0
- package/dist/contexts/DimensionsContext.d.ts +42 -0
- package/dist/contexts/DimensionsContext.d.ts.map +1 -0
- package/dist/contexts/PaletteContext.d.ts +53 -0
- package/dist/contexts/PaletteContext.d.ts.map +1 -0
- package/dist/contexts/QwickAppContext.d.ts +71 -0
- package/dist/contexts/QwickAppContext.d.ts.map +1 -0
- package/dist/contexts/ThemeContext.d.ts +65 -0
- package/dist/contexts/ThemeContext.d.ts.map +1 -0
- package/dist/contexts/index.d.ts +9 -0
- package/dist/contexts/index.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +10 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/useBaseProps.d.ts +101 -0
- package/dist/hooks/useBaseProps.d.ts.map +1 -0
- package/dist/hooks/useDataBinding.d.ts +22 -0
- package/dist/hooks/useDataBinding.d.ts.map +1 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.css +1 -0
- package/dist/index.esm.js +24143 -0
- package/dist/index.js +24245 -0
- package/dist/palettes/PaletteAutumn.d.ts +10 -0
- package/dist/palettes/PaletteAutumn.d.ts.map +1 -0
- package/dist/palettes/PaletteCosmic.d.ts +10 -0
- package/dist/palettes/PaletteCosmic.d.ts.map +1 -0
- package/dist/palettes/PaletteDefault.d.ts +10 -0
- package/dist/palettes/PaletteDefault.d.ts.map +1 -0
- package/dist/palettes/PaletteOcean.d.ts +10 -0
- package/dist/palettes/PaletteOcean.d.ts.map +1 -0
- package/dist/palettes/PaletteSpring.d.ts +10 -0
- package/dist/palettes/PaletteSpring.d.ts.map +1 -0
- package/dist/palettes/PaletteWinter.d.ts +10 -0
- package/dist/palettes/PaletteWinter.d.ts.map +1 -0
- package/dist/palettes/index.d.ts +13 -0
- package/dist/palettes/index.d.ts.map +1 -0
- package/dist/schemas/ActionSchema.d.ts +21 -0
- package/dist/schemas/ActionSchema.d.ts.map +1 -0
- package/dist/schemas/ArticleSchema.d.ts +13 -0
- package/dist/schemas/ArticleSchema.d.ts.map +1 -0
- package/dist/schemas/Builders.d.ts +7 -0
- package/dist/schemas/Builders.d.ts.map +1 -0
- package/dist/schemas/ButtonSchema.d.ts +19 -0
- package/dist/schemas/ButtonSchema.d.ts.map +1 -0
- package/dist/schemas/CardListGridSchema.d.ts +17 -0
- package/dist/schemas/CardListGridSchema.d.ts.map +1 -0
- package/dist/schemas/ChoiceInputFieldSchema.d.ts +18 -0
- package/dist/schemas/ChoiceInputFieldSchema.d.ts.map +1 -0
- package/dist/schemas/CodeSchema.d.ts +18 -0
- package/dist/schemas/CodeSchema.d.ts.map +1 -0
- package/dist/schemas/ContentSchema.d.ts +20 -0
- package/dist/schemas/ContentSchema.d.ts.map +1 -0
- package/dist/schemas/CoverImageHeaderSchema.d.ts +28 -0
- package/dist/schemas/CoverImageHeaderSchema.d.ts.map +1 -0
- package/dist/schemas/FeatureCardSchema.d.ts +28 -0
- package/dist/schemas/FeatureCardSchema.d.ts.map +1 -0
- package/dist/schemas/FeatureGridSchema.d.ts +17 -0
- package/dist/schemas/FeatureGridSchema.d.ts.map +1 -0
- package/dist/schemas/FeatureItemSchema.d.ts +16 -0
- package/dist/schemas/FeatureItemSchema.d.ts.map +1 -0
- package/dist/schemas/FooterItemSchema.d.ts +15 -0
- package/dist/schemas/FooterItemSchema.d.ts.map +1 -0
- package/dist/schemas/FooterSchema.d.ts +20 -0
- package/dist/schemas/FooterSchema.d.ts.map +1 -0
- package/dist/schemas/FooterSectionSchema.d.ts +15 -0
- package/dist/schemas/FooterSectionSchema.d.ts.map +1 -0
- package/dist/schemas/FormBlockSchema.d.ts +19 -0
- package/dist/schemas/FormBlockSchema.d.ts.map +1 -0
- package/dist/schemas/HeaderActionSchema.d.ts +17 -0
- package/dist/schemas/HeaderActionSchema.d.ts.map +1 -0
- package/dist/schemas/HeroBlockSchema.d.ts +22 -0
- package/dist/schemas/HeroBlockSchema.d.ts.map +1 -0
- package/dist/schemas/HtmlInputFieldSchema.d.ts +18 -0
- package/dist/schemas/HtmlInputFieldSchema.d.ts.map +1 -0
- package/dist/schemas/MetadataItemSchema.d.ts +13 -0
- package/dist/schemas/MetadataItemSchema.d.ts.map +1 -0
- package/dist/schemas/PageBannerHeaderSchema.d.ts +28 -0
- package/dist/schemas/PageBannerHeaderSchema.d.ts.map +1 -0
- package/dist/schemas/PaletteSwitcherSchema.d.ts +16 -0
- package/dist/schemas/PaletteSwitcherSchema.d.ts.map +1 -0
- package/dist/schemas/ProductCardSchema.d.ts +39 -0
- package/dist/schemas/ProductCardSchema.d.ts.map +1 -0
- package/dist/schemas/SafeSpanSchema.d.ts +13 -0
- package/dist/schemas/SafeSpanSchema.d.ts.map +1 -0
- package/dist/schemas/SectionSchema.d.ts +17 -0
- package/dist/schemas/SectionSchema.d.ts.map +1 -0
- package/dist/schemas/SelectInputFieldSchema.d.ts +27 -0
- package/dist/schemas/SelectInputFieldSchema.d.ts.map +1 -0
- package/dist/schemas/TextInputFieldSchema.d.ts +22 -0
- package/dist/schemas/TextInputFieldSchema.d.ts.map +1 -0
- package/dist/schemas/ThemeSwitcherSchema.d.ts +19 -0
- package/dist/schemas/ThemeSwitcherSchema.d.ts.map +1 -0
- package/dist/schemas/index.d.ts +33 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/types.d.ts +7 -0
- package/dist/schemas/types.d.ts.map +1 -0
- package/dist/templates/TemplateResolver.d.ts +52 -0
- package/dist/templates/TemplateResolver.d.ts.map +1 -0
- package/dist/templates/index.d.ts +7 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/tests/ConsoleWarningTest.d.ts +5 -0
- package/dist/tests/ConsoleWarningTest.d.ts.map +1 -0
- package/dist/tests/StorageKeyTest.d.ts +6 -0
- package/dist/tests/StorageKeyTest.d.ts.map +1 -0
- package/dist/tests/ThemeStorageKeyTest.d.ts +6 -0
- package/dist/tests/ThemeStorageKeyTest.d.ts.map +1 -0
- package/dist/types/CacheProvider.d.ts +18 -0
- package/dist/types/CacheProvider.d.ts.map +1 -0
- package/dist/types/ContentProxy.d.ts +47 -0
- package/dist/types/ContentProxy.d.ts.map +1 -0
- package/dist/types/DataBinding.d.ts +7 -0
- package/dist/types/DataBinding.d.ts.map +1 -0
- package/dist/types/DataProvider.d.ts +7 -0
- package/dist/types/DataProvider.d.ts.map +1 -0
- package/dist/types/DataTypes.d.ts +185 -0
- package/dist/types/DataTypes.d.ts.map +1 -0
- package/dist/types/TemplateProvider.d.ts +10 -0
- package/dist/types/TemplateProvider.d.ts.map +1 -0
- package/dist/types/TemplateResolver.d.ts +23 -0
- package/dist/types/TemplateResolver.d.ts.map +1 -0
- package/dist/types/index.d.ts +81 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/utils/breakpoints.d.ts +35 -0
- package/dist/utils/breakpoints.d.ts.map +1 -0
- package/dist/utils/customPaletteManager.d.ts +8 -0
- package/dist/utils/customPaletteManager.d.ts.map +1 -0
- package/dist/utils/dimensions.d.ts +34 -0
- package/dist/utils/dimensions.d.ts.map +1 -0
- package/dist/utils/htmlTransform.d.ts +44 -0
- package/dist/utils/htmlTransform.d.ts.map +1 -0
- package/dist/utils/index.d.ts +15 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/paletteUtils.d.ts +38 -0
- package/dist/utils/paletteUtils.d.ts.map +1 -0
- package/dist/utils/persistenceUtils.d.ts +31 -0
- package/dist/utils/persistenceUtils.d.ts.map +1 -0
- package/dist/utils/reactUtils.d.ts +24 -0
- package/dist/utils/reactUtils.d.ts.map +1 -0
- package/dist/utils/spacing.d.ts +34 -0
- package/dist/utils/spacing.d.ts.map +1 -0
- package/dist/utils/themePerformanceMonitor.d.ts +32 -0
- package/dist/utils/themePerformanceMonitor.d.ts.map +1 -0
- package/dist/utils/themeUtils.d.ts +27 -0
- package/dist/utils/themeUtils.d.ts.map +1 -0
- package/package.json +141 -0
- package/src/__tests__/components/Logo.test.js +172 -0
- package/src/__tests__/contexts/DataContext.test.js +505 -0
- package/src/__tests__/contexts/PaletteContext.test.js +115 -0
- package/src/__tests__/contexts/ThemeContext.test.js +123 -0
- package/src/__tests__/utils/paletteUtils.test.js +142 -0
- package/src/__tests__/utils/themeUtils.test.js +142 -0
- package/src/components/AccessibilityChecker.tsx +264 -0
- package/src/components/Html.tsx +191 -0
- package/src/components/Logo.css +217 -0
- package/src/components/Logo.tsx +370 -0
- package/src/components/Markdown.tsx +191 -0
- package/src/components/QwickApp.css +257 -0
- package/src/components/QwickApp.tsx +157 -0
- package/src/components/QwickAppsLogo.tsx +77 -0
- package/src/components/ResponsiveMenu.css +416 -0
- package/src/components/ResponsiveMenu.tsx +310 -0
- package/src/components/SafeSpan.tsx +128 -0
- package/src/components/Scaffold.css +541 -0
- package/src/components/Scaffold.tsx +463 -0
- package/src/components/__tests__/Article.test.tsx +419 -0
- package/src/components/__tests__/Button.test.tsx +702 -0
- package/src/components/__tests__/CardListGrid.test.tsx +478 -0
- package/src/components/__tests__/ChoiceInputField.test.tsx +864 -0
- package/src/components/__tests__/Code.test.tsx +595 -0
- package/src/components/__tests__/Content.integration.test.tsx +193 -0
- package/src/components/__tests__/Content.test.tsx +504 -0
- package/src/components/__tests__/CoverImageHeader.test.tsx +456 -0
- package/src/components/__tests__/FeatureCard.integration.test.tsx +384 -0
- package/src/components/__tests__/FeatureGrid.integration.test.tsx +364 -0
- package/src/components/__tests__/FeatureGrid.test.tsx +494 -0
- package/src/components/__tests__/Footer.test.tsx +544 -0
- package/src/components/__tests__/FormBlock.test.tsx +857 -0
- package/src/components/__tests__/HeroBlock.integration.test.tsx +272 -0
- package/src/components/__tests__/HeroBlock.test.tsx +463 -0
- package/src/components/__tests__/Html.test.tsx +174 -0
- package/src/components/__tests__/HtmlInputField.test.tsx +856 -0
- package/src/components/__tests__/Markdown.test.tsx +233 -0
- package/src/components/__tests__/PageBannerHeader.test.tsx +614 -0
- package/src/components/__tests__/PaletteSwitcher.test.tsx +864 -0
- package/src/components/__tests__/ProductCard.test.tsx +377 -0
- package/src/components/__tests__/SafeSpan.integration.test.tsx +123 -0
- package/src/components/__tests__/SafeSpan.simple.test.tsx +65 -0
- package/src/components/__tests__/SafeSpan.test.tsx +388 -0
- package/src/components/__tests__/Section.integration.test.tsx +288 -0
- package/src/components/__tests__/Section.test.tsx +494 -0
- package/src/components/__tests__/SelectInputField.test.tsx +886 -0
- package/src/components/__tests__/TextInputField.test.tsx +749 -0
- package/src/components/__tests__/ThemeSwitcher.test.tsx +777 -0
- package/src/components/blocks/Article.tsx +194 -0
- package/src/components/blocks/CardListGrid.tsx +132 -0
- package/src/components/blocks/Code.tsx +313 -0
- package/src/components/blocks/Content.tsx +265 -0
- package/src/components/blocks/CoverImageHeader.css +17 -0
- package/src/components/blocks/CoverImageHeader.tsx +435 -0
- package/src/components/blocks/FeatureCard.tsx +321 -0
- package/src/components/blocks/FeatureGrid.tsx +147 -0
- package/src/components/blocks/Footer.tsx +343 -0
- package/src/components/blocks/HeroBlock.tsx +280 -0
- package/src/components/blocks/PageBannerHeader.tsx +471 -0
- package/src/components/blocks/ProductCard.tsx +472 -0
- package/src/components/blocks/Section.tsx +209 -0
- package/src/components/blocks/index.ts +37 -0
- package/src/components/buttons/Button.tsx +233 -0
- package/src/components/buttons/PaletteSwitcher.tsx +268 -0
- package/src/components/buttons/ThemeSwitcher.tsx +283 -0
- package/src/components/buttons/index.ts +11 -0
- package/src/components/forms/FormBlock.tsx +291 -0
- package/src/components/forms/index.ts +7 -0
- package/src/components/index.ts +37 -0
- package/src/components/input/ChoiceInputField.tsx +188 -0
- package/src/components/input/HtmlInputField.tsx +326 -0
- package/src/components/input/SelectInputField.tsx +197 -0
- package/src/components/input/TextField.tsx +47 -0
- package/src/components/input/TextInputField.tsx +144 -0
- package/src/components/input/index.ts +17 -0
- package/src/components/layout/GridCell.tsx +46 -0
- package/src/components/layout/GridCellWrapper.tsx +87 -0
- package/src/components/layout/GridLayout.tsx +169 -0
- package/src/components/layout/index.ts +13 -0
- package/src/components/menu/Menu.tsx +0 -0
- package/src/components/menu/MenuItem.tsx +32 -0
- package/src/components/menu/index.ts +6 -0
- package/src/components/pages/FormPage.tsx +108 -0
- package/src/components/pages/Page.css +460 -0
- package/src/components/pages/Page.tsx +345 -0
- package/src/components/pages/index.ts +11 -0
- package/src/contexts/DataContext.tsx +355 -0
- package/src/contexts/DimensionsContext.tsx +154 -0
- package/src/contexts/PaletteContext.tsx +217 -0
- package/src/contexts/QwickAppContext.tsx +95 -0
- package/src/contexts/ThemeContext.tsx +376 -0
- package/src/contexts/index.ts +9 -0
- package/src/hooks/__tests__/useDataBinding.test.tsx.disabled +229 -0
- package/src/hooks/index.ts +11 -0
- package/src/hooks/useBaseProps.ts +267 -0
- package/src/hooks/useDataBinding.ts +77 -0
- package/src/index.ts +23 -0
- package/src/palettes/PaletteAutumn.css +172 -0
- package/src/palettes/PaletteAutumn.ts +16 -0
- package/src/palettes/PaletteCosmic.css +172 -0
- package/src/palettes/PaletteCosmic.ts +16 -0
- package/src/palettes/PaletteDefault.css +178 -0
- package/src/palettes/PaletteDefault.ts +17 -0
- package/src/palettes/PaletteOcean.css +172 -0
- package/src/palettes/PaletteOcean.ts +16 -0
- package/src/palettes/PaletteSpring.css +160 -0
- package/src/palettes/PaletteSpring.ts +16 -0
- package/src/palettes/PaletteWinter.css +172 -0
- package/src/palettes/PaletteWinter.ts +16 -0
- package/src/palettes/index.css +12 -0
- package/src/palettes/index.ts +29 -0
- package/src/schemas/ActionSchema.ts +140 -0
- package/src/schemas/ArticleSchema.ts +35 -0
- package/src/schemas/ButtonSchema.ts +99 -0
- package/src/schemas/CardListGridSchema.ts +102 -0
- package/src/schemas/ChoiceInputFieldSchema.ts +89 -0
- package/src/schemas/CodeSchema.ts +88 -0
- package/src/schemas/ContentSchema.ts +128 -0
- package/src/schemas/CoverImageHeaderSchema.ts +208 -0
- package/src/schemas/FeatureCardSchema.ts +161 -0
- package/src/schemas/FeatureGridSchema.ts +87 -0
- package/src/schemas/FeatureItemSchema.ts +68 -0
- package/src/schemas/FooterItemSchema.ts +57 -0
- package/src/schemas/FooterSchema.ts +116 -0
- package/src/schemas/FooterSectionSchema.ts +50 -0
- package/src/schemas/FormBlockSchema.ts +102 -0
- package/src/schemas/HeaderActionSchema.ts +83 -0
- package/src/schemas/HeroBlockSchema.ts +149 -0
- package/src/schemas/HtmlInputFieldSchema.ts +88 -0
- package/src/schemas/MetadataItemSchema.ts +35 -0
- package/src/schemas/PageBannerHeaderSchema.ts +206 -0
- package/src/schemas/PaletteSwitcherSchema.ts +66 -0
- package/src/schemas/ProductCardSchema.ts +264 -0
- package/src/schemas/SafeSpanSchema.ts +36 -0
- package/src/schemas/SectionSchema.ts +106 -0
- package/src/schemas/SelectInputFieldSchema.ts +137 -0
- package/src/schemas/TextInputFieldSchema.ts +129 -0
- package/src/schemas/ThemeSwitcherSchema.ts +97 -0
- package/src/schemas/__tests__/builders.test.ts +313 -0
- package/src/schemas/index.ts +34 -0
- package/src/setupTests.js +60 -0
- package/src/stories/Article.stories.tsx +549 -0
- package/src/stories/Button.stories.tsx +498 -0
- package/src/stories/CardListGrid.stories.tsx +539 -0
- package/src/stories/ChoiceInputField.stories.tsx +591 -0
- package/src/stories/Code.stories.tsx +711 -0
- package/src/stories/Content.stories.tsx +463 -0
- package/src/stories/CoverImageHeader.stories.tsx +794 -0
- package/src/stories/DataBinding.advanced.stories.tsx +548 -0
- package/src/stories/DataBinding.stories.tsx +452 -0
- package/src/stories/DataProvider.stories.tsx +1361 -0
- package/src/stories/FeatureCard.stories.tsx +642 -0
- package/src/stories/FeatureGrid.stories.tsx +669 -0
- package/src/stories/Footer.stories.tsx +724 -0
- package/src/stories/FormBlock.stories.tsx +834 -0
- package/src/stories/HeroBlock.stories.tsx +442 -0
- package/src/stories/Html.stories.tsx +264 -0
- package/src/stories/HtmlInputField.stories.tsx +558 -0
- package/src/stories/Introduction.stories.tsx +721 -0
- package/src/stories/LayoutBlocks.stories.tsx +382 -0
- package/src/stories/LayoutSystem.stories.tsx +253 -0
- package/src/stories/Logo.stories.tsx +400 -0
- package/src/stories/Markdown.stories.tsx +349 -0
- package/src/stories/Page.stories.tsx +762 -0
- package/src/stories/PageBannerHeader.stories.tsx +949 -0
- package/src/stories/PaletteSwitcher.stories.tsx +156 -0
- package/src/stories/ProductCard.stories.tsx +504 -0
- package/src/stories/QwickApp.stories.tsx +461 -0
- package/src/stories/ResponsiveMenu.stories.tsx +299 -0
- package/src/stories/SafeSpan.stories.tsx +612 -0
- package/src/stories/Section.stories.tsx +613 -0
- package/src/stories/SelectInputField.stories.tsx +605 -0
- package/src/stories/TextInputField.stories.tsx +526 -0
- package/src/stories/ThemeSwitcher.stories.tsx +170 -0
- package/src/stories/form/FormComponents.stories.tsx +588 -0
- package/src/templates/TemplateResolver.ts +156 -0
- package/src/templates/index.ts +6 -0
- package/src/tests/ConsoleWarningTest.tsx +30 -0
- package/src/tests/StorageKeyTest.tsx +110 -0
- package/src/tests/ThemeStorageKeyTest.tsx +114 -0
- package/src/types/CacheProvider.ts +14 -0
- package/src/types/ContentProxy.ts +99 -0
- package/src/types/DataTypes.ts +196 -0
- package/src/types/TemplateProvider.ts +9 -0
- package/src/types/TemplateResolver.ts +26 -0
- package/src/types/index.ts +99 -0
- package/src/utils/__tests__/createDataDrivenComponent.test.tsx.disabled +193 -0
- package/src/utils/__tests__/htmlTransform.test.tsx +255 -0
- package/src/utils/breakpoints.ts +87 -0
- package/src/utils/customPaletteManager.js +214 -0
- package/src/utils/dimensions.ts +147 -0
- package/src/utils/htmlTransform.tsx +323 -0
- package/src/utils/index.ts +16 -0
- package/src/utils/logger.ts +28 -0
- package/src/utils/paletteUtils.ts +78 -0
- package/src/utils/persistenceUtils.ts +107 -0
- package/src/utils/reactUtils.tsx +37 -0
- package/src/utils/spacing.ts +155 -0
- package/src/utils/themePerformanceMonitor.js +113 -0
- package/src/utils/themeUtils.ts +67 -0
|
@@ -0,0 +1,614 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for PageBannerHeader component
|
|
3
|
+
*
|
|
4
|
+
* Tests both traditional props usage and data binding functionality
|
|
5
|
+
* with the new schema system.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
10
|
+
import '@testing-library/jest-dom';
|
|
11
|
+
import PageBannerHeader from '../blocks/PageBannerHeader';
|
|
12
|
+
import { JsonDataProvider } from '@qwickapps/schema';
|
|
13
|
+
import { ThemeProvider, PaletteProvider } from '../../contexts';
|
|
14
|
+
import QwickApp from '../QwickApp';
|
|
15
|
+
|
|
16
|
+
// Test data for data binding - using nested structure
|
|
17
|
+
const sampleCmsData = {
|
|
18
|
+
'pageBannerHeaders': {
|
|
19
|
+
'aboutBanner': {
|
|
20
|
+
coverImage: '/images/about-banner.jpg',
|
|
21
|
+
coverImageAlt: 'About us banner',
|
|
22
|
+
profileImage: '/images/company-logo.jpg',
|
|
23
|
+
profileImageAlt: 'Company logo',
|
|
24
|
+
profileImageSize: 'large',
|
|
25
|
+
overline: 'About Us',
|
|
26
|
+
title: 'QwickApps React Framework',
|
|
27
|
+
subtitle: 'Building the future of web development',
|
|
28
|
+
metadata: [
|
|
29
|
+
{ label: 'Developers', value: '50+' },
|
|
30
|
+
{ label: 'Projects', value: '1000+' }
|
|
31
|
+
],
|
|
32
|
+
tags: ['React', 'TypeScript', 'Material-UI', 'Open Source'],
|
|
33
|
+
maxVisibleActions: 2,
|
|
34
|
+
height: 300,
|
|
35
|
+
profilePosition: 'bottom-left'
|
|
36
|
+
},
|
|
37
|
+
'teamHero': {
|
|
38
|
+
coverImage: '/images/team-banner.jpg',
|
|
39
|
+
title: 'Meet Our Team',
|
|
40
|
+
subtitle: 'Passionate developers creating amazing software',
|
|
41
|
+
profilePosition: 'overlay-center',
|
|
42
|
+
height: 250
|
|
43
|
+
},
|
|
44
|
+
'minimalHeader': {
|
|
45
|
+
title: 'Simple Header',
|
|
46
|
+
subtitle: 'Clean and minimal design',
|
|
47
|
+
profilePosition: 'bottom-center'
|
|
48
|
+
},
|
|
49
|
+
'emptyData': {},
|
|
50
|
+
'loadingTest': {
|
|
51
|
+
title: 'Loading Test',
|
|
52
|
+
subtitle: 'Testing loading state behavior'
|
|
53
|
+
},
|
|
54
|
+
'errorTest': {
|
|
55
|
+
title: 'Error Test',
|
|
56
|
+
subtitle: 'Testing error state behavior'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Mock HeaderAction type
|
|
62
|
+
const mockActions = [
|
|
63
|
+
{
|
|
64
|
+
id: 'primary',
|
|
65
|
+
label: 'Primary Action',
|
|
66
|
+
priority: 1,
|
|
67
|
+
onClick: jest.fn(),
|
|
68
|
+
disabled: false,
|
|
69
|
+
destructive: false
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 'secondary',
|
|
73
|
+
label: 'Secondary Action',
|
|
74
|
+
priority: 2,
|
|
75
|
+
onClick: jest.fn(),
|
|
76
|
+
disabled: false,
|
|
77
|
+
destructive: false
|
|
78
|
+
}
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
// Wrapper component for tests that need providers
|
|
82
|
+
const TestWrapper: React.FC<{ children: React.ReactNode; dataProvider?: any }> = ({
|
|
83
|
+
children,
|
|
84
|
+
dataProvider
|
|
85
|
+
}) => (
|
|
86
|
+
<ThemeProvider>
|
|
87
|
+
<PaletteProvider>
|
|
88
|
+
{dataProvider ? (
|
|
89
|
+
<QwickApp appId="test-pagebanner" appName="PageBannerHeader Test" dataSource={{ dataProvider }}>
|
|
90
|
+
{children}
|
|
91
|
+
</QwickApp>
|
|
92
|
+
) : (
|
|
93
|
+
children
|
|
94
|
+
)}
|
|
95
|
+
</PaletteProvider>
|
|
96
|
+
</ThemeProvider>
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
describe('PageBannerHeader', () => {
|
|
100
|
+
describe('Traditional Props Usage', () => {
|
|
101
|
+
it('renders basic header with title only', () => {
|
|
102
|
+
render(
|
|
103
|
+
<TestWrapper>
|
|
104
|
+
<PageBannerHeader title="Basic Header" />
|
|
105
|
+
</TestWrapper>
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
expect(screen.getByText('Basic Header')).toBeInTheDocument();
|
|
109
|
+
expect(screen.getByRole('banner')).toBeInTheDocument();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('renders full header with all props', () => {
|
|
113
|
+
render(
|
|
114
|
+
<TestWrapper>
|
|
115
|
+
<PageBannerHeader
|
|
116
|
+
coverImage="/test-cover.jpg"
|
|
117
|
+
coverImageAlt="Test cover"
|
|
118
|
+
profileImage="/test-profile.jpg"
|
|
119
|
+
profileImageAlt="Test profile"
|
|
120
|
+
overline="Test Overline"
|
|
121
|
+
title="Full Header"
|
|
122
|
+
subtitle="Complete header with all features"
|
|
123
|
+
metadata={[
|
|
124
|
+
{ label: 'followers', value: '1.2k' },
|
|
125
|
+
{ label: 'posts', value: 42 }
|
|
126
|
+
]}
|
|
127
|
+
tags={['React', 'TypeScript']}
|
|
128
|
+
actions={mockActions}
|
|
129
|
+
/>
|
|
130
|
+
</TestWrapper>
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
expect(screen.getByText('Test Overline')).toBeInTheDocument();
|
|
134
|
+
expect(screen.getByText('Full Header')).toBeInTheDocument();
|
|
135
|
+
expect(screen.getByText('Complete header with all features')).toBeInTheDocument();
|
|
136
|
+
expect(screen.getByText('1.2k')).toBeInTheDocument();
|
|
137
|
+
expect(screen.getByText('followers')).toBeInTheDocument();
|
|
138
|
+
expect(screen.getByText('42')).toBeInTheDocument();
|
|
139
|
+
expect(screen.getByText('posts')).toBeInTheDocument();
|
|
140
|
+
expect(screen.getByText('React')).toBeInTheDocument();
|
|
141
|
+
expect(screen.getByText('TypeScript')).toBeInTheDocument();
|
|
142
|
+
expect(screen.getByText('Primary Action')).toBeInTheDocument();
|
|
143
|
+
expect(screen.getByText('Secondary Action')).toBeInTheDocument();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('renders with different profile image sizes', () => {
|
|
147
|
+
const sizes = ['small', 'medium', 'large'] as const;
|
|
148
|
+
|
|
149
|
+
sizes.forEach(size => {
|
|
150
|
+
const { unmount } = render(
|
|
151
|
+
<TestWrapper>
|
|
152
|
+
<PageBannerHeader
|
|
153
|
+
title={`${size} profile`}
|
|
154
|
+
profileImage="/test-profile.jpg"
|
|
155
|
+
profileImageSize={size}
|
|
156
|
+
/>
|
|
157
|
+
</TestWrapper>
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
expect(screen.getByText(`${size} profile`)).toBeInTheDocument();
|
|
161
|
+
|
|
162
|
+
unmount();
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('renders with different profile positions', () => {
|
|
167
|
+
const positions = ['bottom-left', 'bottom-center', 'overlay-center'] as const;
|
|
168
|
+
|
|
169
|
+
positions.forEach(position => {
|
|
170
|
+
const { unmount } = render(
|
|
171
|
+
<TestWrapper>
|
|
172
|
+
<PageBannerHeader
|
|
173
|
+
title={`${position} position`}
|
|
174
|
+
profileImage="/test-profile.jpg"
|
|
175
|
+
profilePosition={position}
|
|
176
|
+
/>
|
|
177
|
+
</TestWrapper>
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
expect(screen.getByText(`${position} position`)).toBeInTheDocument();
|
|
181
|
+
|
|
182
|
+
unmount();
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('handles action button clicks', () => {
|
|
187
|
+
const handleClick = jest.fn();
|
|
188
|
+
const actionWithClick = [{
|
|
189
|
+
id: 'test',
|
|
190
|
+
label: 'Click Me',
|
|
191
|
+
priority: 1,
|
|
192
|
+
onClick: handleClick,
|
|
193
|
+
disabled: false,
|
|
194
|
+
destructive: false
|
|
195
|
+
}];
|
|
196
|
+
|
|
197
|
+
render(
|
|
198
|
+
<TestWrapper>
|
|
199
|
+
<PageBannerHeader
|
|
200
|
+
title="Action Test"
|
|
201
|
+
actions={actionWithClick}
|
|
202
|
+
/>
|
|
203
|
+
</TestWrapper>
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
const button = screen.getByText('Click Me');
|
|
207
|
+
fireEvent.click(button);
|
|
208
|
+
|
|
209
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('handles overflow actions with menu', () => {
|
|
213
|
+
const manyActions = Array.from({ length: 5 }, (_, i) => ({
|
|
214
|
+
id: `action-${i}`,
|
|
215
|
+
label: `Action ${i + 1}`,
|
|
216
|
+
priority: i + 1,
|
|
217
|
+
onClick: jest.fn(),
|
|
218
|
+
disabled: false,
|
|
219
|
+
destructive: false
|
|
220
|
+
}));
|
|
221
|
+
|
|
222
|
+
render(
|
|
223
|
+
<TestWrapper>
|
|
224
|
+
<PageBannerHeader
|
|
225
|
+
title="Overflow Test"
|
|
226
|
+
actions={manyActions}
|
|
227
|
+
maxVisibleActions={2}
|
|
228
|
+
/>
|
|
229
|
+
</TestWrapper>
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
// First 2 actions should be visible
|
|
233
|
+
expect(screen.getByText('Action 1')).toBeInTheDocument();
|
|
234
|
+
expect(screen.getByText('Action 2')).toBeInTheDocument();
|
|
235
|
+
|
|
236
|
+
// Overflow menu button should be present
|
|
237
|
+
const menuButton = screen.getByLabelText('More actions');
|
|
238
|
+
expect(menuButton).toBeInTheDocument();
|
|
239
|
+
|
|
240
|
+
// Click to open menu
|
|
241
|
+
fireEvent.click(menuButton);
|
|
242
|
+
|
|
243
|
+
// Remaining actions should be in the menu
|
|
244
|
+
expect(screen.getByText('Action 3')).toBeInTheDocument();
|
|
245
|
+
expect(screen.getByText('Action 4')).toBeInTheDocument();
|
|
246
|
+
expect(screen.getByText('Action 5')).toBeInTheDocument();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('renders with custom height', () => {
|
|
250
|
+
const { container } = render(
|
|
251
|
+
<TestWrapper>
|
|
252
|
+
<PageBannerHeader
|
|
253
|
+
title="Custom Height"
|
|
254
|
+
coverImage="/test-cover.jpg"
|
|
255
|
+
height={400}
|
|
256
|
+
/>
|
|
257
|
+
</TestWrapper>
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
// Check that the component renders without errors
|
|
261
|
+
expect(screen.getByText('Custom Height')).toBeInTheDocument();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('supports grid props', () => {
|
|
265
|
+
const { container } = render(
|
|
266
|
+
<TestWrapper>
|
|
267
|
+
<PageBannerHeader
|
|
268
|
+
title="Grid Test"
|
|
269
|
+
span={6}
|
|
270
|
+
xs={12}
|
|
271
|
+
md={8}
|
|
272
|
+
/>
|
|
273
|
+
</TestWrapper>
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
const element = container.querySelector('[data-grid-span]');
|
|
277
|
+
expect(element).toHaveAttribute('data-grid-span', '6');
|
|
278
|
+
expect(element).toBeInTheDocument();
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('handles profile image as React node', () => {
|
|
282
|
+
const CustomProfile = () => <div>Custom Profile</div>;
|
|
283
|
+
|
|
284
|
+
render(
|
|
285
|
+
<TestWrapper>
|
|
286
|
+
<PageBannerHeader
|
|
287
|
+
title="Custom Profile Test"
|
|
288
|
+
profileImage={<CustomProfile />}
|
|
289
|
+
/>
|
|
290
|
+
</TestWrapper>
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
expect(screen.getByText('Custom Profile Test')).toBeInTheDocument();
|
|
294
|
+
expect(screen.getByText('Custom Profile')).toBeInTheDocument();
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it('handles destructive actions', () => {
|
|
298
|
+
const destructiveAction = [{
|
|
299
|
+
id: 'delete',
|
|
300
|
+
label: 'Delete',
|
|
301
|
+
priority: 1,
|
|
302
|
+
onClick: jest.fn(),
|
|
303
|
+
disabled: false,
|
|
304
|
+
destructive: true
|
|
305
|
+
}];
|
|
306
|
+
|
|
307
|
+
render(
|
|
308
|
+
<TestWrapper>
|
|
309
|
+
<PageBannerHeader
|
|
310
|
+
title="Destructive Action Test"
|
|
311
|
+
actions={destructiveAction}
|
|
312
|
+
/>
|
|
313
|
+
</TestWrapper>
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
expect(screen.getByText('Delete')).toBeInTheDocument();
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('handles disabled actions', () => {
|
|
320
|
+
const disabledAction = [{
|
|
321
|
+
id: 'disabled',
|
|
322
|
+
label: 'Disabled',
|
|
323
|
+
priority: 1,
|
|
324
|
+
onClick: jest.fn(),
|
|
325
|
+
disabled: true,
|
|
326
|
+
destructive: false
|
|
327
|
+
}];
|
|
328
|
+
|
|
329
|
+
render(
|
|
330
|
+
<TestWrapper>
|
|
331
|
+
<PageBannerHeader
|
|
332
|
+
title="Disabled Action Test"
|
|
333
|
+
actions={disabledAction}
|
|
334
|
+
/>
|
|
335
|
+
</TestWrapper>
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
const button = screen.getByText('Disabled');
|
|
339
|
+
expect(button).toBeDisabled();
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it('renders without cover image', () => {
|
|
343
|
+
render(
|
|
344
|
+
<TestWrapper>
|
|
345
|
+
<PageBannerHeader
|
|
346
|
+
title="No Cover Image"
|
|
347
|
+
subtitle="Just title and subtitle"
|
|
348
|
+
/>
|
|
349
|
+
</TestWrapper>
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
expect(screen.getByText('No Cover Image')).toBeInTheDocument();
|
|
353
|
+
expect(screen.getByText('Just title and subtitle')).toBeInTheDocument();
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('renders with tags as React nodes', () => {
|
|
357
|
+
const customTags = [
|
|
358
|
+
'String Tag',
|
|
359
|
+
<span key="custom">Custom Tag</span>
|
|
360
|
+
];
|
|
361
|
+
|
|
362
|
+
render(
|
|
363
|
+
<TestWrapper>
|
|
364
|
+
<PageBannerHeader
|
|
365
|
+
title="Custom Tags Test"
|
|
366
|
+
tags={customTags}
|
|
367
|
+
/>
|
|
368
|
+
</TestWrapper>
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
expect(screen.getByText('Custom Tags Test')).toBeInTheDocument();
|
|
372
|
+
expect(screen.getByText('String Tag')).toBeInTheDocument();
|
|
373
|
+
expect(screen.getByText('Custom Tag')).toBeInTheDocument();
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
describe('Data Binding Usage', () => {
|
|
378
|
+
let dataProvider: JsonDataProvider;
|
|
379
|
+
|
|
380
|
+
beforeEach(() => {
|
|
381
|
+
dataProvider = new JsonDataProvider({ data: sampleCmsData });
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it('renders with dataSource prop (about banner)', async () => {
|
|
385
|
+
render(
|
|
386
|
+
<TestWrapper dataProvider={dataProvider}>
|
|
387
|
+
<PageBannerHeader dataSource="pageBannerHeaders.aboutBanner" />
|
|
388
|
+
</TestWrapper>
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
await screen.findByText('QwickApps React Framework');
|
|
392
|
+
expect(screen.getByText('About Us')).toBeInTheDocument();
|
|
393
|
+
expect(screen.getByText('Building the future of web development')).toBeInTheDocument();
|
|
394
|
+
expect(screen.getByText('50+')).toBeInTheDocument();
|
|
395
|
+
expect(screen.getByText('Developers')).toBeInTheDocument();
|
|
396
|
+
expect(screen.getByText('React')).toBeInTheDocument();
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it('renders with dataSource prop (team hero)', async () => {
|
|
400
|
+
render(
|
|
401
|
+
<TestWrapper dataProvider={dataProvider}>
|
|
402
|
+
<PageBannerHeader dataSource="pageBannerHeaders.teamHero" />
|
|
403
|
+
</TestWrapper>
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
await screen.findByText('Meet Our Team');
|
|
407
|
+
expect(screen.getByText('Passionate developers creating amazing software')).toBeInTheDocument();
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
it('shows loading state while data is loading', () => {
|
|
411
|
+
render(
|
|
412
|
+
<TestWrapper dataProvider={dataProvider}>
|
|
413
|
+
<PageBannerHeader dataSource="pageBannerHeaders.nonexistent" />
|
|
414
|
+
</TestWrapper>
|
|
415
|
+
);
|
|
416
|
+
|
|
417
|
+
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
|
418
|
+
expect(screen.getByText('Loading page banner content...')).toBeInTheDocument();
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it('shows loading state when dataSource does not exist', async () => {
|
|
422
|
+
render(
|
|
423
|
+
<TestWrapper dataProvider={dataProvider}>
|
|
424
|
+
<PageBannerHeader
|
|
425
|
+
dataSource="pageBannerHeaders.nonexistent"
|
|
426
|
+
title="Fallback Title"
|
|
427
|
+
subtitle="Fallback subtitle"
|
|
428
|
+
/>
|
|
429
|
+
</TestWrapper>
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
// When dataSource doesn't exist, component shows loading state
|
|
433
|
+
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
|
434
|
+
expect(screen.getByText('Loading page banner content...')).toBeInTheDocument();
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it('handles minimal header from data', async () => {
|
|
438
|
+
render(
|
|
439
|
+
<TestWrapper dataProvider={dataProvider}>
|
|
440
|
+
<PageBannerHeader dataSource="pageBannerHeaders.minimalHeader" />
|
|
441
|
+
</TestWrapper>
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
await screen.findByText('Simple Header');
|
|
445
|
+
expect(screen.getByText('Clean and minimal design')).toBeInTheDocument();
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
it('works with custom binding options', async () => {
|
|
449
|
+
render(
|
|
450
|
+
<TestWrapper dataProvider={dataProvider}>
|
|
451
|
+
<PageBannerHeader
|
|
452
|
+
dataSource="pageBannerHeaders.aboutBanner"
|
|
453
|
+
bindingOptions={{ cache: false, strict: true }}
|
|
454
|
+
/>
|
|
455
|
+
</TestWrapper>
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
await screen.findByText('QwickApps React Framework');
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
it('handles empty data from CMS', async () => {
|
|
462
|
+
render(
|
|
463
|
+
<TestWrapper dataProvider={dataProvider}>
|
|
464
|
+
<PageBannerHeader
|
|
465
|
+
dataSource="pageBannerHeaders.emptyData"
|
|
466
|
+
title="Fallback for Empty Data"
|
|
467
|
+
/>
|
|
468
|
+
</TestWrapper>
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
await screen.findByText('Fallback for Empty Data');
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
it('shows error state in development mode', () => {
|
|
475
|
+
// Mock console.error to avoid test noise
|
|
476
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
477
|
+
|
|
478
|
+
// Mock process.env.NODE_ENV
|
|
479
|
+
const originalEnv = process.env.NODE_ENV;
|
|
480
|
+
process.env.NODE_ENV = 'development';
|
|
481
|
+
|
|
482
|
+
// Create an empty data provider which should cause loading/error state
|
|
483
|
+
const emptyDataProvider = new JsonDataProvider({ data: {} });
|
|
484
|
+
|
|
485
|
+
render(
|
|
486
|
+
<TestWrapper dataProvider={emptyDataProvider}>
|
|
487
|
+
<PageBannerHeader dataSource="pageBannerHeaders.nonexistentData" />
|
|
488
|
+
</TestWrapper>
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
// Should show loading initially, then fallback to null or show fallback content
|
|
492
|
+
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
|
493
|
+
|
|
494
|
+
// Restore environment
|
|
495
|
+
process.env.NODE_ENV = originalEnv;
|
|
496
|
+
consoleSpy.mockRestore();
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
it('returns loading state when no data provider available', () => {
|
|
500
|
+
// Mock console.error to avoid test noise
|
|
501
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
502
|
+
|
|
503
|
+
// Mock process.env.NODE_ENV
|
|
504
|
+
const originalEnv = process.env.NODE_ENV;
|
|
505
|
+
process.env.NODE_ENV = 'production';
|
|
506
|
+
|
|
507
|
+
const emptyDataProvider = new JsonDataProvider({ data: {} });
|
|
508
|
+
|
|
509
|
+
const { container } = render(
|
|
510
|
+
<TestWrapper dataProvider={emptyDataProvider}>
|
|
511
|
+
<PageBannerHeader dataSource="pageBannerHeaders.nonexistentData" />
|
|
512
|
+
</TestWrapper>
|
|
513
|
+
);
|
|
514
|
+
|
|
515
|
+
// Should show loading state when data is not available
|
|
516
|
+
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
|
517
|
+
|
|
518
|
+
// Restore environment
|
|
519
|
+
process.env.NODE_ENV = originalEnv;
|
|
520
|
+
consoleSpy.mockRestore();
|
|
521
|
+
});
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
describe('Edge Cases', () => {
|
|
525
|
+
it('handles empty metadata array', () => {
|
|
526
|
+
render(
|
|
527
|
+
<TestWrapper>
|
|
528
|
+
<PageBannerHeader
|
|
529
|
+
title="Empty Metadata"
|
|
530
|
+
metadata={[]}
|
|
531
|
+
/>
|
|
532
|
+
</TestWrapper>
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
expect(screen.getByText('Empty Metadata')).toBeInTheDocument();
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
it('handles empty tags array', () => {
|
|
539
|
+
render(
|
|
540
|
+
<TestWrapper>
|
|
541
|
+
<PageBannerHeader
|
|
542
|
+
title="Empty Tags"
|
|
543
|
+
tags={[]}
|
|
544
|
+
/>
|
|
545
|
+
</TestWrapper>
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
expect(screen.getByText('Empty Tags')).toBeInTheDocument();
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
it('handles empty actions array', () => {
|
|
552
|
+
render(
|
|
553
|
+
<TestWrapper>
|
|
554
|
+
<PageBannerHeader
|
|
555
|
+
title="Empty Actions"
|
|
556
|
+
actions={[]}
|
|
557
|
+
/>
|
|
558
|
+
</TestWrapper>
|
|
559
|
+
);
|
|
560
|
+
|
|
561
|
+
expect(screen.getByText('Empty Actions')).toBeInTheDocument();
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
it('handles long title text', () => {
|
|
565
|
+
const longTitle = 'Very '.repeat(20) + 'Long Title That Should Handle Wrapping Properly';
|
|
566
|
+
|
|
567
|
+
render(
|
|
568
|
+
<TestWrapper>
|
|
569
|
+
<PageBannerHeader title={longTitle} />
|
|
570
|
+
</TestWrapper>
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
expect(screen.getByText(longTitle)).toBeInTheDocument();
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
it('handles special characters in content', () => {
|
|
577
|
+
render(
|
|
578
|
+
<TestWrapper>
|
|
579
|
+
<PageBannerHeader
|
|
580
|
+
title="Special: <>&"'"
|
|
581
|
+
subtitle="Content with special chars: & < >"
|
|
582
|
+
/>
|
|
583
|
+
</TestWrapper>
|
|
584
|
+
);
|
|
585
|
+
|
|
586
|
+
expect(screen.getByText(/Special:/, { exact: false })).toBeInTheDocument();
|
|
587
|
+
expect(screen.getByText(/Content with special chars:/, { exact: false })).toBeInTheDocument();
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
it('handles custom CSS classes and styles', () => {
|
|
591
|
+
const { container } = render(
|
|
592
|
+
<TestWrapper>
|
|
593
|
+
<PageBannerHeader
|
|
594
|
+
title="Custom Styled"
|
|
595
|
+
className="custom-header"
|
|
596
|
+
sx={{ border: '1px solid red' }}
|
|
597
|
+
/>
|
|
598
|
+
</TestWrapper>
|
|
599
|
+
);
|
|
600
|
+
|
|
601
|
+
expect(screen.getByText('Custom Styled')).toBeInTheDocument();
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
it('renders without optional props', () => {
|
|
605
|
+
render(
|
|
606
|
+
<TestWrapper>
|
|
607
|
+
<PageBannerHeader title="Minimal Props" />
|
|
608
|
+
</TestWrapper>
|
|
609
|
+
);
|
|
610
|
+
|
|
611
|
+
expect(screen.getByText('Minimal Props')).toBeInTheDocument();
|
|
612
|
+
});
|
|
613
|
+
});
|
|
614
|
+
});
|