detox
An entity that defines properties on how to locate a view within the current view hierarchy, either user properies like id
or text
, location in view hierarchy and other UI properties.
Views can be matched with multiple matchers.
<View style={{flex: 1, paddingTop: 20, justifyContent: 'center', alignItems: 'center'}}>
<Text style={{fontSize: 25, marginBottom: 30}}>
Welcome
</Text>
{this.renderTestButton('Say Hello', this.onButtonPress.bind(this, 'Hello'))}
{this.renderTestButton('Say World', this.onButtonPress.bind(this, 'World'))}
</View>
Will be matched by:
await element(by.label('Welcome')))
<View testID='Grandfather883' style={{padding: 8, backgroundColor: 'red', marginBottom: 10}}>
<View testID='Father883' style={{padding: 8, backgroundColor: 'green'}}>
<View testID='Son883' style={{padding: 8, backgroundColor: 'blue'}}>
<View testID='Grandson883' style={{padding: 8, backgroundColor: 'purple'}} />
</View>
</View>
</View>
Will be matched by:
await element(by.id('Grandson883'))
await element(by.id('Grandson883').withAncestor(by.id('Son883')))
await element(by.id('Son883').withDescendant(by.id('Grandson883')))
Xcode can display the native view hierarchy, by doing so, we can find the native view type, and match by that property.
Will be matched by:
await element(by.type('RCTImageView'))
<View style={{flexDirection: 'row', marginBottom: 20}}>
<Text testID='ProductId000' style={{margin: 10}}>Product</Text>
<Text testID='ProductId001' style={{margin: 10}}>Product</Text>
<Text testID='ProductId002' style={{margin: 10}}>Product</Text>
<Text testID='ProductId003' style={{margin: 10}}>Product</Text>
</View>
await element(by.label('Product')).atIndex(2)
When a single view property is not enough, multiple matchers can be combined
<Text testID='UniqueId345' style={{color: 'blue', marginBottom: 20}}>ID</Text>
Will be matched by:
await element(by.id('UniqueId345').and(by.label('ID')))
An entity that interacts with the matched view, simulating user actions.
await element(by.label('Tap Me')).tap();
await element(by.label('Tap Me')).longPress();
await element(by.id('UniqueId819')).multiTap(3);
await element(by.id('UniqueId937')).typeText('passcode');
await element(by.id('UniqueId937')).replaceText('passcode again');
await element(by.id('UniqueId005')).clearText();
await element(by.id('ScrollView161')).scroll(100, 'down');
await element(by.id('ScrollView161')).scroll(100, 'up');
await element(by.id('ScrollView161')).scrollTo('bottom');
await element(by.id('ScrollView161')).scrollTo('top');
// directions: 'up'/'down'/'left'/'right', speed: 'fast'/'slow'
await element(by.id('ScrollView799')).swipe('down', 'fast');
The expection entity, asserting that the matched views have certain properties: visibility, content, etc...
await expect(element(by.id('UniqueId204'))).toBeVisible();
await expect(element(by.id('UniqueId205'))).toBeNotVisible();
await expect(element(by.id('UniqueId205'))).toExist();
await expect(element(by.id('RandomJunk959'))).toNotExist();
await expect(element(by.id('UniqueId204'))).toHaveText('I contain some text');
await expect(element(by.id('UniqueId204'))).toHaveLabel('I contain some text');
await expect(element(by.label('I contain some text'))).toHaveId('UniqueId204');
await expect(element(by.id('UniqueId146'))).toHaveValue('0');
await waitFor(element(by.id('UniqueId336'))).toExist().withTimeout(2000);
await waitFor(element(by.label('Text5'))).toBeVisible().whileElement(by.id('ScrollView630')).scroll(50, 'down');
If this is a react native app, reload react native JS bundle
await device.reloadReactNative();
Install the app file defined in the current configuration
await device.installApp();
Uninstall the app defined in the current configuration
await device.uninstallApp();
The following command mock starting of the application from various sources
await device.relaunchApp(params);
await openURL(url);
await sendUserNotification(params);
See the Detailed API for more information.