@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,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test for native portal with react-native-teleport integration
|
|
3
|
+
* Verifies that Portal/Sheet/Popover work correctly when using teleport
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { by, device, element, expect, waitFor } from 'detox'
|
|
7
|
+
import { navigateToTestCase } from './utils/navigation'
|
|
8
|
+
|
|
9
|
+
describe('NativePortal', () => {
|
|
10
|
+
beforeAll(async () => {
|
|
11
|
+
await device.launchApp({ newInstance: true })
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
await device.reloadReactNative()
|
|
16
|
+
await navigateToTestCase('NativePortalTest', 'portal-status')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('should navigate to NativePortalTest test case', async () => {
|
|
20
|
+
// verify we're on the right screen by checking for portal status
|
|
21
|
+
await expect(element(by.id('portal-status'))).toBeVisible()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('should show teleport as enabled', async () => {
|
|
25
|
+
// check that teleport is detected and enabled
|
|
26
|
+
const statusText = element(by.id('portal-status'))
|
|
27
|
+
await expect(statusText).toBeVisible()
|
|
28
|
+
// the status should indicate teleport is active (not "Not enabled")
|
|
29
|
+
// we can't easily check text content in detox, but visibility confirms component renders
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should open Select with Sheet', async () => {
|
|
33
|
+
await device.disableSynchronization()
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
// tap the select trigger
|
|
37
|
+
await element(by.id('native-portal-select-trigger')).tap()
|
|
38
|
+
|
|
39
|
+
// wait for select options to appear
|
|
40
|
+
await waitFor(element(by.id('native-portal-select-option-apple')))
|
|
41
|
+
.toBeVisible()
|
|
42
|
+
.withTimeout(10000)
|
|
43
|
+
|
|
44
|
+
// close by selecting an option
|
|
45
|
+
await element(by.id('native-portal-select-option-apple')).tap()
|
|
46
|
+
|
|
47
|
+
// wait for sheet to close
|
|
48
|
+
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
49
|
+
} finally {
|
|
50
|
+
await device.enableSynchronization()
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('should open and close Popover', async () => {
|
|
55
|
+
await device.disableSynchronization()
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
// tap popover trigger
|
|
59
|
+
await element(by.id('native-portal-popover-trigger')).tap()
|
|
60
|
+
|
|
61
|
+
// wait for popover content to appear
|
|
62
|
+
await waitFor(element(by.id('native-portal-popover-content')))
|
|
63
|
+
.toBeVisible()
|
|
64
|
+
.withTimeout(5000)
|
|
65
|
+
|
|
66
|
+
// verify text is visible inside popover
|
|
67
|
+
await expect(element(by.id('native-portal-popover-text'))).toBeVisible()
|
|
68
|
+
|
|
69
|
+
// close popover
|
|
70
|
+
await element(by.id('native-portal-popover-close')).tap()
|
|
71
|
+
|
|
72
|
+
// wait for popover to close
|
|
73
|
+
await new Promise((resolve) => setTimeout(resolve, 500))
|
|
74
|
+
|
|
75
|
+
// popover content should no longer be visible
|
|
76
|
+
await waitFor(element(by.id('native-portal-popover-content')))
|
|
77
|
+
.not.toBeVisible()
|
|
78
|
+
.withTimeout(3000)
|
|
79
|
+
} finally {
|
|
80
|
+
await device.enableSynchronization()
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('should open and close Sheet', async () => {
|
|
85
|
+
await device.disableSynchronization()
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
// tap sheet trigger
|
|
89
|
+
await element(by.id('native-portal-sheet-trigger')).tap()
|
|
90
|
+
|
|
91
|
+
// wait for sheet frame to appear
|
|
92
|
+
await waitFor(element(by.id('native-portal-sheet-frame')))
|
|
93
|
+
.toBeVisible()
|
|
94
|
+
.withTimeout(5000)
|
|
95
|
+
|
|
96
|
+
// verify text is visible inside sheet
|
|
97
|
+
await expect(element(by.id('native-portal-sheet-text'))).toBeVisible()
|
|
98
|
+
|
|
99
|
+
// close sheet by swiping down (dismissOnSnapToBottom)
|
|
100
|
+
await element(by.id('native-portal-sheet-frame')).swipe('down', 'fast')
|
|
101
|
+
|
|
102
|
+
// wait for sheet close animation
|
|
103
|
+
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
104
|
+
|
|
105
|
+
// sheet text should no longer be visible
|
|
106
|
+
await waitFor(element(by.id('native-portal-sheet-text')))
|
|
107
|
+
.not.toBeVisible()
|
|
108
|
+
.withTimeout(5000)
|
|
109
|
+
} finally {
|
|
110
|
+
await device.enableSynchronization()
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
})
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native tests for pointer events
|
|
3
|
+
* Verifies touch events map correctly to pointer events on native
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { by, device, element, expect } from 'detox'
|
|
7
|
+
import { navigateToTestCase } from './utils/navigation'
|
|
8
|
+
|
|
9
|
+
async function navigateToPointerEvents() {
|
|
10
|
+
await navigateToTestCase('PointerEventsCase', 'pointer-events-root')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe('PointerEvents', () => {
|
|
14
|
+
beforeAll(async () => {
|
|
15
|
+
await device.launchApp({ newInstance: true })
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
await device.reloadReactNative()
|
|
20
|
+
await navigateToPointerEvents()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('should render the test case', async () => {
|
|
24
|
+
await expect(element(by.id('pointer-target'))).toExist()
|
|
25
|
+
await expect(element(by.id('down-count'))).toHaveText('Down: 0')
|
|
26
|
+
await expect(element(by.id('up-count'))).toHaveText('Up: 0')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should fire pointerDown and pointerUp on tap', async () => {
|
|
30
|
+
await element(by.id('pointer-target')).tap()
|
|
31
|
+
|
|
32
|
+
await expect(element(by.id('down-count'))).toHaveText('Down: 1')
|
|
33
|
+
await expect(element(by.id('up-count'))).toHaveText('Up: 1')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('should fire pointerEnter on touch start', async () => {
|
|
37
|
+
await element(by.id('pointer-target')).tap()
|
|
38
|
+
|
|
39
|
+
await expect(element(by.id('enter-count'))).toHaveText('Enter: 1')
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('should fire pointerLeave on touch end', async () => {
|
|
43
|
+
await element(by.id('pointer-target')).tap()
|
|
44
|
+
|
|
45
|
+
await expect(element(by.id('leave-count'))).toHaveText('Leave: 1')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('should fire pointerMove during drag', async () => {
|
|
49
|
+
await element(by.id('pointer-target')).longPressAndDrag(
|
|
50
|
+
300, // duration ms
|
|
51
|
+
0.2, // start x (normalized)
|
|
52
|
+
0.5, // start y (normalized)
|
|
53
|
+
element(by.id('pointer-target')),
|
|
54
|
+
0.8, // end x (normalized)
|
|
55
|
+
0.5, // end y (normalized)
|
|
56
|
+
'slow',
|
|
57
|
+
0
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
// should have fired at least one move event (not still 0)
|
|
61
|
+
const moveEl = element(by.id('move-count'))
|
|
62
|
+
// if move fired, text won't be "Move: 0"
|
|
63
|
+
await expect(moveEl).not.toHaveText('Move: 0')
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
// skipping this test because longPressAndDrag from one element to another has
|
|
67
|
+
// visibility threshold issues in Detox when the root container extends beyond viewport
|
|
68
|
+
it.skip('should fire pointerLeave when dragging off element', async () => {
|
|
69
|
+
await element(by.id('pointer-target')).longPressAndDrag(
|
|
70
|
+
500,
|
|
71
|
+
0.5,
|
|
72
|
+
0.5,
|
|
73
|
+
element(by.id('pointer-events-root')),
|
|
74
|
+
0.5,
|
|
75
|
+
0.1, // drag to top of root (outside target)
|
|
76
|
+
'slow',
|
|
77
|
+
0
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
await new Promise((r) => setTimeout(r, 100))
|
|
81
|
+
|
|
82
|
+
await expect(element(by.id('leave-count'))).toHaveText('Leave: 1')
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('should handle multiple tap cycles', async () => {
|
|
86
|
+
await element(by.id('pointer-target')).tap()
|
|
87
|
+
await element(by.id('pointer-target')).tap()
|
|
88
|
+
await element(by.id('pointer-target')).tap()
|
|
89
|
+
|
|
90
|
+
await expect(element(by.id('down-count'))).toHaveText('Down: 3')
|
|
91
|
+
await expect(element(by.id('up-count'))).toHaveText('Up: 3')
|
|
92
|
+
await expect(element(by.id('enter-count'))).toHaveText('Enter: 3')
|
|
93
|
+
await expect(element(by.id('leave-count'))).toHaveText('Leave: 3')
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// skipping this test because the capture-target (second 200px square) is often
|
|
97
|
+
// partially off-screen and longPressAndDrag requires 100% visibility
|
|
98
|
+
// the core pointer capture functionality is tested in web tests
|
|
99
|
+
it.skip('should receive moves outside bounds when pointer is captured', async () => {
|
|
100
|
+
// drag from capture target to outside (root area)
|
|
101
|
+
// with setPointerCapture, moves should still fire even outside bounds
|
|
102
|
+
await element(by.id('capture-target')).longPressAndDrag(
|
|
103
|
+
500,
|
|
104
|
+
0.5,
|
|
105
|
+
0.5,
|
|
106
|
+
element(by.id('pointer-events-root')),
|
|
107
|
+
0.5,
|
|
108
|
+
0.05, // drag way up outside the target
|
|
109
|
+
'slow',
|
|
110
|
+
0
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
// should have received move events even while outside bounds
|
|
114
|
+
await expect(element(by.id('capture-move-count'))).not.toHaveText('CapMove: 0')
|
|
115
|
+
})
|
|
116
|
+
})
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native press style tests WITHOUT gesture handler (usePressability fallback)
|
|
3
|
+
*
|
|
4
|
+
* This test runs with RNGH disabled via launch args to verify that press handling
|
|
5
|
+
* works correctly when falling back to RN's usePressability.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { by, device, element, expect, waitFor } from 'detox'
|
|
9
|
+
import * as fs from 'fs'
|
|
10
|
+
import * as assert from 'assert'
|
|
11
|
+
import { PNG } from 'pngjs'
|
|
12
|
+
import { navigateToTestCase } from './utils/navigation'
|
|
13
|
+
import { getDominantColor, isBlueish, formatRGB } from './utils/colors'
|
|
14
|
+
|
|
15
|
+
async function navigateToPressStyleNative() {
|
|
16
|
+
await navigateToTestCase('PressStyleNative', 'color-test-pressable')
|
|
17
|
+
// navigateToTestCase re-enables sync, but we need it disabled for no-RNGH tests
|
|
18
|
+
// because the RNManualRecognizer gesture blocks Detox synchronization in CI
|
|
19
|
+
await device.disableSynchronization()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe('PressStyleNative (no RNGH)', () => {
|
|
23
|
+
beforeAll(async () => {
|
|
24
|
+
// launch with RNGH disabled
|
|
25
|
+
await device.launchApp({
|
|
26
|
+
newInstance: true,
|
|
27
|
+
launchArgs: { disableGestureHandler: true },
|
|
28
|
+
})
|
|
29
|
+
// disable synchronization for the entire suite - without RNGH, there's a
|
|
30
|
+
// RNManualRecognizer gesture that stays in "Possible" state which blocks Detox
|
|
31
|
+
await device.disableSynchronization()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
afterAll(async () => {
|
|
35
|
+
await device.enableSynchronization()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
beforeEach(async () => {
|
|
39
|
+
// use launchApp instead of reloadReactNative — on RN 0.83, reloadReactNative
|
|
40
|
+
// doesn't work reliably when RNGH is disabled (JS run loop stays busy)
|
|
41
|
+
await device.launchApp({
|
|
42
|
+
newInstance: true,
|
|
43
|
+
launchArgs: { disableGestureHandler: true },
|
|
44
|
+
})
|
|
45
|
+
await device.disableSynchronization()
|
|
46
|
+
// wait for app to stabilize after launch
|
|
47
|
+
await new Promise((resolve) => setTimeout(resolve, 1500))
|
|
48
|
+
await navigateToPressStyleNative()
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('should render the test case screen', async () => {
|
|
52
|
+
await waitFor(element(by.id('color-test-pressable')))
|
|
53
|
+
.toBeVisible()
|
|
54
|
+
.withTimeout(5000)
|
|
55
|
+
await waitFor(element(by.id('animated-color-test-pressable')))
|
|
56
|
+
.toBeVisible()
|
|
57
|
+
.withTimeout(5000)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
describe('pressStyle without transition', () => {
|
|
61
|
+
it('should fire pressIn and pressOut events on tap', async () => {
|
|
62
|
+
await waitFor(element(by.id('simple-press-in-count')))
|
|
63
|
+
.toHaveText('In: 0')
|
|
64
|
+
.withTimeout(5000)
|
|
65
|
+
await waitFor(element(by.id('simple-press-out-count')))
|
|
66
|
+
.toHaveText('Out: 0')
|
|
67
|
+
.withTimeout(5000)
|
|
68
|
+
|
|
69
|
+
await element(by.id('color-test-pressable')).tap()
|
|
70
|
+
await new Promise((resolve) => setTimeout(resolve, 300))
|
|
71
|
+
|
|
72
|
+
await waitFor(element(by.id('simple-press-in-count')))
|
|
73
|
+
.toHaveText('In: 1')
|
|
74
|
+
.withTimeout(5000)
|
|
75
|
+
await waitFor(element(by.id('simple-press-out-count')))
|
|
76
|
+
.toHaveText('Out: 1')
|
|
77
|
+
.withTimeout(5000)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('should not be stuck in pressed state after tap', async () => {
|
|
81
|
+
await element(by.id('color-test-pressable')).tap()
|
|
82
|
+
await new Promise((resolve) => setTimeout(resolve, 300))
|
|
83
|
+
await waitFor(element(by.id('simple-is-pressed')))
|
|
84
|
+
.toHaveText('Pressed: NO')
|
|
85
|
+
.withTimeout(5000)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('should show blue background at rest', async () => {
|
|
89
|
+
await new Promise((resolve) => setTimeout(resolve, 300))
|
|
90
|
+
const restScreenshot = await element(by.id('color-test-pressable')).takeScreenshot(
|
|
91
|
+
'color-test-rest-norngh'
|
|
92
|
+
)
|
|
93
|
+
const color = getDominantColor(restScreenshot)
|
|
94
|
+
assert.ok(isBlueish(color), `Expected blue at rest, got ${formatRGB(color)}`)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('should unpress when finger drags off element', async () => {
|
|
98
|
+
await waitFor(element(by.id('simple-press-in-count')))
|
|
99
|
+
.toHaveText('In: 0')
|
|
100
|
+
.withTimeout(5000)
|
|
101
|
+
await waitFor(element(by.id('simple-press-out-count')))
|
|
102
|
+
.toHaveText('Out: 0')
|
|
103
|
+
.withTimeout(5000)
|
|
104
|
+
|
|
105
|
+
await element(by.id('color-test-pressable')).longPressAndDrag(
|
|
106
|
+
500,
|
|
107
|
+
0.5,
|
|
108
|
+
0.5,
|
|
109
|
+
element(by.id('press-style-native-root')),
|
|
110
|
+
0.5,
|
|
111
|
+
0.1,
|
|
112
|
+
'slow',
|
|
113
|
+
100
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
await new Promise((resolve) => setTimeout(resolve, 400))
|
|
117
|
+
|
|
118
|
+
await waitFor(element(by.id('simple-press-in-count')))
|
|
119
|
+
.toHaveText('In: 1')
|
|
120
|
+
.withTimeout(5000)
|
|
121
|
+
await waitFor(element(by.id('simple-press-out-count')))
|
|
122
|
+
.toHaveText('Out: 1')
|
|
123
|
+
.withTimeout(5000)
|
|
124
|
+
await waitFor(element(by.id('simple-is-pressed')))
|
|
125
|
+
.toHaveText('Pressed: NO')
|
|
126
|
+
.withTimeout(5000)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('should return to blue after drag off', async () => {
|
|
130
|
+
await element(by.id('color-test-pressable')).longPressAndDrag(
|
|
131
|
+
500,
|
|
132
|
+
0.5,
|
|
133
|
+
0.5,
|
|
134
|
+
element(by.id('press-style-native-root')),
|
|
135
|
+
0.5,
|
|
136
|
+
0.1,
|
|
137
|
+
'slow',
|
|
138
|
+
100
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
await new Promise((resolve) => setTimeout(resolve, 400))
|
|
142
|
+
|
|
143
|
+
const afterScreenshot = await element(by.id('color-test-pressable')).takeScreenshot(
|
|
144
|
+
'color-test-after-drag-norngh'
|
|
145
|
+
)
|
|
146
|
+
const color = getDominantColor(afterScreenshot)
|
|
147
|
+
assert.ok(isBlueish(color), `Expected blue after drag off, got ${formatRGB(color)}`)
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
describe('pressStyle with transition (animation driver)', () => {
|
|
152
|
+
it('should fire pressIn and pressOut events on animated pressable', async () => {
|
|
153
|
+
await waitFor(element(by.id('animated-press-in-count')))
|
|
154
|
+
.toHaveText('In: 0')
|
|
155
|
+
.withTimeout(5000)
|
|
156
|
+
await waitFor(element(by.id('animated-press-out-count')))
|
|
157
|
+
.toHaveText('Out: 0')
|
|
158
|
+
.withTimeout(5000)
|
|
159
|
+
|
|
160
|
+
await element(by.id('animated-color-test-pressable')).tap()
|
|
161
|
+
await new Promise((resolve) => setTimeout(resolve, 300))
|
|
162
|
+
|
|
163
|
+
await waitFor(element(by.id('animated-press-in-count')))
|
|
164
|
+
.toHaveText('In: 1')
|
|
165
|
+
.withTimeout(5000)
|
|
166
|
+
await waitFor(element(by.id('animated-press-out-count')))
|
|
167
|
+
.toHaveText('Out: 1')
|
|
168
|
+
.withTimeout(5000)
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
it('should not be stuck in pressed state after tap (animated)', async () => {
|
|
172
|
+
await element(by.id('animated-color-test-pressable')).tap()
|
|
173
|
+
await new Promise((resolve) => setTimeout(resolve, 300))
|
|
174
|
+
await waitFor(element(by.id('animated-is-pressed')))
|
|
175
|
+
.toHaveText('Pressed: NO')
|
|
176
|
+
.withTimeout(5000)
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
it('should show blue background at rest (animated)', async () => {
|
|
180
|
+
await new Promise((resolve) => setTimeout(resolve, 300))
|
|
181
|
+
const restScreenshot = await element(
|
|
182
|
+
by.id('animated-color-test-pressable')
|
|
183
|
+
).takeScreenshot('animated-color-test-rest-norngh')
|
|
184
|
+
const color = getDominantColor(restScreenshot)
|
|
185
|
+
assert.ok(
|
|
186
|
+
isBlueish(color),
|
|
187
|
+
`Expected blue at rest (animated), got ${formatRGB(color)}`
|
|
188
|
+
)
|
|
189
|
+
})
|
|
190
|
+
})
|
|
191
|
+
})
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detox E2E tests for native press style behaviors
|
|
3
|
+
*
|
|
4
|
+
* Tests verify:
|
|
5
|
+
* 1. Press events fire correctly (onPressIn/onPressOut)
|
|
6
|
+
* 2. Press state doesn't get stuck after tap or drag-off
|
|
7
|
+
* 3. Both non-animated and animated (transition) pressables work
|
|
8
|
+
* 4. Actual pixel colors are verified via screenshots
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { by, device, element, expect, waitFor } from 'detox'
|
|
12
|
+
import * as fs from 'fs'
|
|
13
|
+
import * as assert from 'assert'
|
|
14
|
+
import { PNG } from 'pngjs'
|
|
15
|
+
import { navigateToTestCase } from './utils/navigation'
|
|
16
|
+
|
|
17
|
+
// helper to get the dominant color from a PNG screenshot
|
|
18
|
+
// samples pixels from the center region to avoid edges/text
|
|
19
|
+
function getDominantColor(screenshotPath: string): { r: number; g: number; b: number } {
|
|
20
|
+
const data = fs.readFileSync(screenshotPath)
|
|
21
|
+
const png = PNG.sync.read(data)
|
|
22
|
+
|
|
23
|
+
// sample the center 50% of the image to avoid edges and text
|
|
24
|
+
const startX = Math.floor(png.width * 0.25)
|
|
25
|
+
const endX = Math.floor(png.width * 0.75)
|
|
26
|
+
const startY = Math.floor(png.height * 0.25)
|
|
27
|
+
const endY = Math.floor(png.height * 0.75)
|
|
28
|
+
|
|
29
|
+
let totalR = 0,
|
|
30
|
+
totalG = 0,
|
|
31
|
+
totalB = 0,
|
|
32
|
+
count = 0
|
|
33
|
+
|
|
34
|
+
for (let y = startY; y < endY; y++) {
|
|
35
|
+
for (let x = startX; x < endX; x++) {
|
|
36
|
+
const idx = (png.width * y + x) * 4
|
|
37
|
+
totalR += png.data[idx]
|
|
38
|
+
totalG += png.data[idx + 1]
|
|
39
|
+
totalB += png.data[idx + 2]
|
|
40
|
+
count++
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
r: Math.round(totalR / count),
|
|
46
|
+
g: Math.round(totalG / count),
|
|
47
|
+
b: Math.round(totalB / count),
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// check if a color is predominantly blue (for $blue10)
|
|
52
|
+
function isBlueish(color: { r: number; g: number; b: number }): boolean {
|
|
53
|
+
// blue should have high B, low R, and low-medium G
|
|
54
|
+
return color.b > 100 && color.b > color.r && color.b > color.g
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// TODO: These tests are flaky on iOS simulator - press events don't fire reliably
|
|
58
|
+
// Need to investigate press event handling in simulator environment
|
|
59
|
+
describe.skip('PressStyleNative', () => {
|
|
60
|
+
beforeAll(async () => {
|
|
61
|
+
await device.launchApp({ newInstance: true })
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
beforeEach(async () => {
|
|
65
|
+
await device.reloadReactNative()
|
|
66
|
+
await navigateToPressStyleNative()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('should render the test case screen', async () => {
|
|
70
|
+
await expect(element(by.id('color-test-pressable'))).toBeVisible()
|
|
71
|
+
await expect(element(by.id('animated-color-test-pressable'))).toBeVisible()
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
describe('pressStyle without transition', () => {
|
|
75
|
+
it('should fire pressIn and pressOut events on tap', async () => {
|
|
76
|
+
await expect(element(by.id('simple-press-in-count'))).toHaveText('In: 0')
|
|
77
|
+
await expect(element(by.id('simple-press-out-count'))).toHaveText('Out: 0')
|
|
78
|
+
|
|
79
|
+
await element(by.id('color-test-pressable')).tap()
|
|
80
|
+
|
|
81
|
+
await expect(element(by.id('simple-press-in-count'))).toHaveText('In: 1')
|
|
82
|
+
await expect(element(by.id('simple-press-out-count'))).toHaveText('Out: 1')
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('should not be stuck in pressed state after tap', async () => {
|
|
86
|
+
await element(by.id('color-test-pressable')).tap()
|
|
87
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
88
|
+
await expect(element(by.id('simple-is-pressed'))).toHaveText('Pressed: NO')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('should show blue background at rest', async () => {
|
|
92
|
+
const restScreenshot = await element(by.id('color-test-pressable')).takeScreenshot(
|
|
93
|
+
'color-test-rest'
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
const color = getDominantColor(restScreenshot)
|
|
97
|
+
assert.ok(
|
|
98
|
+
isBlueish(color),
|
|
99
|
+
`Expected blue at rest, got RGB(${color.r}, ${color.g}, ${color.b})`
|
|
100
|
+
)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('should unpress when finger drags off element', async () => {
|
|
104
|
+
await expect(element(by.id('simple-press-in-count'))).toHaveText('In: 0')
|
|
105
|
+
await expect(element(by.id('simple-press-out-count'))).toHaveText('Out: 0')
|
|
106
|
+
|
|
107
|
+
await element(by.id('color-test-pressable')).longPressAndDrag(
|
|
108
|
+
500,
|
|
109
|
+
0.5,
|
|
110
|
+
0.5,
|
|
111
|
+
element(by.id('press-style-native-root')),
|
|
112
|
+
0.5,
|
|
113
|
+
0.1,
|
|
114
|
+
'slow',
|
|
115
|
+
100
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
await new Promise((resolve) => setTimeout(resolve, 200))
|
|
119
|
+
|
|
120
|
+
await expect(element(by.id('simple-press-in-count'))).toHaveText('In: 1')
|
|
121
|
+
await expect(element(by.id('simple-press-out-count'))).toHaveText('Out: 1')
|
|
122
|
+
await expect(element(by.id('simple-is-pressed'))).toHaveText('Pressed: NO')
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it('should return to blue after drag off', async () => {
|
|
126
|
+
await element(by.id('color-test-pressable')).longPressAndDrag(
|
|
127
|
+
500,
|
|
128
|
+
0.5,
|
|
129
|
+
0.5,
|
|
130
|
+
element(by.id('press-style-native-root')),
|
|
131
|
+
0.5,
|
|
132
|
+
0.1,
|
|
133
|
+
'slow',
|
|
134
|
+
100
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
await new Promise((resolve) => setTimeout(resolve, 200))
|
|
138
|
+
|
|
139
|
+
const afterDragScreenshot = await element(
|
|
140
|
+
by.id('color-test-pressable')
|
|
141
|
+
).takeScreenshot('color-test-after-drag')
|
|
142
|
+
|
|
143
|
+
const color = getDominantColor(afterDragScreenshot)
|
|
144
|
+
assert.ok(
|
|
145
|
+
isBlueish(color),
|
|
146
|
+
`Expected blue after drag off, got RGB(${color.r}, ${color.g}, ${color.b})`
|
|
147
|
+
)
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
it('should handle multiple press-drag-off cycles', async () => {
|
|
151
|
+
await expect(element(by.id('simple-press-in-count'))).toHaveText('In: 0')
|
|
152
|
+
await expect(element(by.id('simple-press-out-count'))).toHaveText('Out: 0')
|
|
153
|
+
|
|
154
|
+
for (let i = 0; i < 3; i++) {
|
|
155
|
+
await element(by.id('color-test-pressable')).longPressAndDrag(
|
|
156
|
+
500,
|
|
157
|
+
0.5,
|
|
158
|
+
0.5,
|
|
159
|
+
element(by.id('press-style-native-root')),
|
|
160
|
+
0.5,
|
|
161
|
+
0.1,
|
|
162
|
+
'slow',
|
|
163
|
+
100
|
|
164
|
+
)
|
|
165
|
+
await new Promise((resolve) => setTimeout(resolve, 200))
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
await expect(element(by.id('simple-press-in-count'))).toHaveText('In: 3')
|
|
169
|
+
await expect(element(by.id('simple-press-out-count'))).toHaveText('Out: 3')
|
|
170
|
+
await expect(element(by.id('simple-is-pressed'))).toHaveText('Pressed: NO')
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
describe('pressStyle with transition (animation driver)', () => {
|
|
175
|
+
it('should fire pressIn and pressOut events on animated pressable', async () => {
|
|
176
|
+
await expect(element(by.id('animated-press-in-count'))).toHaveText('In: 0')
|
|
177
|
+
await expect(element(by.id('animated-press-out-count'))).toHaveText('Out: 0')
|
|
178
|
+
|
|
179
|
+
await element(by.id('animated-color-test-pressable')).tap()
|
|
180
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
181
|
+
|
|
182
|
+
await expect(element(by.id('animated-press-in-count'))).toHaveText('In: 1')
|
|
183
|
+
await expect(element(by.id('animated-press-out-count'))).toHaveText('Out: 1')
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it('should not be stuck in pressed state after tap (animated)', async () => {
|
|
187
|
+
await element(by.id('animated-color-test-pressable')).tap()
|
|
188
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
189
|
+
await expect(element(by.id('animated-is-pressed'))).toHaveText('Pressed: NO')
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
it('should show blue background at rest (animated)', async () => {
|
|
193
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
194
|
+
const restScreenshot = await element(
|
|
195
|
+
by.id('animated-color-test-pressable')
|
|
196
|
+
).takeScreenshot('animated-color-test-rest')
|
|
197
|
+
|
|
198
|
+
const color = getDominantColor(restScreenshot)
|
|
199
|
+
assert.ok(
|
|
200
|
+
isBlueish(color),
|
|
201
|
+
`Expected blue at rest (animated), got RGB(${color.r}, ${color.g}, ${color.b})`
|
|
202
|
+
)
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
it('should unpress when finger drags off animated element', async () => {
|
|
206
|
+
await expect(element(by.id('animated-press-in-count'))).toHaveText('In: 0')
|
|
207
|
+
await expect(element(by.id('animated-press-out-count'))).toHaveText('Out: 0')
|
|
208
|
+
|
|
209
|
+
await element(by.id('animated-color-test-pressable')).longPressAndDrag(
|
|
210
|
+
500,
|
|
211
|
+
0.5,
|
|
212
|
+
0.5,
|
|
213
|
+
element(by.id('press-style-native-root')),
|
|
214
|
+
0.5,
|
|
215
|
+
0.1,
|
|
216
|
+
'slow',
|
|
217
|
+
100
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
221
|
+
|
|
222
|
+
await expect(element(by.id('animated-press-in-count'))).toHaveText('In: 1')
|
|
223
|
+
await expect(element(by.id('animated-press-out-count'))).toHaveText('Out: 1')
|
|
224
|
+
await expect(element(by.id('animated-is-pressed'))).toHaveText('Pressed: NO')
|
|
225
|
+
})
|
|
226
|
+
})
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
async function navigateToPressStyleNative() {
|
|
230
|
+
await navigateToTestCase('PressStyleNative', 'color-test-pressable')
|
|
231
|
+
}
|