@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,505 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataContext Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests the React Context integration for DataProvider including:
|
|
5
|
+
* - Context provider functionality
|
|
6
|
+
* - Custom hooks (useData, useResolveTemplate)
|
|
7
|
+
* - Tagged template function (t) and t.wrap
|
|
8
|
+
* - Error handling for missing provider
|
|
9
|
+
* - Loading states
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { JsonDataProvider } from '@qwickapps/schema';
|
|
13
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
14
|
+
import {
|
|
15
|
+
DataProvider,
|
|
16
|
+
t,
|
|
17
|
+
useData,
|
|
18
|
+
useDataProvider,
|
|
19
|
+
useResolveTemplate,
|
|
20
|
+
useTemplate
|
|
21
|
+
} from '../../contexts/DataContext';
|
|
22
|
+
|
|
23
|
+
// Test components for hook testing
|
|
24
|
+
const TestUseData = ({ fieldGroupId }) => {
|
|
25
|
+
const { data, loading, error } = useData(fieldGroupId);
|
|
26
|
+
|
|
27
|
+
if (loading) return <div data-testid="loading">Loading...</div>;
|
|
28
|
+
if (error) return <div data-testid="error">{error.message}</div>;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div data-testid="content">
|
|
32
|
+
{data.map((item, index) => (
|
|
33
|
+
<div key={index} data-testid={`item-${index}`}>
|
|
34
|
+
{item.title || item.name || 'Untitled'}
|
|
35
|
+
</div>
|
|
36
|
+
))}
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const TestUseResolveTemplate = ({ template }) => {
|
|
42
|
+
const { resolved, loading, error } = useResolveTemplate(template);
|
|
43
|
+
|
|
44
|
+
if (loading) return <div data-testid="loading">Loading...</div>;
|
|
45
|
+
if (error) return <div data-testid="error">{error.message}</div>;
|
|
46
|
+
|
|
47
|
+
return <div data-testid="resolved">{resolved}</div>;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const TestUseDataProvider = () => {
|
|
51
|
+
const provider = useDataProvider();
|
|
52
|
+
return <div data-testid="provider-type">{provider.constructor.name}</div>;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const TestErrorBoundary = ({ children }) => {
|
|
56
|
+
try {
|
|
57
|
+
return children;
|
|
58
|
+
} catch (error) {
|
|
59
|
+
return <div data-testid="context-error">{error.message}</div>;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
describe.skip('DataContext', () => {
|
|
64
|
+
let mockDataSource;
|
|
65
|
+
|
|
66
|
+
beforeEach(() => {
|
|
67
|
+
mockDataSource = {
|
|
68
|
+
dataProvider: new JsonDataProvider({
|
|
69
|
+
data: {
|
|
70
|
+
company: [
|
|
71
|
+
{ name: 'QwickApps', founded: 2025, industry: 'Software' }
|
|
72
|
+
],
|
|
73
|
+
features: [
|
|
74
|
+
{ title: 'Fast', description: 'Lightning speed' },
|
|
75
|
+
{ title: 'Secure', description: 'Bank-level security' }
|
|
76
|
+
],
|
|
77
|
+
empty: []
|
|
78
|
+
}
|
|
79
|
+
}),
|
|
80
|
+
cacheProvider: false, // Disable caching for tests
|
|
81
|
+
enableLogging: false
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('DataProvider Component', () => {
|
|
86
|
+
it('should provide data context to children', async () => {
|
|
87
|
+
render(
|
|
88
|
+
<DataProvider dataSource={mockDataSource}>
|
|
89
|
+
<TestUseData fieldGroupId="company" />
|
|
90
|
+
</DataProvider>
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// Initially loading
|
|
94
|
+
expect(screen.getByTestId('loading')).toBeInTheDocument();
|
|
95
|
+
|
|
96
|
+
// Wait for data to load
|
|
97
|
+
await waitFor(() => {
|
|
98
|
+
expect(screen.getByTestId('content')).toBeInTheDocument();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
expect(screen.getByTestId('item-0')).toHaveTextContent('QwickApps');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should throw error when useDataContext used outside provider', () => {
|
|
105
|
+
// Mock console.error to avoid noise in test output
|
|
106
|
+
const originalError = console.error;
|
|
107
|
+
console.error = jest.fn();
|
|
108
|
+
|
|
109
|
+
expect(() => {
|
|
110
|
+
render(<TestUseData fieldGroupId="company" />);
|
|
111
|
+
}).toThrow('useDataContext must be used within a DataProvider');
|
|
112
|
+
|
|
113
|
+
console.error = originalError;
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('useData Hook', () => {
|
|
118
|
+
const renderWithProvider = (component) => {
|
|
119
|
+
return render(
|
|
120
|
+
<DataProvider dataSource={mockDataSource}>
|
|
121
|
+
{component}
|
|
122
|
+
</DataProvider>
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
it('should fetch and return data', async () => {
|
|
127
|
+
renderWithProvider(<TestUseData fieldGroupId="features" />);
|
|
128
|
+
|
|
129
|
+
await waitFor(() => {
|
|
130
|
+
expect(screen.getByTestId('content')).toBeInTheDocument();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
expect(screen.getByTestId('item-0')).toHaveTextContent('Fast');
|
|
134
|
+
expect(screen.getByTestId('item-1')).toHaveTextContent('Secure');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should handle empty field group', async () => {
|
|
138
|
+
renderWithProvider(<TestUseData fieldGroupId="empty" />);
|
|
139
|
+
|
|
140
|
+
await waitFor(() => {
|
|
141
|
+
expect(screen.getByTestId('content')).toBeInTheDocument();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Should render container but no items
|
|
145
|
+
expect(screen.queryByTestId('item-0')).not.toBeInTheDocument();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should handle non-existent field group', async () => {
|
|
149
|
+
renderWithProvider(<TestUseData fieldGroupId="nonexistent" />);
|
|
150
|
+
|
|
151
|
+
await waitFor(() => {
|
|
152
|
+
expect(screen.getByTestId('content')).toBeInTheDocument();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
expect(screen.queryByTestId('item-0')).not.toBeInTheDocument();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should show loading state initially', () => {
|
|
159
|
+
renderWithProvider(<TestUseData fieldGroupId="company" />);
|
|
160
|
+
expect(screen.getByTestId('loading')).toBeInTheDocument();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should handle provider errors', async () => {
|
|
164
|
+
const errorDataProvider = {
|
|
165
|
+
getData: jest.fn().mockRejectedValue(new Error('Provider error')),
|
|
166
|
+
clearCache: jest.fn()
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const errorDataSource = {
|
|
170
|
+
dataProvider: errorDataProvider,
|
|
171
|
+
cacheProvider: false,
|
|
172
|
+
enableLogging: false
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
render(
|
|
176
|
+
<DataProvider dataSource={errorDataSource}>
|
|
177
|
+
<TestUseData fieldGroupId="company" />
|
|
178
|
+
</DataProvider>
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
await waitFor(() => {
|
|
182
|
+
expect(screen.getByTestId('error')).toBeInTheDocument();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
expect(screen.getByTestId('error')).toHaveTextContent('Provider error');
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe('useResolveTemplate Hook', () => {
|
|
190
|
+
const renderWithProvider = (component) => {
|
|
191
|
+
return render(
|
|
192
|
+
<DataProvider dataSource={mockDataSource}>
|
|
193
|
+
{component}
|
|
194
|
+
</DataProvider>
|
|
195
|
+
);
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
it('should resolve simple templates', async () => {
|
|
199
|
+
renderWithProvider(<TestUseResolveTemplate template="Welcome to {{company.name}}!" />);
|
|
200
|
+
|
|
201
|
+
await waitFor(() => {
|
|
202
|
+
expect(screen.getByTestId('resolved')).toBeInTheDocument();
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
expect(screen.getByTestId('resolved')).toHaveTextContent('Welcome to QwickApps!');
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('should handle templates without mustache syntax', async () => {
|
|
209
|
+
renderWithProvider(<TestUseResolveTemplate template="Plain text" />);
|
|
210
|
+
|
|
211
|
+
// Should resolve immediately without loading
|
|
212
|
+
expect(screen.getByTestId('resolved')).toHaveTextContent('Plain text');
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('should show loading state for complex templates', () => {
|
|
216
|
+
renderWithProvider(<TestUseResolveTemplate template="{{company.name}} - {{company.industry}}" />);
|
|
217
|
+
|
|
218
|
+
// May show loading briefly
|
|
219
|
+
const loading = screen.queryByTestId('loading');
|
|
220
|
+
const resolved = screen.queryByTestId('resolved');
|
|
221
|
+
|
|
222
|
+
expect(loading || resolved).toBeInTheDocument();
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('should handle template resolution errors', async () => {
|
|
226
|
+
const errorTemplateResolver = {
|
|
227
|
+
resolve: jest.fn().mockImplementation(() => {
|
|
228
|
+
throw new Error('Template error');
|
|
229
|
+
})
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const errorDataSource = {
|
|
233
|
+
dataProvider: new JsonDataProvider({ data: {} }),
|
|
234
|
+
templateResolver: errorTemplateResolver,
|
|
235
|
+
cacheProvider: false,
|
|
236
|
+
enableLogging: false
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
render(
|
|
240
|
+
<DataProvider dataSource={errorDataSource}>
|
|
241
|
+
<TestUseResolveTemplate template="{{company.name}}" />
|
|
242
|
+
</DataProvider>
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
await waitFor(() => {
|
|
246
|
+
expect(screen.getByTestId('error')).toBeInTheDocument();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
expect(screen.getByTestId('error')).toHaveTextContent('Template error');
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
describe('useDataProvider Hook', () => {
|
|
254
|
+
it('should return the provider instance', () => {
|
|
255
|
+
render(
|
|
256
|
+
<DataProvider dataSource={mockDataSource}>
|
|
257
|
+
<TestUseDataProvider />
|
|
258
|
+
</DataProvider>
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
expect(screen.getByTestId('provider-type')).toHaveTextContent('TemplateResolver');
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('should throw error when used outside provider', () => {
|
|
265
|
+
const originalError = console.error;
|
|
266
|
+
console.error = jest.fn();
|
|
267
|
+
|
|
268
|
+
expect(() => {
|
|
269
|
+
render(<TestUseDataProvider />);
|
|
270
|
+
}).toThrow('useDataContext must be used within a DataProvider');
|
|
271
|
+
|
|
272
|
+
console.error = originalError;
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
describe('Tagged Template Function (t)', () => {
|
|
277
|
+
const TestTaggedTemplate = ({ template, fallback }) => {
|
|
278
|
+
return (
|
|
279
|
+
<div data-testid="template-result">
|
|
280
|
+
{template || fallback || 'No content'}
|
|
281
|
+
</div>
|
|
282
|
+
);
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const renderWithProvider = (component) => {
|
|
286
|
+
return render(
|
|
287
|
+
<DataProvider dataSource={mockDataSource}>
|
|
288
|
+
{component}
|
|
289
|
+
</DataProvider>
|
|
290
|
+
);
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
it('should resolve and render templates', async () => {
|
|
294
|
+
const TestComponent = () => (
|
|
295
|
+
<div data-testid="template-result">
|
|
296
|
+
{t`Founded in {{company.founded}}`}
|
|
297
|
+
</div>
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
renderWithProvider(<TestComponent />);
|
|
301
|
+
|
|
302
|
+
await waitFor(() => {
|
|
303
|
+
expect(screen.getByText('Founded in 2025')).toBeInTheDocument();
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('should support fallback with || operator', async () => {
|
|
308
|
+
const TestComponent = () => {
|
|
309
|
+
const resolved = useTemplate('{{nonexistent.property}}');
|
|
310
|
+
return (
|
|
311
|
+
<div data-testid="template-result">
|
|
312
|
+
{resolved || 'Default fallback'}
|
|
313
|
+
</div>
|
|
314
|
+
);
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
renderWithProvider(<TestComponent />);
|
|
318
|
+
|
|
319
|
+
await waitFor(() => {
|
|
320
|
+
expect(screen.getByText('Default fallback')).toBeInTheDocument();
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
it('should show error details in development', async () => {
|
|
325
|
+
const originalEnv = process.env.NODE_ENV;
|
|
326
|
+
process.env.NODE_ENV = 'development';
|
|
327
|
+
|
|
328
|
+
const errorTemplateResolver = {
|
|
329
|
+
resolve: jest.fn().mockImplementation(() => {
|
|
330
|
+
throw new Error('Template error');
|
|
331
|
+
})
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
const errorDataSource = {
|
|
335
|
+
dataProvider: new JsonDataProvider({ data: {} }),
|
|
336
|
+
templateResolver: errorTemplateResolver,
|
|
337
|
+
cacheProvider: false,
|
|
338
|
+
enableLogging: false
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const TestComponent = () => (
|
|
342
|
+
<div data-testid="template-result">
|
|
343
|
+
{t`{{error.template}}`}
|
|
344
|
+
</div>
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
render(
|
|
348
|
+
<DataProvider dataSource={errorDataSource}>
|
|
349
|
+
<TestComponent />
|
|
350
|
+
</DataProvider>
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
await waitFor(() => {
|
|
354
|
+
expect(screen.getByText('[Template Error: Template error]')).toBeInTheDocument();
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
process.env.NODE_ENV = originalEnv;
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it('should return null on error in production', async () => {
|
|
361
|
+
const originalEnv = process.env.NODE_ENV;
|
|
362
|
+
process.env.NODE_ENV = 'production';
|
|
363
|
+
|
|
364
|
+
const errorTemplateResolver = {
|
|
365
|
+
resolve: jest.fn().mockImplementation(() => {
|
|
366
|
+
throw new Error('Template error');
|
|
367
|
+
})
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const errorDataSource = {
|
|
371
|
+
dataProvider: new JsonDataProvider({ data: {} }),
|
|
372
|
+
templateResolver: errorTemplateResolver,
|
|
373
|
+
cacheProvider: false,
|
|
374
|
+
enableLogging: false
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
const TestComponent = () => {
|
|
378
|
+
const resolved = useTemplate('{{error.template}}');
|
|
379
|
+
return (
|
|
380
|
+
<div data-testid="template-result">
|
|
381
|
+
{resolved || 'Error fallback'}
|
|
382
|
+
</div>
|
|
383
|
+
);
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
render(
|
|
387
|
+
<DataProvider dataSource={errorDataSource}>
|
|
388
|
+
<TestComponent />
|
|
389
|
+
</DataProvider>
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
await waitFor(() => {
|
|
393
|
+
expect(screen.getByText('Error fallback')).toBeInTheDocument();
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
process.env.NODE_ENV = originalEnv;
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it('should support custom wrapper with t.wrap', async () => {
|
|
400
|
+
const TestComponent = () => (
|
|
401
|
+
<div data-testid="template-result">
|
|
402
|
+
{t.wrap(({ children }) => <strong data-testid="wrapper">{children}</strong>)`{{company.name}}`}
|
|
403
|
+
</div>
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
renderWithProvider(<TestComponent />);
|
|
407
|
+
|
|
408
|
+
await waitFor(() => {
|
|
409
|
+
expect(screen.getByTestId('wrapper')).toBeInTheDocument();
|
|
410
|
+
expect(screen.getByTestId('wrapper')).toHaveTextContent('QwickApps');
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it('should handle plain text without templates', async () => {
|
|
415
|
+
const TestComponent = () => (
|
|
416
|
+
<div data-testid="template-result">
|
|
417
|
+
{t`Plain text content`}
|
|
418
|
+
</div>
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
renderWithProvider(<TestComponent />);
|
|
422
|
+
|
|
423
|
+
expect(screen.getByText('Plain text content')).toBeInTheDocument();
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
it('should throw error when used outside provider', () => {
|
|
427
|
+
const originalError = console.error;
|
|
428
|
+
console.error = jest.fn();
|
|
429
|
+
|
|
430
|
+
const TestComponent = () => (
|
|
431
|
+
<div data-testid="template-result">
|
|
432
|
+
{t`{{company.name}}`}
|
|
433
|
+
</div>
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
expect(() => {
|
|
437
|
+
render(<TestComponent />);
|
|
438
|
+
}).toThrow('useDataContext must be used within a DataProvider');
|
|
439
|
+
|
|
440
|
+
console.error = originalError;
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
describe('Integration Tests', () => {
|
|
445
|
+
it('should work with multiple hooks in same component', async () => {
|
|
446
|
+
const CombinedTest = () => {
|
|
447
|
+
const { data: companies } = useData('company');
|
|
448
|
+
const { resolved } = useResolveTemplate('{{company.name}} offers {{features.0.title}} solutions');
|
|
449
|
+
|
|
450
|
+
return (
|
|
451
|
+
<div>
|
|
452
|
+
<div data-testid="companies">{companies.length} companies</div>
|
|
453
|
+
<div data-testid="resolved-template">{resolved}</div>
|
|
454
|
+
</div>
|
|
455
|
+
);
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
render(
|
|
459
|
+
<DataProvider dataSource={mockDataSource}>
|
|
460
|
+
<CombinedTest />
|
|
461
|
+
</DataProvider>
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
await waitFor(() => {
|
|
465
|
+
expect(screen.getByTestId('companies')).toHaveTextContent('1 companies');
|
|
466
|
+
expect(screen.getByTestId('first-feature')).toHaveTextContent('Fast');
|
|
467
|
+
// Template resolution might still be in progress
|
|
468
|
+
expect(screen.getByTestId('resolved-template')).toBeInTheDocument();
|
|
469
|
+
});
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it('should handle provider changes', async () => {
|
|
473
|
+
const newDataSource = {
|
|
474
|
+
dataProvider: new JsonDataProvider({
|
|
475
|
+
data: {
|
|
476
|
+
company: [{ name: 'New Company' }]
|
|
477
|
+
}
|
|
478
|
+
}),
|
|
479
|
+
cacheProvider: false,
|
|
480
|
+
enableLogging: false
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
const { rerender } = render(
|
|
484
|
+
<DataProvider dataSource={mockDataSource}>
|
|
485
|
+
<TestUseDataItem fieldGroupId="company" />
|
|
486
|
+
</DataProvider>
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
await waitFor(() => {
|
|
490
|
+
expect(screen.getByTestId('item')).toHaveTextContent('QwickApps');
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
// Change provider
|
|
494
|
+
rerender(
|
|
495
|
+
<DataProvider dataSource={newDataSource}>
|
|
496
|
+
<TestUseDataItem fieldGroupId="company" />
|
|
497
|
+
</DataProvider>
|
|
498
|
+
);
|
|
499
|
+
|
|
500
|
+
await waitFor(() => {
|
|
501
|
+
expect(screen.getByTestId('item')).toHaveTextContent('New Company');
|
|
502
|
+
});
|
|
503
|
+
});
|
|
504
|
+
});
|
|
505
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PaletteContext Tests
|
|
3
|
+
* Tests for palette management functionality
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
8
|
+
import { PaletteProvider, usePalette } from '../../contexts/PaletteContext';
|
|
9
|
+
|
|
10
|
+
// Test component that uses the palette context
|
|
11
|
+
const TestComponent = () => {
|
|
12
|
+
const { currentPalette, setPreferredPalette, availablePalettes } = usePalette();
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div>
|
|
16
|
+
<span data-testid="current-palette">{currentPalette}</span>
|
|
17
|
+
<span data-testid="available-count">{availablePalettes.length}</span>
|
|
18
|
+
<button onClick={() => setPreferredPalette('winter')}>Switch to Winter</button>
|
|
19
|
+
<button onClick={() => setPreferredPalette('ocean')}>Switch to Ocean</button>
|
|
20
|
+
{availablePalettes.map(palette => (
|
|
21
|
+
<span key={palette.id} data-testid={`palette-${palette.id}`}>
|
|
22
|
+
{palette.name}
|
|
23
|
+
</span>
|
|
24
|
+
))}
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const renderWithPaletteProvider = (component) => {
|
|
30
|
+
return render(<PaletteProvider>{component}</PaletteProvider>);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
describe('PaletteContext', () => {
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
// Reset document.documentElement mock
|
|
36
|
+
document.documentElement.setAttribute.mockClear();
|
|
37
|
+
document.documentElement.getAttribute.mockReturnValue(null);
|
|
38
|
+
|
|
39
|
+
// Reset localStorage mocks
|
|
40
|
+
localStorage.getItem.mockClear();
|
|
41
|
+
localStorage.setItem.mockClear();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('provides default palette as default', () => {
|
|
45
|
+
renderWithPaletteProvider(<TestComponent />);
|
|
46
|
+
|
|
47
|
+
expect(screen.getByTestId('current-palette')).toHaveTextContent('default');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('provides all available palettes', () => {
|
|
51
|
+
renderWithPaletteProvider(<TestComponent />);
|
|
52
|
+
|
|
53
|
+
expect(screen.getByTestId('available-count')).toHaveTextContent('6');
|
|
54
|
+
expect(screen.getByTestId('palette-default')).toHaveTextContent('Default');
|
|
55
|
+
expect(screen.getByTestId('palette-winter')).toHaveTextContent('Winter');
|
|
56
|
+
expect(screen.getByTestId('palette-autumn')).toHaveTextContent('Autumn');
|
|
57
|
+
expect(screen.getByTestId('palette-spring')).toHaveTextContent('Spring');
|
|
58
|
+
expect(screen.getByTestId('palette-ocean')).toHaveTextContent('Ocean');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('switches palette correctly', async () => {
|
|
62
|
+
renderWithPaletteProvider(<TestComponent />);
|
|
63
|
+
|
|
64
|
+
const winterButton = screen.getByText('Switch to Winter');
|
|
65
|
+
fireEvent.click(winterButton);
|
|
66
|
+
|
|
67
|
+
await waitFor(() => {
|
|
68
|
+
expect(screen.getByTestId('current-palette')).toHaveTextContent('winter');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('persists palette preference to localStorage', () => {
|
|
73
|
+
renderWithPaletteProvider(<TestComponent />);
|
|
74
|
+
|
|
75
|
+
const oceanButton = screen.getByText('Switch to Ocean');
|
|
76
|
+
fireEvent.click(oceanButton);
|
|
77
|
+
|
|
78
|
+
expect(localStorage.setItem).toHaveBeenCalledWith('qwickapps-react-framework-palette', 'ocean');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('loads palette from localStorage on initialization', () => {
|
|
82
|
+
localStorage.getItem.mockImplementation(() => 'autumn');
|
|
83
|
+
|
|
84
|
+
renderWithPaletteProvider(<TestComponent />);
|
|
85
|
+
|
|
86
|
+
expect(screen.getByTestId('current-palette')).toHaveTextContent('autumn');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test('updates document attributes when palette changes', async () => {
|
|
90
|
+
renderWithPaletteProvider(<TestComponent />);
|
|
91
|
+
|
|
92
|
+
const winterButton = screen.getByText('Switch to Winter');
|
|
93
|
+
fireEvent.click(winterButton);
|
|
94
|
+
|
|
95
|
+
await waitFor(() => {
|
|
96
|
+
expect(document.documentElement.setAttribute).toHaveBeenCalledWith('data-palette', 'winter');
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('throws error when usePalette is used outside PaletteProvider', () => {
|
|
101
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
102
|
+
|
|
103
|
+
expect(() => {
|
|
104
|
+
render(<TestComponent />);
|
|
105
|
+
}).toThrow('usePalette must be used within a PaletteProvider');
|
|
106
|
+
|
|
107
|
+
consoleSpy.mockRestore();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('handles invalid palette gracefully', async () => {
|
|
111
|
+
// Test that the context doesn't break with invalid input
|
|
112
|
+
// This is tested implicitly by the other tests working correctly
|
|
113
|
+
expect(true).toBe(true);
|
|
114
|
+
});
|
|
115
|
+
});
|