Apologies in advance if this has been asked before. I came across the detox
e2e framework for react native apps, and I thought of giving it a try.
I am trying to automate this demo mobile application given here - link
Since the tests in detox
uses testID
as one of the locators so I added one in the LoginScreenMaterial.js
file inside app/screen/LoginScreenMaterial.js
like this
<View testID="login_screen" style={{width: this._width, justifyContent: 'center'}}>
<RkCard style={styles.container}>
<View rkCardHeader style={styles.header}>
<RkText/>
<RkText style={styles.label}>Sign in into your account</RkText>
</View>
However, even after sucessfully building the app, I ran the app with this simple test
it('should have welcome screen', async () => {
await expect(element(by.id('login_screen'))).toBeVisible();
});
However, the tests still fail with the element being failed to be recognised. What am I missing here in this tests? Can we not add testID
like this explicitly in the .js
file.
Edit 1 : Adding the error message
1) Example
should have welcome screen:
Error: Error: Cannot find UI Element.
Exception with Assertion: {
"Assertion Criteria" : "assertWithMatcher:matcherForSufficientlyVisible(>=0.750000)",
"Element Matcher" : "(((respondsToSelector(accessibilityIdentifier) && accessibilityID('login_screen')) && !(kindOfClass('RCTScrollView'))) || (kindOfClass('UIScrollView') && ((kindOfClass('UIView') || respondsToSelector(accessibilityContainer)) && ancestorThatMatches(((respondsToSelector(accessibilityIdentifier) && accessibilityID('login_screen')) && kindOfClass('RCTScrollView'))))))",
"Recovery Suggestion" : "Check if the element exists in the UI hierarchy printed below. If it exists, adjust the matcher so that it accurately matches element."
}
Error Trace: [
{
"Description" : "Interaction cannot continue because the desired element was not found.",
"Error Domain" : "com.google.earlgrey.ElementInteractionErrorDomain",
"Error Code" : "0",
"File Name" : "GREYElementInteraction.m",
"Function Name" : "-[GREYElementInteraction matchedElementsWithTimeout:error:]",
"Line" : "124"
}
]
at Client.execute (node_modules/detox/src/client/Client.js:74:13)
Detox is a JavaScript mobile testing framework that is built into the application so that the test execution starts with the app launch. This makes test execution fast and robust because no additional external tools are needed to orchestrate and synchronize tests.
I took a look at the application and was able to get it to work. I set the following in my devDependencies.
"devDependencies": {
...
"jest": "23.2.0",
"detox": "8.0.0"
...
},
To the package.json I also added
"detox": {
"configurations": {
"ios.sim.debug": {
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/BoomApp.app",
"build": "xcodebuild -project ios/BoomApp.xcodeproj -scheme BoomApp -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
"type": "ios.simulator",
"name": "iPhone 7"
}
},
I ran detox init -r jest
I was then able to get it to recognise when a specific screen had been rendered I did this by adding the testID to the ScrollView LoginScreenBlur.js (line 23)
<AppWrapper>
<ScrollView contentContainerStyle={{flex: 1}} testID={'login_screen'}>
....
</ScrollView>
</AppWrapper>
A then in e2e/firstTest.spec.js
I replaced the tests with
it('should have loginScreen', async () => {
await expect(element(by.id('login_screen'))).toBeVisible();
});
This was my console response after running detox build && detox test
node_modules/.bin/jest e2e --config=e2e/config.json --maxWorkers=1 --testNamePattern='^((?!:android:).)*$'
server listening on localhost:64579...
: Searching for device matching iPhone 7...
: Uninstalling org.reactjs.native.example.BoomApp...
: org.reactjs.native.example.BoomApp uninstalled
: Installing /Users/work/Downloads/react-native-ui-kitten-demo-app-master/ios/build/Build/Products/Debug-iphonesimulator/BoomApp.app...
: /Users/work/Downloads/react-native-ui-kitten-demo-app-master/ios/build/Build/Products/Debug-iphonesimulator/BoomApp.app installed
: Terminating org.reactjs.native.example.BoomApp...
: org.reactjs.native.example.BoomApp terminated
: Launching org.reactjs.native.example.BoomApp...
7: org.reactjs.native.example.BoomApp launched. The stdout and stderr logs were recreated, you can watch them with:
tail -F /Users/work/Library/Developer/CoreSimulator/Devices/AF406169-5CF3-4480-9D00-8F934C420043/data/tmp/detox.last_launch_app_log.{out,err}
PASS e2e/firstTest.spec.js (7.935s)
Example
✓ should have loginScreen (1499ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 8.87s, estimated 9s
Ran all test suites matching /e2e/i with tests matching "^((?!:android:).)*$".
It would seem that the app defaults to launching LoginScreenBlur, so it would make sense to test it first, rather than LoginScreenMaterial.
One thing I have noticed is that the application uses RKTextInput
and RkButton
, these are not native components but wrappers around native components. This means that you will need to pass the testID down to the native component that you want to have the testID. I am not sure if react-native-ui-kitten
supports accessibility labels, so there may be some more work ahead if you wish to automate input of text and button taps.
Adding testID to custom components
See Step 3 https://github.com/wix/detox/blob/master/docs/Introduction.WritingFirstTest.md
Note that not all React components support this prop. Most of the built-in native components in React Native like View, Text, TextInput, Switch, ScrollView have support though. If you create your own composite components, you will have to propagate this prop manually to the correct native component.
A more detailed explanation of adding testID to custom components is given here https://github.com/wix/detox/blob/master/docs/Troubleshooting.RunningTests.md#cant-find-my-component-even-though-i-added-testid-to-its-props
Briefly you should implement your custom component as follows.
Custom Component
export class MyCompositeComponent extends Component {
render() {
return (
<TouchableOpacity testID={this.props.testID}>
<View>
<Text>Something something</Text>
</View>
</TouchableOpacity>
);
}
}
Using Custom Component
Then you should use it like this.
render() {
return <MyCompositeComponent testID='MyUniqueId123' />;
}
Searching the hierarchy
If you have done the above and you are sure your item has the correct testID and the tests are still failing, then you can search for it in the view hierarchy https://github.com/wix/detox/blob/master/docs/Troubleshooting.RunningTests.md#debug-view-hierarchy
I won't repeat the above post in full but the steps are
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