Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
10 contributors

Users who have contributed to this file

@rotemmiz @simonracz @xcarpentier @vonovak @vadimshvetsov @LeoNatan @joegoodall2 @isnifer @dluksza @DanielMSchmidt
167 lines (121 sloc) 4.5 KB

Matchers

Detox uses Matchers to find UI elements in your app, Actions to emulate user interaction with those elements and Expectations to verify values on those elements.

Matchers find elements in your app that match one or more properties.

NOTE: Whenever possible we recommend to match elements by.id, these are more resilient to layout restructuring and text/language changes

Methods

by.id(id)

by.id will match an id that is given to the view via testID prop.

In a React Native component add testID like so:

<TouchableOpacity testID={'tap_me'}>
...

Then match with by.id:

element(by.id('tap_me'));

For other cases, and only if you can't use by.id there is a variety of options:

by.text(text)

Find an element by text, useful for text fields, buttons.

element(by.text('Tap Me'));

by.label(label)

Find an element by accessibilityLabel on iOS, or by contentDescription on Android.

element(by.label('Welcome'));

by.type(nativeViewType)

Find an element by native view type. View types differ between iOS and Android.

on iOS:

element(by.type('RCTImageView'));

on Android, provide the class canonical name:

element(by.type('android.widget.ImageView'));

by.traits([traits])

Find an element with an accessibility trait. (iOS only)

element(by.traits(['button']));

Advanced

Multiple matchers
element(by.id('uniqueId').and(by.text('some text')));
Match by id and by parent id
element(by.id('child').withAncestor(by.id('parent')));
Match by id and by child id
element(by.id('parent').withDescendant(by.id('child')));
Example
  • To find the view with the id child

     <View testID='grandparent' style={{padding: 8, backgroundColor: 'red', marginBottom: 10}}>
       <View testID='parent' style={{padding: 8, backgroundColor: 'green'}}>
         <View testID='child' style={{padding: 8, backgroundColor: 'blue'}}>
           <View testID='grandchild' style={{padding: 8, backgroundColor: 'purple'}} />
         </View>
       </View>
     </View>

    Use:

     // any of the following will work
     element(by.id('child'));
     element(by.id('child').withAncestor(by.id('parent')));
     element(by.id('child').withDescendant(by.id('grandchild')));

Dealing with multiple elements matching the same matcher

When a matcher matches multiple views, there are three possible solutions:

  1. Use multiple matchers to narrow down the matched results.

  2. Add unique identifiers (testIDs) to the view which need to matched. A common use-case, is adding identifiers to list items. testIDs for FlatList items can be assigned dynamically, by passing index in renderItem({item, index}) and using it in the component's render function.

    FlatList renderItem function:

    renderItem({item, index}) {
      return (
           <CustomComponent
             index={index}
             ...
           />
      );
    }

    CustomComponent's render function:

    render() {
      return (
        <View
          testID={'listitem' + this.props.index}
          ...
        />
      );
    }
  3. Select a matched view from the matched view list using atIndex

    element(by.text('Product')).atIndex(2);

Usage of atIndex is not recommended!, since the order of matched views can not be guaranteed by the system. Recyclable views in UITableView / UICollectionView / RecyclerView or any custom view may even change during scroll, while views are being recycled with new data. React Native FlatList items are being traversed in different ways on the different platforms, causing atIndex to return the opposite indexes on iOS than what it does on Android.

TIP: Finding the back button on iOS

on iOS 11:

element(by.traits(['button']).and(by.label('Back')));

on iOS 10:

element(by.type('_UIModernBarButton').and(by.label('Back')));
You can’t perform that action at this time.