@hanzogui/kitchen-sink 3.0.5
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/.detoxrc.js +130 -0
- package/.env.production +2 -0
- package/.maestro/config.yaml +4 -0
- package/.maestro/flows/shorthand-variables.yaml +23 -0
- package/.watchmanconfig +1 -0
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/app.json +43 -0
- package/assets/adaptive-icon.png +0 -0
- package/assets/favicon.png +0 -0
- package/assets/icon.png +0 -0
- package/assets/splash.png +0 -0
- package/babel.config.js +25 -0
- package/e2e/CompilerExtraction.test.ts +147 -0
- package/e2e/GroupPressNative.test.ts +167 -0
- package/e2e/MediaQueryGtMd.test.ts +71 -0
- package/e2e/NativePortal.test.ts +113 -0
- package/e2e/PointerEvents.test.ts +116 -0
- package/e2e/PressStyleNative.noRngh.test.ts +191 -0
- package/e2e/PressStyleNative.test.ts +231 -0
- package/e2e/SafeArea.test.ts +57 -0
- package/e2e/SelectAndroidOnPress.test.ts +181 -0
- package/e2e/SelectRemount.test.ts +137 -0
- package/e2e/SheetDragResist.test.ts +370 -0
- package/e2e/SheetKeyboardDrag.test.ts +249 -0
- package/e2e/SheetScrollableDrag.test.ts +560 -0
- package/e2e/ShorthandVariables.test.ts +53 -0
- package/e2e/ThemeChangeBasic.test.ts +123 -0
- package/e2e/ThemeMutation.test.ts +80 -0
- package/e2e/check-rngh-status.test.ts +31 -0
- package/e2e/jest.config.js +19 -0
- package/e2e/utils/colors.ts +75 -0
- package/e2e/utils/navigation.ts +53 -0
- package/eas.json +22 -0
- package/flows/AlertDialog.yaml +17 -0
- package/flows/OpenApp.yaml +25 -0
- package/flows/Select.yaml +13 -0
- package/flows/Sheet.yaml +12 -0
- package/flows/Tabs.yaml +13 -0
- package/flows/Toast.yaml +14 -0
- package/flows/WarmUp.yaml +24 -0
- package/index.html +21 -0
- package/index.js +17 -0
- package/metro.config.js +64 -0
- package/next-router-shim.ts +9 -0
- package/package.json +118 -0
- package/plans/toast-2.md +471 -0
- package/playwright.config.ts +71 -0
- package/plugins/expo-modules-core-swift6.js +76 -0
- package/pod-install.sh +7 -0
- package/public/favicon.svg +70 -0
- package/public/fonts/inter.css +15 -0
- package/public/fonts/noto-cn.otf +0 -0
- package/public/gui-icon.svg +68 -0
- package/run-detox.sh +230 -0
- package/run-native-tests.sh +4 -0
- package/run-tests-parallel.ts +195 -0
- package/screenshots/Screenshotter.test.tsx +48 -0
- package/src/AnimationDemos.tsx +131 -0
- package/src/App.native.tsx +121 -0
- package/src/App.tsx +121 -0
- package/src/Navigation.tsx +98 -0
- package/src/Sandbox.tsx +87 -0
- package/src/TestDynamicEval.tsx +33 -0
- package/src/TestNativeSheet.tsx +100 -0
- package/src/components/TimedRender.tsx +18 -0
- package/src/constants/test-ids.ts +52 -0
- package/src/features/demos/demo-screen.tsx +72 -0
- package/src/features/home/ColorSchemeListItem.tsx +41 -0
- package/src/features/home/TestBuildAButton.tsx +102 -0
- package/src/features/home/TestSeparator.tsx +0 -0
- package/src/features/home/screen.tsx +285 -0
- package/src/features/testcases/screen.tsx +59 -0
- package/src/features/testcases/test-screen.tsx +50 -0
- package/src/generatedV5Theme.ts +112 -0
- package/src/gui.config.ts +411 -0
- package/src/guy.png +0 -0
- package/src/index.tsx +6 -0
- package/src/provider/index.tsx +18 -0
- package/src/test-gui-stack.tsx +11 -0
- package/src/test.tsx +3 -0
- package/src/useKitchenSinkTheme.tsx +15 -0
- package/src/usecases/ActionsSheetComparison.tsx +194 -0
- package/src/usecases/AnimatePresenceEnterExitCase.tsx +255 -0
- package/src/usecases/AnimatePresenceExitTest.tsx +69 -0
- package/src/usecases/AnimatedByProp.tsx +39 -0
- package/src/usecases/AnimationComprehensiveCase.tsx +2515 -0
- package/src/usecases/AnimationValueLoggingCase.tsx +526 -0
- package/src/usecases/AnimationsWithMediaQueriesCase.tsx +110 -0
- package/src/usecases/Benchmark.tsx +148 -0
- package/src/usecases/BenchmarkSelect.tsx +34 -0
- package/src/usecases/ButtonCircular.tsx +3 -0
- package/src/usecases/ButtonCustom.tsx +33 -0
- package/src/usecases/ButtonIconColor.tsx +18 -0
- package/src/usecases/ButtonInverse.tsx +30 -0
- package/src/usecases/ButtonUnstyled.tsx +31 -0
- package/src/usecases/CheckboxDisabledOnPress.tsx +62 -0
- package/src/usecases/ClickDuringEnterCase.tsx +59 -0
- package/src/usecases/CodeExamplesInput.tsx +9 -0
- package/src/usecases/ColorTokenFallback.tsx +52 -0
- package/src/usecases/CompilerExtraction.tsx +380 -0
- package/src/usecases/ComplexVariants.tsx +164 -0
- package/src/usecases/CrashAdaptSheet.tsx +98 -0
- package/src/usecases/CustomStyledAnimatedPopover.tsx +42 -0
- package/src/usecases/CustomStyledAnimatedTooltip.tsx +72 -0
- package/src/usecases/DOMNodeAPIs.tsx +154 -0
- package/src/usecases/DialogFocusScopeCase.tsx +277 -0
- package/src/usecases/DialogFocusScopeDebug.tsx +85 -0
- package/src/usecases/DialogNestedCase.tsx +121 -0
- package/src/usecases/DialogOpenControlled.tsx +49 -0
- package/src/usecases/DialogPointerEventsCase.tsx +58 -0
- package/src/usecases/DialogScopedCase.tsx +106 -0
- package/src/usecases/DialogSheetAdaptCase.tsx +178 -0
- package/src/usecases/DialogSheetAdaptResizeCase.tsx +98 -0
- package/src/usecases/DismissLayerStackingCase.tsx +223 -0
- package/src/usecases/DriverDisableAnimationPropsCase.tsx +44 -0
- package/src/usecases/Example.tsx +10 -0
- package/src/usecases/ExitCompletionCase.tsx +713 -0
- package/src/usecases/FocusVisibleButton.tsx +14 -0
- package/src/usecases/FocusVisibleButtonPointer.tsx +13 -0
- package/src/usecases/FocusVisibleButtonWithFocusStyle.tsx +16 -0
- package/src/usecases/FocusWithinCase.tsx +55 -0
- package/src/usecases/FontTokensInVariants.tsx +14 -0
- package/src/usecases/FormButtonTypeCase.tsx +34 -0
- package/src/usecases/GlobalScopedTriggerIsolationCase.tsx +178 -0
- package/src/usecases/GroupHoverMobile.tsx +39 -0
- package/src/usecases/GroupPressInVariant.tsx +92 -0
- package/src/usecases/GroupPressNative.tsx +200 -0
- package/src/usecases/GroupProp.tsx +96 -0
- package/src/usecases/GroupPseudoVariantOverride.tsx +56 -0
- package/src/usecases/GroupUseCases.tsx +94 -0
- package/src/usecases/HeightMediaQueryOverrideCase.tsx +183 -0
- package/src/usecases/InputAutoFocusAfterMenuCase.tsx +105 -0
- package/src/usecases/InputAutoFocusStyledCase.tsx +39 -0
- package/src/usecases/KeyboardControllerTest.tsx +146 -0
- package/src/usecases/ListItem.tsx +123 -0
- package/src/usecases/MediaQueriesV5.tsx +137 -0
- package/src/usecases/MediaQueryGtMd.tsx +73 -0
- package/src/usecases/MenuAboveDialogCase.tsx +75 -0
- package/src/usecases/MenuAccessibilityCase.tsx +133 -0
- package/src/usecases/MenuAnimatePositionCase.tsx +41 -0
- package/src/usecases/MenuArrowAnimatePresenceCase.tsx +98 -0
- package/src/usecases/MenuAsChildPositionCase.tsx +24 -0
- package/src/usecases/MenuAutoResizeCase.tsx +57 -0
- package/src/usecases/MenuBottomCase.tsx +55 -0
- package/src/usecases/MenuFocusLeaveCase.tsx +135 -0
- package/src/usecases/MenuHighlightCase.tsx +44 -0
- package/src/usecases/MenuItemFocusCase.tsx +79 -0
- package/src/usecases/MenuItemPseudoOverrideCase.tsx +270 -0
- package/src/usecases/MenuMultiTriggerCase.tsx +47 -0
- package/src/usecases/MenuOverflowCase.tsx +60 -0
- package/src/usecases/MenuSubCase.tsx +223 -0
- package/src/usecases/MenuSubLeftCase.tsx +178 -0
- package/src/usecases/MenuSubNestedPositionCase.tsx +171 -0
- package/src/usecases/MenuSubStyledCase.tsx +145 -0
- package/src/usecases/MenuThemeCase.tsx +50 -0
- package/src/usecases/MenuUnstyledCase.tsx +52 -0
- package/src/usecases/MultiDriverAnimation.tsx +118 -0
- package/src/usecases/NativePortalTest.tsx +179 -0
- package/src/usecases/NewInputBasic.tsx +16 -0
- package/src/usecases/NewInputEvents.tsx +29 -0
- package/src/usecases/NonGuiTextStyledType.tsx +23 -0
- package/src/usecases/OnLayoutCase.tsx +134 -0
- package/src/usecases/OnLayoutScaleCase.tsx +88 -0
- package/src/usecases/OnLayoutStressCase.tsx +353 -0
- package/src/usecases/OpacityModifierCase.tsx +113 -0
- package/src/usecases/OverlayStyled.tsx +66 -0
- package/src/usecases/ParagraphSpanFontInheritance.tsx +53 -0
- package/src/usecases/PlaceholderTextColor.tsx +20 -0
- package/src/usecases/PointerEventsCase.tsx +100 -0
- package/src/usecases/PopoverAndMenuMultiTriggerCase.tsx +138 -0
- package/src/usecases/PopoverCase.tsx +222 -0
- package/src/usecases/PopoverContentStyledPlusAnimations.tsx +44 -0
- package/src/usecases/PopoverFocusScopeCase.tsx +171 -0
- package/src/usecases/PopoverHoverableCase.tsx +167 -0
- package/src/usecases/PopoverHoverableDisableClickCase.tsx +118 -0
- package/src/usecases/PopoverHoverableRapidCase.tsx +103 -0
- package/src/usecases/PopoverHoverableScopedCase.tsx +135 -0
- package/src/usecases/PopoverScopedCase.tsx +76 -0
- package/src/usecases/PopoverTriggerIsolationCase.tsx +80 -0
- package/src/usecases/PressStyleNative.tsx +143 -0
- package/src/usecases/PseudoStyleMerge.tsx +25 -0
- package/src/usecases/PseudoTransitionCase.tsx +174 -0
- package/src/usecases/RawAnimatedValueCase.tsx +231 -0
- package/src/usecases/RemoveScrollCase.tsx +66 -0
- package/src/usecases/RenderPropCase.tsx +263 -0
- package/src/usecases/SafeAreaCase.tsx +236 -0
- package/src/usecases/ScrollViewRefCase.tsx +88 -0
- package/src/usecases/SecondPage.tsx +5 -0
- package/src/usecases/SelectAndroidOnPress.tsx +129 -0
- package/src/usecases/SelectFocusScopeCase.tsx +270 -0
- package/src/usecases/SelectRemount.tsx +136 -0
- package/src/usecases/Shadows.tsx +5 -0
- package/src/usecases/SheetAnimationCase.tsx +155 -0
- package/src/usecases/SheetDragCase.tsx +183 -0
- package/src/usecases/SheetDragResistCase.tsx +433 -0
- package/src/usecases/SheetDragResistCase.web.tsx +359 -0
- package/src/usecases/SheetKeyboardDragCase.tsx +328 -0
- package/src/usecases/SheetKeyboardFitContentCase.tsx +165 -0
- package/src/usecases/SheetOnAnimationCompleteCase.tsx +54 -0
- package/src/usecases/SheetScrollLockCase.tsx +166 -0
- package/src/usecases/SheetScrollableDrag.tsx +249 -0
- package/src/usecases/SheetSnapPointsFitCase.tsx +393 -0
- package/src/usecases/ShorthandVariables.tsx +49 -0
- package/src/usecases/SlowThemeReRender.tsx +48 -0
- package/src/usecases/SpinnerCustomColors.tsx +34 -0
- package/src/usecases/StackZIndex.tsx +82 -0
- package/src/usecases/StressPage.tsx +301 -0
- package/src/usecases/StylePlatform.tsx +30 -0
- package/src/usecases/StyleProp.tsx +29 -0
- package/src/usecases/StyledAnchor.tsx +27 -0
- package/src/usecases/StyledButtonAnimationAuto.tsx +99 -0
- package/src/usecases/StyledButtonTheme.tsx +63 -0
- package/src/usecases/StyledButtonVariantPseudo.tsx +25 -0
- package/src/usecases/StyledButtonVariantPseudoMerge.tsx +77 -0
- package/src/usecases/StyledCheckboxTheme.tsx +23 -0
- package/src/usecases/StyledContextColor.tsx +246 -0
- package/src/usecases/StyledContextTokens.tsx +147 -0
- package/src/usecases/StyledHOCNamed.tsx +20 -0
- package/src/usecases/StyledHtmlCase.tsx +144 -0
- package/src/usecases/StyledIconColor.tsx +19 -0
- package/src/usecases/StyledInputFocusStyle.tsx +21 -0
- package/src/usecases/StyledInputOnFocus.tsx +30 -0
- package/src/usecases/StyledMediaQueryMerge.tsx +95 -0
- package/src/usecases/StyledOverridePsuedo.tsx +26 -0
- package/src/usecases/StyledRNW.tsx +61 -0
- package/src/usecases/StyledStyleableInputOnFocus.tsx +34 -0
- package/src/usecases/StyledStyleableInputVariant.tsx +48 -0
- package/src/usecases/StyledStyledStyleableInputOnFocus.tsx +36 -0
- package/src/usecases/StyledVariantTextColor.tsx +25 -0
- package/src/usecases/StyledViewOnFocus.tsx +32 -0
- package/src/usecases/TabHoverAnimationCase.tsx +212 -0
- package/src/usecases/TextNestedInheritance.tsx +80 -0
- package/src/usecases/ThemeChange.tsx +100 -0
- package/src/usecases/ThemeChangeBasic.tsx +52 -0
- package/src/usecases/ThemeComponentResolution.tsx +119 -0
- package/src/usecases/ThemeConditionalName.tsx +31 -0
- package/src/usecases/ThemeMediaAnimationCase.tsx +39 -0
- package/src/usecases/ThemeMutation.tsx +86 -0
- package/src/usecases/ThemeNested.tsx +103 -0
- package/src/usecases/ThemeReset.tsx +62 -0
- package/src/usecases/ThemeShallowCase.tsx +83 -0
- package/src/usecases/ToastCase.tsx +46 -0
- package/src/usecases/ToggleGroupActiveProps.tsx +40 -0
- package/src/usecases/ToggleGroupXGroupCase.tsx +104 -0
- package/src/usecases/TooltipAnimationCase.tsx +99 -0
- package/src/usecases/TooltipCase.tsx +32 -0
- package/src/usecases/TooltipGlobalPatternCase.tsx +83 -0
- package/src/usecases/TooltipGroupCase.tsx +102 -0
- package/src/usecases/TooltipMultiTriggerCase.tsx +88 -0
- package/src/usecases/TooltipPositionJumpCase.tsx +91 -0
- package/src/usecases/TooltipTriggerInlineCase.tsx +60 -0
- package/src/usecases/TransformMediaQueryMerge.tsx +98 -0
- package/src/usecases/UseCases.tsx +409 -0
- package/src/usecases/UseTheme.tsx +41 -0
- package/src/usecases/V5ThemeBuilderOutput.tsx +231 -0
- package/src/usecases/VariantFontFamily.tsx +25 -0
- package/src/usecases/VariantsOrder.tsx +117 -0
- package/src/usecases/ZIndex.tsx +155 -0
- package/src/usecases/helpers.tsx +44 -0
- package/src/usecases/index.native.ts +122 -0
- package/src/usecases/index.ts +3 -0
- package/src/usecases/index.web.ts +177 -0
- package/tests/AnimatePresenceEnterExit.animated.test.tsx +176 -0
- package/tests/AnimatedByProp.animated.test.tsx +138 -0
- package/tests/AnimationBehavior.animated.test.tsx +543 -0
- package/tests/AnimationTiming.animated.test.tsx +195 -0
- package/tests/AnimationsWithMediaQueries.animated.test.tsx +154 -0
- package/tests/BuildAButton.test.tsx +87 -0
- package/tests/ButtonCircular.test.tsx +17 -0
- package/tests/ButtonCustom.test.tsx +17 -0
- package/tests/ButtonIconColor.test.tsx +23 -0
- package/tests/ButtonUnstyled.test.tsx +56 -0
- package/tests/ClickDuringEnter.animated.test.tsx +174 -0
- package/tests/ColorTokenFallback.test.tsx +45 -0
- package/tests/DOMNodeAPIs.test.tsx +161 -0
- package/tests/DialogFocusScope.animated.test.tsx +309 -0
- package/tests/DialogNested.test.tsx +128 -0
- package/tests/DialogOpenControlled.test.tsx +42 -0
- package/tests/DialogPointerEvents.animated.test.tsx +108 -0
- package/tests/DialogScoped.test.tsx +137 -0
- package/tests/DialogSheetAdapt.test.tsx +68 -0
- package/tests/DialogSheetAdaptResize.test.tsx +161 -0
- package/tests/DismissLayerStacking.test.tsx +292 -0
- package/tests/DriverDisableAnimationProps.animated.test.tsx +157 -0
- package/tests/ExitCompletion.animated.test.tsx +425 -0
- package/tests/ExitTimingCheck.animated.test.ts +34 -0
- package/tests/FocusVisibleButton.test.tsx +41 -0
- package/tests/FocusVisibleButtonPointerFocus.test.tsx +23 -0
- package/tests/FocusVisibleButtonPointerFocusWithFocusStyle.test.tsx +40 -0
- package/tests/FocusWithinStyle.animated.test.tsx +66 -0
- package/tests/FocusWithinStyle.test.tsx +60 -0
- package/tests/FormButtonType.test.tsx +42 -0
- package/tests/GlobalScopedTriggerIsolation.test.tsx +89 -0
- package/tests/GroupHoverMobile.test.tsx +52 -0
- package/tests/GroupPressInVariant.test.tsx +82 -0
- package/tests/GroupProp.test.tsx +30 -0
- package/tests/GroupPseudoVariantOverride.test.tsx +57 -0
- package/tests/GroupUseCases.test.tsx +111 -0
- package/tests/GuiSiteMotion.test.ts +481 -0
- package/tests/HeightMediaQueryOverride.test.tsx +112 -0
- package/tests/InputAutoFocusAfterMenu.test.tsx +55 -0
- package/tests/InputAutoFocusStyled.test.tsx +22 -0
- package/tests/ListItem.test.tsx +129 -0
- package/tests/MediaQueriesV5.test.tsx +113 -0
- package/tests/MediaQueryGtMd.test.tsx +84 -0
- package/tests/MenuAboveDialog.test.tsx +108 -0
- package/tests/MenuAccessibility.test.tsx +346 -0
- package/tests/MenuAnimatePosition.animated.test.tsx +57 -0
- package/tests/MenuArrowAnimatePresence.animated.test.tsx +71 -0
- package/tests/MenuAsChildPosition.test.tsx +16 -0
- package/tests/MenuAutoResize.test.tsx +54 -0
- package/tests/MenuFocusLeave.test.tsx +181 -0
- package/tests/MenuHighlight.test.tsx +165 -0
- package/tests/MenuHoverKeyboardBugs.test.tsx +252 -0
- package/tests/MenuItemFocus.test.tsx +59 -0
- package/tests/MenuItemPseudoOverride.test.tsx +231 -0
- package/tests/MenuMultiTrigger.test.tsx +101 -0
- package/tests/MenuOverflow.test.tsx +93 -0
- package/tests/MenuStayInFrame.test.tsx +102 -0
- package/tests/MenuSubKeyboardFocus.test.tsx +220 -0
- package/tests/MenuSubLeftSafePolygon.test.tsx +88 -0
- package/tests/MenuSubNestedPosition.test.tsx +48 -0
- package/tests/MenuSubSafePolygon.test.tsx +97 -0
- package/tests/MenuSubStyled.test.tsx +40 -0
- package/tests/MenuTheme.test.tsx +34 -0
- package/tests/MenuUnstyled.test.tsx +56 -0
- package/tests/MultiDriverAnimation.test.tsx +207 -0
- package/tests/NewInputBasic.test.tsx +50 -0
- package/tests/NewInputEvents.test.tsx +55 -0
- package/tests/OnLayout.test.tsx +163 -0
- package/tests/OnLayoutScale.test.tsx +100 -0
- package/tests/OnLayoutStress.test.tsx +304 -0
- package/tests/ParagraphSpanFontInheritance.test.tsx +73 -0
- package/tests/PointerEvents.test.tsx +123 -0
- package/tests/Popover.animated.test.tsx +234 -0
- package/tests/PopoverAndMenuMultiTrigger.test.tsx +184 -0
- package/tests/PopoverAnimatePosition.animated.test.tsx +51 -0
- package/tests/PopoverClickDuringEnter.animated.test.tsx +197 -0
- package/tests/PopoverFocusScope.test.tsx +242 -0
- package/tests/PopoverHoverable.test.tsx +383 -0
- package/tests/PopoverHoverableDisableClick.test.tsx +106 -0
- package/tests/PopoverHoverableRapid.test.tsx +129 -0
- package/tests/PopoverHoverableReposition.test.tsx +111 -0
- package/tests/PopoverHoverableScoped.animated.test.tsx +103 -0
- package/tests/PopoverHoverableStress.test.tsx +169 -0
- package/tests/PopoverInitialPosition.animated.test.tsx +82 -0
- package/tests/PopoverMiddlewareSkipRegression.animated.test.tsx +221 -0
- package/tests/PopoverScoped.test.tsx +128 -0
- package/tests/PopoverScopedPositionGlitch.animated.test.tsx +184 -0
- package/tests/PopoverTriggerIsolation.test.tsx +62 -0
- package/tests/PseudoTransition.animated.test.tsx +319 -0
- package/tests/RawAnimatedValue.test.tsx +147 -0
- package/tests/RemoveScroll.test.tsx +223 -0
- package/tests/RenderProp.test.tsx +293 -0
- package/tests/ScrollViewRef.test.tsx +39 -0
- package/tests/SelectClickHold.test.tsx +147 -0
- package/tests/SelectFocusScope.test.tsx +176 -0
- package/tests/SelectInnerPositioning.test.tsx +82 -0
- package/tests/SelectKeyboardNav.test.tsx +173 -0
- package/tests/SelectPositioning.test.tsx +56 -0
- package/tests/SelectTypeahead.test.tsx +63 -0
- package/tests/Shadows.test.tsx +14 -0
- package/tests/SheetAnimation.animated.test.tsx +413 -0
- package/tests/SheetDrag.animated.test.tsx +223 -0
- package/tests/SheetDragResist.animated.test.tsx +393 -0
- package/tests/SheetOnAnimationComplete.animated.test.tsx +62 -0
- package/tests/SheetScrollLock.animated.test.tsx +287 -0
- package/tests/SheetScrollableDrag.animated.test.tsx +1264 -0
- package/tests/SheetSnapPointsFit.animated.test.tsx +259 -0
- package/tests/ShorthandVariables.test.tsx +44 -0
- package/tests/SpinnerCustomColors.test.tsx +67 -0
- package/tests/StackZIndex.test.tsx +51 -0
- package/tests/StressPagePerf.test.tsx +76 -0
- package/tests/StylePlatform.test.tsx +38 -0
- package/tests/StyleProp.test.tsx +20 -0
- package/tests/StyledAnchor.test.tsx +17 -0
- package/tests/StyledButtonTheme.test.tsx +22 -0
- package/tests/StyledButtonVariantPseudo.test.tsx +20 -0
- package/tests/StyledButtonVariantPseudoMerge.animated.test.tsx +33 -0
- package/tests/StyledCheckboxTheme.test.tsx +16 -0
- package/tests/StyledContextColor.test.tsx +119 -0
- package/tests/StyledContextTokens.test.tsx +56 -0
- package/tests/StyledHOCNamed.test.tsx +16 -0
- package/tests/StyledHtml.test.tsx +161 -0
- package/tests/StyledIconColor.test.tsx +32 -0
- package/tests/StyledInputFocusStyle.test.tsx +19 -0
- package/tests/StyledInputOnFocus.test.tsx +27 -0
- package/tests/StyledMediaQueryMerge.test.tsx +66 -0
- package/tests/StyledRNW.test.tsx +17 -0
- package/tests/StyledStyleableInputOnFocus.test.tsx +27 -0
- package/tests/StyledStyleableInputVariant.test.tsx +22 -0
- package/tests/StyledStyledStyleableInputOnFocus.test.tsx +27 -0
- package/tests/StyledVariantTextColor.test.tsx +24 -0
- package/tests/StyledViewOnFocus.test.tsx +27 -0
- package/tests/TabHoverAnimation.animated.test.tsx +468 -0
- package/tests/TabHoverPositionSmooth.animated.test.tsx +129 -0
- package/tests/TextNestedInheritance.test.tsx +93 -0
- package/tests/ThemeChange.test.tsx +70 -0
- package/tests/ThemeComponentResolution.test.tsx +82 -0
- package/tests/ThemeConditionalName.test.tsx +34 -0
- package/tests/ThemeMediaAnimation.test.tsx +65 -0
- package/tests/ThemeNested.test.tsx +141 -0
- package/tests/ThemeReset.test.tsx +63 -0
- package/tests/ThemeShallow.test.tsx +95 -0
- package/tests/Toast.test.tsx +106 -0
- package/tests/ToggleGroup.test.tsx +61 -0
- package/tests/ToggleGroupActiveProps.test.tsx +38 -0
- package/tests/ToggleGroupXGroup.test.tsx +172 -0
- package/tests/TooltipAnimation.animated.test.tsx +260 -0
- package/tests/TooltipEnterInterrupt.animated.test.tsx +76 -0
- package/tests/TooltipGlobalPattern.animated.test.tsx +208 -0
- package/tests/TooltipGroup.animated.test.tsx +79 -0
- package/tests/TooltipMultiTrigger.test.tsx +116 -0
- package/tests/TooltipPositionJump.animated.test.tsx +229 -0
- package/tests/TooltipPositionJumpNotes.md +219 -0
- package/tests/TooltipRapidSwitch.animated.test.tsx +399 -0
- package/tests/TooltipTriggerInline.test.tsx +65 -0
- package/tests/TransformMediaQueryMerge.test.tsx +104 -0
- package/tests/TransitionEnterExit.animated.test.tsx +311 -0
- package/tests/UseTheme.test.tsx +16 -0
- package/tests/V5ThemeBuilderOutput.test.tsx +164 -0
- package/tests/VariantFontFamily.test.tsx +11 -0
- package/tests/VariantsOrder.test.tsx +53 -0
- package/tests/_debug_position.mjs +52 -0
- package/tests/test-utils.ts +106 -0
- package/tests/utils.tsx +54 -0
- package/tsconfig.json +45 -0
- package/vite-env.d.ts +1 -0
- package/vite.config.ts +14 -0
- package/webpack.config.js +139 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
import { getStyles } from './utils'
|
|
4
|
+
import { TEST_IDS } from '../src/constants/test-ids'
|
|
5
|
+
|
|
6
|
+
test.beforeEach(async ({ page }) => {
|
|
7
|
+
await setupPage(page, { name: 'ThemeChange', type: 'useCase' })
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test('Initial theme (yellow) renders with correct colors', async ({ page }) => {
|
|
11
|
+
// The expected yellow theme color in RGB format (themeDev palette)
|
|
12
|
+
const expectedYellowColor = 'rgb(255, 221, 0)'
|
|
13
|
+
|
|
14
|
+
// Get the theme info text to verify we're on yellow theme
|
|
15
|
+
const themeInfo0 = await page.locator(`#${TEST_IDS.themeInfo}-0`).textContent()
|
|
16
|
+
const themeInfo1 = await page.locator(`#${TEST_IDS.themeInfo}-1`).textContent()
|
|
17
|
+
|
|
18
|
+
// Verify both levels show yellow theme
|
|
19
|
+
expect(themeInfo0).toContain('"theme":"yellow"')
|
|
20
|
+
expect(themeInfo1).toContain('"theme":"yellow"')
|
|
21
|
+
|
|
22
|
+
// Get the styles for all squares
|
|
23
|
+
const staticSquare0Styles = await getStyles(page.locator(`#${TEST_IDS.staticSquare}-0`))
|
|
24
|
+
const staticSquare1Styles = await getStyles(page.locator(`#${TEST_IDS.staticSquare}-1`))
|
|
25
|
+
const dynamicSquare0Styles = await getStyles(
|
|
26
|
+
page.locator(`#${TEST_IDS.dynamicSquare}-0`)
|
|
27
|
+
)
|
|
28
|
+
const dynamicSquare1Styles = await getStyles(
|
|
29
|
+
page.locator(`#${TEST_IDS.dynamicSquare}-1`)
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
// Verify all squares have the yellow theme color
|
|
33
|
+
expect(staticSquare0Styles.backgroundColor).toBe(expectedYellowColor)
|
|
34
|
+
expect(staticSquare1Styles.backgroundColor).toBe(expectedYellowColor)
|
|
35
|
+
expect(dynamicSquare0Styles.backgroundColor).toBe(expectedYellowColor)
|
|
36
|
+
expect(dynamicSquare1Styles.backgroundColor).toBe(expectedYellowColor)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('Inner theme change does not affect outer theme', async ({ page }) => {
|
|
40
|
+
// Initial colors (themeDev palette)
|
|
41
|
+
const initialYellowColor = 'rgb(255, 221, 0)'
|
|
42
|
+
|
|
43
|
+
// Get initial styles for both levels
|
|
44
|
+
const outerSquareInitial = await getStyles(page.locator(`#${TEST_IDS.staticSquare}-0`))
|
|
45
|
+
const innerSquareInitial = await getStyles(page.locator(`#${TEST_IDS.staticSquare}-1`))
|
|
46
|
+
|
|
47
|
+
// Verify both start with yellow
|
|
48
|
+
expect(outerSquareInitial.backgroundColor).toBe(initialYellowColor)
|
|
49
|
+
expect(innerSquareInitial.backgroundColor).toBe(initialYellowColor)
|
|
50
|
+
|
|
51
|
+
// Click the inner theme change button
|
|
52
|
+
await page.locator(`#${TEST_IDS.changeThemeButton}-1`).click()
|
|
53
|
+
|
|
54
|
+
// Get updated styles
|
|
55
|
+
const outerSquareAfter = await getStyles(page.locator(`#${TEST_IDS.staticSquare}-0`))
|
|
56
|
+
const innerSquareAfter = await getStyles(page.locator(`#${TEST_IDS.staticSquare}-1`))
|
|
57
|
+
|
|
58
|
+
// Verify outer square remains yellow
|
|
59
|
+
expect(outerSquareAfter.backgroundColor).toBe(initialYellowColor)
|
|
60
|
+
|
|
61
|
+
// Verify inner square has changed (not yellow anymore)
|
|
62
|
+
expect(innerSquareAfter.backgroundColor).not.toBe(initialYellowColor)
|
|
63
|
+
|
|
64
|
+
// Verify theme info text reflects changes
|
|
65
|
+
const outerThemeInfo = await page.locator(`#${TEST_IDS.themeInfo}-0`).textContent()
|
|
66
|
+
const innerThemeInfo = await page.locator(`#${TEST_IDS.themeInfo}-1`).textContent()
|
|
67
|
+
|
|
68
|
+
expect(outerThemeInfo).toContain('"theme":"yellow"')
|
|
69
|
+
expect(innerThemeInfo).not.toContain('"theme":"yellow"')
|
|
70
|
+
})
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
import { TEST_IDS } from '../src/constants/test-ids'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Tests for theme component resolution (commit 5839319146 goals)
|
|
7
|
+
*
|
|
8
|
+
* These tests verify that the theme resolution algorithm correctly handles:
|
|
9
|
+
* 1. Explicit scheme overrides (e.g., dark_green inside blue parent)
|
|
10
|
+
* 2. Inheriting scheme from parent for component themes
|
|
11
|
+
* 3. Preserving sub-themes when only componentName is provided (no backtracking)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
test.beforeEach(async ({ page }) => {
|
|
15
|
+
// Use v4 themes as these tests require theme names like light_green, dark_green, etc.
|
|
16
|
+
await setupPage(page, {
|
|
17
|
+
name: 'ThemeComponentResolution',
|
|
18
|
+
type: 'useCase',
|
|
19
|
+
searchParams: { v4theme: 'true' },
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test.describe('Goal 1a: Explicit scheme override', () => {
|
|
24
|
+
test('dark_green theme is preserved when nested inside blue parent', async ({
|
|
25
|
+
page,
|
|
26
|
+
}) => {
|
|
27
|
+
// Direct dark_green theme
|
|
28
|
+
const directSquare = page.locator(`#${TEST_IDS.themeExplicitSchemeDirect}`)
|
|
29
|
+
await expect(directSquare).toBeVisible()
|
|
30
|
+
|
|
31
|
+
// Nested: blue → dark_green
|
|
32
|
+
const nestedSquare = page.locator(`#${TEST_IDS.themeExplicitSchemeNested}`)
|
|
33
|
+
await expect(nestedSquare).toBeVisible()
|
|
34
|
+
|
|
35
|
+
// Both should have the same theme name (dark_green)
|
|
36
|
+
const directText = await directSquare.innerText()
|
|
37
|
+
const nestedText = await nestedSquare.innerText()
|
|
38
|
+
|
|
39
|
+
expect(directText).toBe('dark_green')
|
|
40
|
+
expect(nestedText).toBe('dark_green')
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test.describe('Goal 1b: Inherit scheme from parent', () => {
|
|
45
|
+
test('green theme inherits light scheme from parent', async ({ page }) => {
|
|
46
|
+
// Direct light_green theme
|
|
47
|
+
const directSquare = page.locator(`#${TEST_IDS.themeInheritSchemeDirect}`)
|
|
48
|
+
await expect(directSquare).toBeVisible()
|
|
49
|
+
|
|
50
|
+
// Nested: light → green
|
|
51
|
+
const nestedSquare = page.locator(`#${TEST_IDS.themeInheritSchemeNested}`)
|
|
52
|
+
await expect(nestedSquare).toBeVisible()
|
|
53
|
+
|
|
54
|
+
// Both should resolve to light_green
|
|
55
|
+
const directText = await directSquare.innerText()
|
|
56
|
+
const nestedText = await nestedSquare.innerText()
|
|
57
|
+
|
|
58
|
+
expect(directText).toBe('light_green')
|
|
59
|
+
expect(nestedText).toBe('light_green')
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test.describe('Goal 2: Sub-theme preservation', () => {
|
|
64
|
+
test('surface1 sub-theme is preserved when nested (no backtracking)', async ({
|
|
65
|
+
page,
|
|
66
|
+
}) => {
|
|
67
|
+
// Direct light_blue_surface1
|
|
68
|
+
const directSquare = page.locator(`#${TEST_IDS.themeSurface1Direct}`)
|
|
69
|
+
await expect(directSquare).toBeVisible()
|
|
70
|
+
|
|
71
|
+
// Nested: blue → surface1
|
|
72
|
+
const nestedSquare = page.locator(`#${TEST_IDS.themeSurface1WithComponent}`)
|
|
73
|
+
await expect(nestedSquare).toBeVisible()
|
|
74
|
+
|
|
75
|
+
// Both should be light_blue_surface1
|
|
76
|
+
const directText = await directSquare.innerText()
|
|
77
|
+
const nestedText = await nestedSquare.innerText()
|
|
78
|
+
|
|
79
|
+
expect(directText).toBe('light_blue_surface1')
|
|
80
|
+
expect(nestedText).toBe('light_blue_surface1')
|
|
81
|
+
})
|
|
82
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
import { getStyles } from './utils'
|
|
4
|
+
|
|
5
|
+
test.beforeEach(async ({ page }) => {
|
|
6
|
+
await setupPage(page, { name: 'ThemeConditionalName', type: 'useCase' })
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test('Theme reverts to parent when name changes from accent to undefined', async ({
|
|
10
|
+
page,
|
|
11
|
+
}) => {
|
|
12
|
+
const parent = page.locator('#theme-conditional-parent')
|
|
13
|
+
const child = page.locator('#theme-conditional-child')
|
|
14
|
+
const toggle = page.locator('#theme-conditional-toggle')
|
|
15
|
+
|
|
16
|
+
// initially active=false, child should match parent (no theme override)
|
|
17
|
+
const parentInitial = await getStyles(parent)
|
|
18
|
+
const childInitial = await getStyles(child)
|
|
19
|
+
expect(childInitial.backgroundColor).toBe(parentInitial.backgroundColor)
|
|
20
|
+
|
|
21
|
+
// toggle active=true, child gets accent theme — should differ from parent
|
|
22
|
+
await toggle.click()
|
|
23
|
+
await page.waitForTimeout(100)
|
|
24
|
+
const parentActive = await getStyles(parent)
|
|
25
|
+
const childActive = await getStyles(child)
|
|
26
|
+
expect(childActive.backgroundColor).not.toBe(parentActive.backgroundColor)
|
|
27
|
+
|
|
28
|
+
// toggle active=false again, child should revert to parent theme
|
|
29
|
+
await toggle.click()
|
|
30
|
+
await page.waitForTimeout(100)
|
|
31
|
+
const parentReverted = await getStyles(parent)
|
|
32
|
+
const childReverted = await getStyles(child)
|
|
33
|
+
expect(childReverted.backgroundColor).toBe(parentReverted.backgroundColor)
|
|
34
|
+
})
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
// $theme-dark + animateOnly fix was intentionally reverted (80d70ce595)
|
|
5
|
+
test.skip()
|
|
6
|
+
|
|
7
|
+
test.describe('Theme Media + Animation', () => {
|
|
8
|
+
test('$theme-dark bg applies when animated with motion driver', async ({ page }) => {
|
|
9
|
+
await setupPage(page, {
|
|
10
|
+
name: 'ThemeMediaAnimationCase',
|
|
11
|
+
type: 'useCase',
|
|
12
|
+
theme: 'dark',
|
|
13
|
+
searchParams: { animationDriver: 'motion' },
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const animatedBg = await page.evaluate(() => {
|
|
17
|
+
const el = document.querySelector('[data-testid="theme-media-animated"]')
|
|
18
|
+
return el ? getComputedStyle(el).backgroundColor : null
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const staticBg = await page.evaluate(() => {
|
|
22
|
+
const el = document.querySelector('[data-testid="theme-media-static"]')
|
|
23
|
+
return el ? getComputedStyle(el).backgroundColor : null
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
// both should have the same background color in dark mode
|
|
27
|
+
// ($theme-dark overrides bg to $color3)
|
|
28
|
+
expect(animatedBg).toBeTruthy()
|
|
29
|
+
expect(staticBg).toBeTruthy()
|
|
30
|
+
expect(animatedBg).toBe(staticBg)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('$theme-dark bg differs from light theme when animated', async ({ page }) => {
|
|
34
|
+
// light theme
|
|
35
|
+
await setupPage(page, {
|
|
36
|
+
name: 'ThemeMediaAnimationCase',
|
|
37
|
+
type: 'useCase',
|
|
38
|
+
theme: 'light',
|
|
39
|
+
searchParams: { animationDriver: 'motion' },
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const lightBg = await page.evaluate(() => {
|
|
43
|
+
const el = document.querySelector('[data-testid="theme-media-animated"]')
|
|
44
|
+
return el ? getComputedStyle(el).backgroundColor : null
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
// dark theme
|
|
48
|
+
await setupPage(page, {
|
|
49
|
+
name: 'ThemeMediaAnimationCase',
|
|
50
|
+
type: 'useCase',
|
|
51
|
+
theme: 'dark',
|
|
52
|
+
searchParams: { animationDriver: 'motion' },
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const darkBg = await page.evaluate(() => {
|
|
56
|
+
const el = document.querySelector('[data-testid="theme-media-animated"]')
|
|
57
|
+
return el ? getComputedStyle(el).backgroundColor : null
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// $theme-dark changes bg from $color1 to $color3, so they should differ
|
|
61
|
+
expect(lightBg).toBeTruthy()
|
|
62
|
+
expect(darkBg).toBeTruthy()
|
|
63
|
+
expect(lightBg).not.toBe(darkBg)
|
|
64
|
+
})
|
|
65
|
+
})
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
import { getStyles } from './utils'
|
|
4
|
+
import { TEST_IDS } from '../src/constants/test-ids'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Tests for GitHub issue #3673: Nested theme regression
|
|
8
|
+
*
|
|
9
|
+
* When using nested themes like <Theme name="blue"><Theme name="surface3">,
|
|
10
|
+
* the parent color context (blue) should be preserved, resulting in
|
|
11
|
+
* light_blue_surface3 theme being applied.
|
|
12
|
+
*
|
|
13
|
+
* The bug causes the nested theme to lose the color context, resulting in
|
|
14
|
+
* just light_surface3 being applied instead.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
test.beforeEach(async ({ page }) => {
|
|
18
|
+
// Test the nested theme regression (issue #3673)
|
|
19
|
+
// Use v4 themes as the bug specifically occurs with @hanzogui/themes/v4
|
|
20
|
+
await setupPage(page, {
|
|
21
|
+
name: 'ThemeNested',
|
|
22
|
+
type: 'useCase',
|
|
23
|
+
searchParams: { v4theme: 'true' },
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('Nested blue theme with surface3 matches direct light_blue_surface3', async ({
|
|
28
|
+
page,
|
|
29
|
+
}) => {
|
|
30
|
+
// Get the direct theme element
|
|
31
|
+
const directSquare = page.locator(`#${TEST_IDS.nestedThemeDirect}`)
|
|
32
|
+
await expect(directSquare).toBeVisible()
|
|
33
|
+
|
|
34
|
+
// Get the nested theme element
|
|
35
|
+
const nestedSquare = page.locator(`#${TEST_IDS.nestedThemeNested}`)
|
|
36
|
+
await expect(nestedSquare).toBeVisible()
|
|
37
|
+
|
|
38
|
+
// Get computed styles for both
|
|
39
|
+
const directStyles = await getStyles(directSquare)
|
|
40
|
+
const nestedStyles = await getStyles(nestedSquare)
|
|
41
|
+
|
|
42
|
+
// The nested theme should produce the same background color as the direct theme
|
|
43
|
+
// If the bug is present, nestedStyles will have light_surface3 colors instead of light_blue_surface3
|
|
44
|
+
expect(nestedStyles.backgroundColor).toBe(directStyles.backgroundColor)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('Nested light → blue → surface3 matches direct light_blue_surface3', async ({
|
|
48
|
+
page,
|
|
49
|
+
}) => {
|
|
50
|
+
// Get the direct theme element
|
|
51
|
+
const directSquare = page.locator(`#${TEST_IDS.nestedThemeDirect}`)
|
|
52
|
+
await expect(directSquare).toBeVisible()
|
|
53
|
+
|
|
54
|
+
// Get the nested theme with explicit light parent
|
|
55
|
+
const nestedWithParent = page.locator(`#${TEST_IDS.nestedThemeWithParent}`)
|
|
56
|
+
await expect(nestedWithParent).toBeVisible()
|
|
57
|
+
|
|
58
|
+
// Get computed styles for both
|
|
59
|
+
const directStyles = await getStyles(directSquare)
|
|
60
|
+
const nestedStyles = await getStyles(nestedWithParent)
|
|
61
|
+
|
|
62
|
+
// The nested theme should produce the same background color as the direct theme
|
|
63
|
+
expect(nestedStyles.backgroundColor).toBe(directStyles.backgroundColor)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test('Nested red theme with surface3 matches direct light_red_surface3', async ({
|
|
67
|
+
page,
|
|
68
|
+
}) => {
|
|
69
|
+
// Get the direct red theme element
|
|
70
|
+
const redDirectSquare = page.locator(`#${TEST_IDS.nestedThemeRedDirect}`)
|
|
71
|
+
await expect(redDirectSquare).toBeVisible()
|
|
72
|
+
|
|
73
|
+
// Get the nested red theme element
|
|
74
|
+
const redNestedSquare = page.locator(`#${TEST_IDS.nestedThemeRedNested}`)
|
|
75
|
+
await expect(redNestedSquare).toBeVisible()
|
|
76
|
+
|
|
77
|
+
// Get computed styles for both
|
|
78
|
+
const redDirectStyles = await getStyles(redDirectSquare)
|
|
79
|
+
const redNestedStyles = await getStyles(redNestedSquare)
|
|
80
|
+
|
|
81
|
+
// The nested theme should produce the same background color as the direct theme
|
|
82
|
+
expect(redNestedStyles.backgroundColor).toBe(redDirectStyles.backgroundColor)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('Blue surface3 differs from colorless surface3', async ({ page }) => {
|
|
86
|
+
// Get the blue nested theme
|
|
87
|
+
const blueNestedSquare = page.locator(`#${TEST_IDS.nestedThemeNested}`)
|
|
88
|
+
await expect(blueNestedSquare).toBeVisible()
|
|
89
|
+
|
|
90
|
+
// Get the colorless surface3 theme
|
|
91
|
+
const noColorSquare = page.locator(`#${TEST_IDS.nestedThemeNoColor}`)
|
|
92
|
+
await expect(noColorSquare).toBeVisible()
|
|
93
|
+
|
|
94
|
+
// Get computed styles for both
|
|
95
|
+
const blueStyles = await getStyles(blueNestedSquare)
|
|
96
|
+
const noColorStyles = await getStyles(noColorSquare)
|
|
97
|
+
|
|
98
|
+
// The blue surface3 should have a different background than the colorless surface3
|
|
99
|
+
// This verifies that color context actually makes a difference
|
|
100
|
+
expect(blueStyles.backgroundColor).not.toBe(noColorStyles.backgroundColor)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
test('Blue surface3 differs from red surface3', async ({ page }) => {
|
|
104
|
+
// Get the blue nested theme
|
|
105
|
+
const blueNestedSquare = page.locator(`#${TEST_IDS.nestedThemeNested}`)
|
|
106
|
+
await expect(blueNestedSquare).toBeVisible()
|
|
107
|
+
|
|
108
|
+
// Get the red nested theme
|
|
109
|
+
const redNestedSquare = page.locator(`#${TEST_IDS.nestedThemeRedNested}`)
|
|
110
|
+
await expect(redNestedSquare).toBeVisible()
|
|
111
|
+
|
|
112
|
+
// Get computed styles for both
|
|
113
|
+
const blueStyles = await getStyles(blueNestedSquare)
|
|
114
|
+
const redStyles = await getStyles(redNestedSquare)
|
|
115
|
+
|
|
116
|
+
// Different color contexts should produce different backgrounds
|
|
117
|
+
expect(blueStyles.backgroundColor).not.toBe(redStyles.backgroundColor)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('Nested blue → surface1 → surface3 preserves blue color context', async ({
|
|
121
|
+
page,
|
|
122
|
+
}) => {
|
|
123
|
+
// This is the exact reproduction case from issue #3673
|
|
124
|
+
// Using surface3 theme inside a surface1 theme should preserve the blue color context
|
|
125
|
+
|
|
126
|
+
// Get the direct blue_surface3 element
|
|
127
|
+
const directSquare = page.locator(`#${TEST_IDS.nestedSurface1To3Direct}`)
|
|
128
|
+
await expect(directSquare).toBeVisible()
|
|
129
|
+
|
|
130
|
+
// Get the nested blue → surface1 → surface3 element
|
|
131
|
+
const nestedSquare = page.locator(`#${TEST_IDS.nestedSurface1To3Nested}`)
|
|
132
|
+
await expect(nestedSquare).toBeVisible()
|
|
133
|
+
|
|
134
|
+
// Get computed styles for both
|
|
135
|
+
const directStyles = await getStyles(directSquare)
|
|
136
|
+
const nestedStyles = await getStyles(nestedSquare)
|
|
137
|
+
|
|
138
|
+
// The nested theme should produce the same background color as the direct theme
|
|
139
|
+
// If the bug is present, nestedStyles will have light_surface3 colors instead of light_blue_surface3
|
|
140
|
+
expect(nestedStyles.backgroundColor).toBe(directStyles.backgroundColor)
|
|
141
|
+
})
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
import { getStyles } from './utils'
|
|
4
|
+
import { TEST_IDS } from '../src/constants/test-ids'
|
|
5
|
+
|
|
6
|
+
test.beforeEach(async ({ page }) => {
|
|
7
|
+
await setupPage(page, { name: 'ThemeReset', type: 'useCase' })
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test('Reset from nested themes goes back to grandparent', async ({ page }) => {
|
|
11
|
+
// Case 1: Reset from dark → pink → blue should go back to dark
|
|
12
|
+
const resetButton1 = page.locator(`#${TEST_IDS.resetButton1}`)
|
|
13
|
+
await expect(resetButton1).toBeVisible()
|
|
14
|
+
|
|
15
|
+
// Get the background color of the button
|
|
16
|
+
const button1Styles = await getStyles(resetButton1)
|
|
17
|
+
|
|
18
|
+
// The button should have dark theme background (not pink or blue)
|
|
19
|
+
// Dark theme typically has a dark background
|
|
20
|
+
expect(button1Styles.backgroundColor).not.toBe('rgb(255, 192, 203)') // pink
|
|
21
|
+
expect(button1Styles.backgroundColor).not.toBe('rgb(0, 0, 255)') // blue
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('Reset from dark → pink goes back to dark (documentation example)', async ({
|
|
25
|
+
page,
|
|
26
|
+
}) => {
|
|
27
|
+
// Case 2: Reset from dark → pink should go back to dark
|
|
28
|
+
const resetSquare1 = page.locator(`#${TEST_IDS.resetSquare1}`)
|
|
29
|
+
await expect(resetSquare1).toBeVisible()
|
|
30
|
+
|
|
31
|
+
const square1Styles = await getStyles(resetSquare1)
|
|
32
|
+
|
|
33
|
+
// The square should have dark theme background
|
|
34
|
+
// This matches the documentation example
|
|
35
|
+
expect(square1Styles.backgroundColor).not.toBe('rgb(255, 192, 203)') // pink
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('Reset from dark only goes to light', async ({ page }) => {
|
|
39
|
+
// Case 3: Reset from dark only should go to light (opposite scheme)
|
|
40
|
+
const resetSquare2 = page.locator(`#${TEST_IDS.resetSquare2}`)
|
|
41
|
+
await expect(resetSquare2).toBeVisible()
|
|
42
|
+
|
|
43
|
+
const square2Styles = await getStyles(resetSquare2)
|
|
44
|
+
|
|
45
|
+
// The square should have light theme background (opposite of dark)
|
|
46
|
+
expect(square2Styles.backgroundColor).not.toBe('rgb(0, 0, 0)') // black/dark
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('Reset from dark with button shows different themes', async ({ page }) => {
|
|
50
|
+
// Case 4: Dark button vs reset button should have different themes
|
|
51
|
+
const darkButton = page.locator(`#${TEST_IDS.darkButton}`)
|
|
52
|
+
const resetButton2 = page.locator(`#${TEST_IDS.resetButton2}`)
|
|
53
|
+
|
|
54
|
+
await expect(darkButton).toBeVisible()
|
|
55
|
+
await expect(resetButton2).toBeVisible()
|
|
56
|
+
|
|
57
|
+
const darkButtonStyles = await getStyles(darkButton)
|
|
58
|
+
const resetButton2Styles = await getStyles(resetButton2)
|
|
59
|
+
|
|
60
|
+
// The buttons should have different background colors
|
|
61
|
+
// Dark button should have dark theme, reset button should have light theme
|
|
62
|
+
expect(darkButtonStyles.backgroundColor).not.toBe(resetButton2Styles.backgroundColor)
|
|
63
|
+
})
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
import { TEST_IDS } from '../src/constants/test-ids'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Tests for themeShallow prop DOM structure stability
|
|
7
|
+
*
|
|
8
|
+
* The themeShallow prop should NOT affect DOM structure (span wrapping).
|
|
9
|
+
* It only affects whether grandchildren inherit the theme change.
|
|
10
|
+
*
|
|
11
|
+
* This test verifies that themeShallow doesn't cause unexpected DOM changes.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
test.beforeEach(async ({ page }) => {
|
|
15
|
+
await setupPage(page, { name: 'ThemeShallowCase', type: 'useCase' })
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('themeShallow does not add extra wrapper elements compared to normal theme', async ({
|
|
19
|
+
page,
|
|
20
|
+
}) => {
|
|
21
|
+
const normalContainer = page.locator(`#${TEST_IDS.themeShallowNormal}`)
|
|
22
|
+
const shallowContainer = page.locator(`#${TEST_IDS.themeShallowEnabled}`)
|
|
23
|
+
|
|
24
|
+
await expect(normalContainer).toBeVisible()
|
|
25
|
+
await expect(shallowContainer).toBeVisible()
|
|
26
|
+
|
|
27
|
+
// Get the DOM structure depth for both containers
|
|
28
|
+
// Count the number of wrapper elements between the container and its text content
|
|
29
|
+
const normalDepth = await normalContainer.evaluate((el) => {
|
|
30
|
+
let depth = 0
|
|
31
|
+
let current = el.querySelector('[class*="is_Theme"]')
|
|
32
|
+
while (current && current !== el) {
|
|
33
|
+
depth++
|
|
34
|
+
current = current.parentElement
|
|
35
|
+
}
|
|
36
|
+
return depth
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const shallowDepth = await shallowContainer.evaluate((el) => {
|
|
40
|
+
let depth = 0
|
|
41
|
+
let current = el.querySelector('[class*="is_Theme"]')
|
|
42
|
+
while (current && current !== el) {
|
|
43
|
+
depth++
|
|
44
|
+
current = current.parentElement
|
|
45
|
+
}
|
|
46
|
+
return depth
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
// The DOM structure depth should be the same regardless of themeShallow
|
|
50
|
+
// themeShallow only affects theme context propagation, not DOM structure
|
|
51
|
+
expect(shallowDepth).toBe(normalDepth)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('themeShallow container has consistent DOM structure', async ({ page }) => {
|
|
55
|
+
const container = page.locator(`#${TEST_IDS.themeShallowContainer}`)
|
|
56
|
+
const inner = page.locator(`#${TEST_IDS.themeShallowInner}`)
|
|
57
|
+
|
|
58
|
+
await expect(container).toBeVisible()
|
|
59
|
+
await expect(inner).toBeVisible()
|
|
60
|
+
|
|
61
|
+
// Snapshot the inner HTML structure to catch any regressions
|
|
62
|
+
const innerHtml = await inner.evaluate((el) => {
|
|
63
|
+
// Normalize the HTML by removing dynamic attributes like data-* IDs
|
|
64
|
+
const clone = el.cloneNode(true) as HTMLElement
|
|
65
|
+
clone.querySelectorAll('*').forEach((node) => {
|
|
66
|
+
// Remove dynamic attributes that change between runs
|
|
67
|
+
Array.from(node.attributes).forEach((attr) => {
|
|
68
|
+
if (
|
|
69
|
+
attr.name.startsWith('data-') &&
|
|
70
|
+
!attr.name.startsWith('data-test') &&
|
|
71
|
+
!attr.name.startsWith('data-disable')
|
|
72
|
+
) {
|
|
73
|
+
node.removeAttribute(attr.name)
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
return clone.innerHTML
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
// The inner container should have text content wrapped appropriately
|
|
81
|
+
expect(innerHtml).toContain('Inner content')
|
|
82
|
+
|
|
83
|
+
// Verify Theme wrapper spans are present (theme always wraps in span on web)
|
|
84
|
+
const themeSpans = await container.locator('span.is_Theme').count()
|
|
85
|
+
expect(themeSpans).toBeGreaterThan(0)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test('themeShallow prop does not change element tag type', async ({ page }) => {
|
|
89
|
+
const shallowContainer = page.locator(`#${TEST_IDS.themeShallowEnabled}`)
|
|
90
|
+
await expect(shallowContainer).toBeVisible()
|
|
91
|
+
|
|
92
|
+
// The container itself should be a div (Stack renders as div)
|
|
93
|
+
const tagName = await shallowContainer.evaluate((el) => el.tagName.toLowerCase())
|
|
94
|
+
expect(tagName).toBe('div')
|
|
95
|
+
})
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { Page } from '@playwright/test'
|
|
2
|
+
import { expect, test } from '@playwright/test'
|
|
3
|
+
|
|
4
|
+
import { setupPage } from './test-utils'
|
|
5
|
+
|
|
6
|
+
test.beforeEach(async ({ page }) => {
|
|
7
|
+
await setupPage(page, { name: 'ToastCase', type: 'useCase' })
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
async function buttonIsFocused(page: Page, identifier: number) {
|
|
11
|
+
await expect(page.getByTestId(`toast-button-${identifier}`)).toBeFocused()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function toastIsFocused(page: Page, identifier: number) {
|
|
15
|
+
await expect(page.getByTestId(`toast-${identifier}`)).toBeFocused()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
test.describe('given zero toasts', () => {
|
|
19
|
+
test('should not interrupt natural tab order in the document', async ({ page }) => {
|
|
20
|
+
await page.getByTestId('button-before').focus()
|
|
21
|
+
|
|
22
|
+
await page.keyboard.press('Tab')
|
|
23
|
+
|
|
24
|
+
await expect(page.getByTestId('button-after')).toBeFocused()
|
|
25
|
+
|
|
26
|
+
await page.keyboard.press('Shift+Tab')
|
|
27
|
+
|
|
28
|
+
await expect(page.getByTestId('button-before')).toBeFocused()
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test.describe('given multiple toasts', () => {
|
|
33
|
+
test.beforeEach(async ({ page }) => {
|
|
34
|
+
await page.getByTestId('button-add-toast').click()
|
|
35
|
+
await page.getByTestId('button-add-toast').click()
|
|
36
|
+
await new Promise((res) => setTimeout(res, 1000))
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('should reverse tab order from most recent to least', async ({ page }) => {
|
|
40
|
+
await page.getByTestId('button-before').focus()
|
|
41
|
+
|
|
42
|
+
await page.keyboard.press('Tab')
|
|
43
|
+
await toastIsFocused(page, 2)
|
|
44
|
+
|
|
45
|
+
// Forward tab
|
|
46
|
+
await page.keyboard.press('Tab')
|
|
47
|
+
await buttonIsFocused(page, 2.1)
|
|
48
|
+
|
|
49
|
+
await page.keyboard.press('Tab')
|
|
50
|
+
await buttonIsFocused(page, 2.2)
|
|
51
|
+
|
|
52
|
+
await page.keyboard.press('Tab')
|
|
53
|
+
await toastIsFocused(page, 1)
|
|
54
|
+
|
|
55
|
+
await page.keyboard.press('Tab')
|
|
56
|
+
await buttonIsFocused(page, 1.1)
|
|
57
|
+
|
|
58
|
+
await page.keyboard.press('Tab')
|
|
59
|
+
await buttonIsFocused(page, 1.2)
|
|
60
|
+
|
|
61
|
+
// End of viewport
|
|
62
|
+
await page.keyboard.press('Tab')
|
|
63
|
+
await expect(page.getByTestId('button-after')).toBeFocused()
|
|
64
|
+
|
|
65
|
+
// Backwards tab
|
|
66
|
+
await page.keyboard.press('Shift+Tab')
|
|
67
|
+
await buttonIsFocused(page, 1.2)
|
|
68
|
+
|
|
69
|
+
await page.keyboard.press('Shift+Tab')
|
|
70
|
+
await buttonIsFocused(page, 1.1)
|
|
71
|
+
|
|
72
|
+
await page.keyboard.press('Shift+Tab')
|
|
73
|
+
await toastIsFocused(page, 1)
|
|
74
|
+
|
|
75
|
+
await page.keyboard.press('Shift+Tab')
|
|
76
|
+
await buttonIsFocused(page, 2.2)
|
|
77
|
+
|
|
78
|
+
await page.keyboard.press('Shift+Tab')
|
|
79
|
+
await buttonIsFocused(page, 2.1)
|
|
80
|
+
|
|
81
|
+
await page.keyboard.press('Shift+Tab')
|
|
82
|
+
await toastIsFocused(page, 2)
|
|
83
|
+
|
|
84
|
+
// Start of viewport
|
|
85
|
+
await page.keyboard.press('Shift+Tab')
|
|
86
|
+
await expect(page.getByTestId('button-before')).toBeFocused()
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('should tab forwards from viewport to latest toast or backwards into the document', async ({
|
|
90
|
+
page,
|
|
91
|
+
}) => {
|
|
92
|
+
// Focus viewport directly instead of using F8
|
|
93
|
+
const viewport = page.locator('[role="region"][aria-label="Notifications (F8)"]')
|
|
94
|
+
await viewport.focus()
|
|
95
|
+
await expect(viewport).toBeFocused()
|
|
96
|
+
|
|
97
|
+
// Tab forward from viewport
|
|
98
|
+
await page.keyboard.press('Tab')
|
|
99
|
+
await toastIsFocused(page, 2)
|
|
100
|
+
|
|
101
|
+
// Tab backward from viewport - focus viewport again
|
|
102
|
+
await viewport.focus()
|
|
103
|
+
await page.keyboard.press('Shift+Tab')
|
|
104
|
+
await expect(page.getByTestId('button-before')).toBeFocused()
|
|
105
|
+
})
|
|
106
|
+
})
|