This is what I meant about the animating button. I let it have an ID, but it can't be located by the Detox somehow.
Detox eliminates flakiness by automatically synchronizing your tests with the app. A test cannot continue to the next line if the app is busy. The test will only resume when the app becomes idle. Detox monitors your app very closely in order to know when it's idle. It tracks several asynchronous operations and waits until they complete. This includes:
Keeping track of all network requests that are currently in-flight and waiting until they complete Keeping track of pending animations and waiting until they complete Keeping track of timers (like setTimeout) and waiting until they expire Keeping track of the React Native bridge which carries asynchronous messages Keeping track of asynchronous React Native layout and the shadow queue Keeping track of the JavaScript event loop which may contain pending asynchronous actions
So apparently there is a line saying that keeping track of pending animation, so if the button keeps animating like this. Then It will keep waiting? Thus, usually how to deal with this issue properly?
Thanks
From Detox documentation:
Endless looping animations
By default, Detox will wait until animations complete. If you have an endless looping animation, this may cause Detox to hang. In this case, consider turning off the animation synchronization or remove the endless loop in your E2E build with react-native-repackager.
https://github.com/wix/detox/blob/master/docs/Troubleshooting.Synchronization.md#endless-looping-animations
General remarks
Infinite animations (looped animations) can make detox wait forever. Please consider turning looped animations off for testing. It's also a good practice to speed up all animations for testing.
https://github.com/wix/detox/blob/master/docs/More.AndroidSupportStatus.md#general-remarks
Detox provides disableSynchronization()
- so you can temporarily disable synchronization to work around an animation
and then turn it back on after the animation is gone. This however will not work for all cases. For example if you are using react-navigation and the on press button pushes new screen to the navigation stack the button is still going to continue animating in the background, blocking any further tests you are planning to run on the new screen.
So ideally you want to go with the other suggestion and disable these types of animations for your E2E tests. Here are 3 possible options to achieve this.
A:
Detox authors suggest using react-native-repackager for this. At the moment it only supports RN 0.51, so this might not be ideal for everyone. Please check supported version before using.
Currently supports only RN 0.51
B:
Set up React Native build environments. Based on an environment configuration variables you can then disable continues animations when building for E2E tests.
https://blog.carbonfive.com/2016/09/29/setting-up-react-native-build-environments-using-nativemodules/
C:
The easiest way I found is to use react-native-config. Here is also a good article on Managing Configuration in React Native with react-native-config, and another related question how-to-tell-detox-is-running-tests.
Install the package:
$ yarn add react-native-config
Link the library:
$ react-native link react-native-config
To test this solution I created 2 files, .env.production
and .env.testing
in the root React Native app directory. I am then using IS_ANIMATE config variable to toggle animation depending on the build environment. You need to add ENVFILE=.env.testing
and ENVFILE=.env.production
to your detox build config.
.env.production
ENV_TYPE=Production
IS_ANIMATE=1
.env.testing
ENV_TYPE=Testing
IS_ANIMATE=0
app.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)
example.spec.js
it('Animated Button', async () => {
const buttonElement = element(by.id('button'));
await expect(buttonElement).toBeVisible();
await buttonElement.tap();
});
package.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"
}
}
}
The release build will hang: detox build --configuration ios.sim.release && detox test --configuration ios.sim.release
The test build will pass: detox build --configuration ios.sim.test && detox test --configuration ios.sim.test
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With