Detox: Detox doesn't wait for button animation

Description

Hi, I’m new to Detox and not a very experienced developer so apologies if the answer to this is very obvious, I haven’t found any other bugs about this problem. In the Detox documentation I read the following in the “Endless looping animations” section:

By default, Detox will wait until animations complete.

But it doesn’t do that for me, below is a screen recording of when the test taps a button prematurely, along with the code that’s being run.

https://user-images.githubusercontent.com/7572926/108333565-61eda580-71d1-11eb-8b47-26e09629b12b.mov

Screenshot 2021-02-16 at 10 53 28

I also ran the test with the debug-synchronization 500 argument, see log below, I’ve highlighted where the test taps the button too early.

Screenshot 2021-02-16 at 15 10 02
  • I have tested this issue on the latest Detox release and it still reproduces

Reproduction

This has been the most puzzling thing about this issue, I’ve tried different solutions that by all indications seem to be working - for example I added the waitFor + toBeVisible before tapping the button as in the first screen shot above - but when I get back the next morning I see the problem again.

Step by step

  1. Start test
  2. Watch the test tap button too early

Expected behavior

Test should wait for button to animate before tapping it

Environment (please complete the following information):

  • Detox: 18.2.2
  • React Native: 0.63.4
  • Node: 15.7.0
  • Device: iPhone 11 simulator
  • Xcode: 12.4
  • iOS: 14.4
  • macOS: 10.15.7

Logs

If you are experiencing a timeout in your test

If you are seeing a Detox build problem (e.g. during npm install, not detox build)

I’m not

  • I am providing the npm install log below:

Device and verbose Detox logs

  • I have run my tests using the --loglevel trace argument and am providing the verbose log below:

trace.txt

Thanks for your time

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 28 (3 by maintainers)

Most upvoted comments

@onnerfors yes, it’s probably a good idea to delay the process, and figure out if the animation is the root cause. await new Promise(resolve => setTimeout(resolve, 5000));

Sorry @d4vidi was thrown into a project at work, will try to find some time for it soon

Hello, it seems MotiView animations are not tracked either as I just ran into the same problem with Detox’s latest version.

@onnerfors with #2746 all done and well, we now have DetoxTemplate ready for easy reproductions. Perhaps you could work out a reproduction based on it? You can easily fork it and have a project up and running in a breeze.

@onnerfors no problem. Hopefully by then we will have a skeletal project you could use (#2746)

Good point @noomorph, in fact I thought I was running the latest version, that npm updated the package automagically on npm install. The issue persists with 18.11.1 though.

Hi @alon-ha, sure, I’ve attached the .tsx of the button as well as the Animated.View from the screen it’s a part of. Let me know if there’s anything else you need.

OnboardingContinueButton.tsx

import React, { useEffect, useRef } from 'react';
import { Animated, StyleSheet } from 'react-native';
import { t } from 'i18n-js';
import Button from '@components/Button';
import OnboardingScreen from './OnboardingScreen';

const styles = StyleSheet.create({
  button: {
    marginVertical: 0,
  },
});

const DEFAULT_DURATION = 420;

type Props = {
  visible: boolean;
  nextScreen: string;
  onPress: () => void;
  animationDuration?: number;
  label?: string;
};

const OnboardingContinueButton = ({
  visible,
  onPress,
  animationDuration = DEFAULT_DURATION,
  nextScreen,
  label,
}: Props): JSX.Element => {
  const opacity = useRef(new Animated.Value(0)).current;

  useEffect(() => {
    Animated.timing(opacity, {
      toValue: visible ? 1 : 0,
      duration: animationDuration,
      useNativeDriver: false,
    }).start();
  }, [animationDuration, opacity, visible]);

  return (
    <Animated.View style={{ opacity }}>
      <Button
        buttonStyle={styles.button}
        title={label || t('onboarding.continueButtonLabel')}
        onPress={onPress}
        isDisabled={!visible}
        testID={`onboardingContinueButton${nextScreen}`}
      />
    </Animated.View>
  );
};

export default OnboardingContinueButton;

Animated.View from OnboardingScreen.tsx

<Animated.View
          style={[
            styles.continueButtonContainer,
            {
              opacity: animatedValue.current.interpolate({
                inputRange: [0, 1],
                outputRange: [1, 0],
              }),
            },
          ]}
        >
          <OnboardingContinueButton
            onPress={onPressContinue}
            label={continueButtonLabel}
            visible={continueButtonVisible}
            animationDuration={continueButtonAnimationDuration}
          />
        </Animated.View>