8

这就是我对动画按钮的意思。我让它有一个 ID,但 Detox 无法以某种方式找到它。

动画按钮

Detox 通过自动将您的测试与应用程序同步来消除片状。如果应用程序繁忙,则测试无法继续到下一行。只有当应用程序空闲时,测试才会恢复。Detox 非常密切地监控您的应用程序,以便了解它何时处于空闲状态。它跟踪几个异步操作并等待它们完成。这包括:

跟踪当前正在进行的所有网络请求并等待它们完成 跟踪未决动画并等待它们完成 跟踪计时器(如 setTimeout)并等待它们到期 跟踪承载异步的 React Native 桥消息 跟踪异步 React Native 布局和影子队列 跟踪可能包含未决异步操作的 JavaScript 事件循环

所以显然有一条线说要跟踪待处理的动画,所以如果按钮保持这样的动画。那么它会一直等待吗?因此,通常如何正确处理这个问题?

谢谢

4

2 回答 2

14

来自排毒文档:

无尽的循环动画

默认情况下,排毒会等到动画完成。如果您有无限循环动画,这可能会导致 Detox 挂起。在这种情况下,请考虑关闭动画同步或使用 react-native-repackager 删除 E2E 构建中的无限循环。

https://github.com/wix/detox/blob/master/docs/Troubleshooting.Synchronization.md#endless-looping-animations

一般说明

无限动画(循环动画)可以让排毒永远等待。请考虑关闭循环动画进行测试。加快所有动画以进行测试也是一个好习惯。

https://github.com/wix/detox/blob/master/docs/More.AndroidSupportStatus.md#general-remarks

Detox 提供disableSynchronization()- 因此您可以暂时禁用同步以解决动画问题,然后在动画消失后将其重新打开。然而,这并不适用于所有情况。例如,如果您使用react-navigation并且按下按钮将新屏幕推送到导航堆栈,则该按钮仍将继续在后台动画,阻止您计划在新屏幕上运行的任何进一步测试。

因此,理想情况下,您希望采用其他建议并为您的 E2E 测试禁用这些类型的动画。这里有 3 个可能的选项来实现这一点。

A:

Detox 作者建议为此使用react-native-repackager。目前它只支持 RN 0.51,所以这可能并不适合所有人。使用前请检查支持的版本。

目前仅支持 RN 0.51

乙:

设置 React Native 构建环境。根据环境配置变量,您可以在构建 E2E 测试时禁用继续动画。

https://blog.carbonfive.com/2016/09/29/setting-up-react-native-build-environments-using-nativemodules/

C:

我发现最简单的方法是使用react-native-config。这里还有一篇关于使用 react-native-config在 React Native 中管理配置的好文章,以及另一个相关问题how-to-tell-detox-is-running-tests

安装包:

$ yarn add react-native-config

链接库:

$ react-native 链接 react-native-config

为了测试这个解决方案,我创建了 2 个文件,.env.production.env.testing在根 React Native 应用程序目录中。然后我使用IS_ANIMATE配置变量根据构建环境切换动画。您需要添加ENVFILE=.env.testingENVFILE=.env.production到您的 detox 构建配置。

.env.production

ENV_TYPE=Production
IS_ANIMATE=1

.env.testing

ENV_TYPE=Testing
IS_ANIMATE=0

应用程序.js

import Config from 'react-native-config'

import React, { Component } from 'react'
import {
  AppRegistry,
  StyleSheet,
  Alert,
  Animated,
  View,
  TouchableOpacity,
  Text
} from 'react-native'

class example extends Component {
  constructor(props) {
    super(props)

    this.state = {
      radius: new Animated.Value(1)
    }
  }

  componentDidMount() {
    // only enable animation for production
    if (Config.IS_ANIMATE == true) {
      this.cycleAnimation()
    }
  }

  cycleAnimation() {
    Animated.loop(
      Animated.sequence([
        Animated.timing(this.state.radius, {
          toValue: 2,
          duration: 500,
          delay: 1000
        }),
        Animated.timing(this.state.radius, {
          toValue: 1,
          duration: 500
        })
      ])
    ).start()
  }

  render() {
    return (
      <View testID='container' style={styles.container}>
        <Text>{Config.ENV_TYPE}</Text>
        <TouchableOpacity
          testID='button'
          onPress={() => Alert.alert("I was pressed")}
        >
          <Animated.View
            style={[
              styles.button,
              {transform: [
                {scale: this.state.radius},
              ]}
            ]}
          >
            <Text>START DIARY</Text>
          </Animated.View>
        </TouchableOpacity>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  button: {
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 60,
    width: 120,
    height: 120,
    backgroundColor: 'green'
  },
  text: {
    padding: 5,
    fontSize: 14
  }
})

AppRegistry.registerComponent('example', () => example)

例子.spec.js

it('Animated Button', async () => {
  const buttonElement = element(by.id('button'));
  await expect(buttonElement).toBeVisible();
  await buttonElement.tap();
});

包.json

"detox": {
  "specs": "e2e",
  "configurations": {
    "ios.sim.release": {
      "binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app",
      "build": "ENVFILE=.env.production export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -project ios/example.xcodeproj -scheme example -configuration Release -sdk iphonesimulator -derivedDataPath ios/build",
      "type": "ios.simulator",
      "name": "iPhone 5s, iOS 10.3"
    },
    "ios.sim.test": {
      "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
      "build": "ENVFILE=.env.testing xcodebuild -project ios/example.xcodeproj -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -arch x86_64",
      "type": "ios.simulator",
      "name": "iPhone 5s, iOS 10.3"
    }
  }
}

发布版本将挂起:detox build --configuration ios.sim.release && detox test --configuration ios.sim.release

排毒挂起

测试构建将通过:detox build --configuration ios.sim.test && detox test --configuration ios.sim.test

detox_passes

于 2017-11-20T21:08:17.910 回答
0

您可以通过使用解决这个无限动画循环

await device.disableSynchronization();

只需在与动画元素交互之前放置此行,然后您就可以再次启用同步

await device.enableSynchronization();

此功能之前有一个错误,他们只是在此版本中修复了它:18.18.0

于 2021-07-02T12:31:43.540 回答