React Native UI element access via testID

I’m developing some iOS/Android apps using React Native.

React Native Views (https://facebook.github.io/react-native/docs/view.html) can have a testID value to allow them to be found when doing automated testing.

Using elementByName() I can find views by the testID values in Appium on iOS but not on Android - from digging around it looks like React Native puts the testID value into the the Android View’s tag (see https://github.com/facebook/react-native/blob/a99c5160eeeedec0d08afca1a7cda235418765f4/ReactAndroid/src/androidTest/java/com/facebook/react/testing/ReactTestHelper.java)

Is there any way to get at that using Appium? If not would it be difficult to add?

Thanks
Darren

appium supports finding by content description.

React test ID is currently propagated into view content description.
https://github.com/facebook/react-native/blob/a99c5160eeeedec0d08afca1a7cda235418765f4/ReactAndroid/src/androidTest/java/com/facebook/react/testing/ReactTestHelper.java#L93

See find by accessibility id.

driver.findElementByAccessibilityId(“play-button”);
http://sauceio.com/index.php/2015/06/appium-sauce-labs-bootcamp-chapter-1-language-bindings/

Finding by accessibility id doesn’t work for React Native View testID - it works for accessibilityLabel but that’s a user-facing string (e.g. read out by TalkBack) so I’d prefer not to put test ids in there.

So I don’t think that comment is correct - in the methods themselves you’ll see that Android View.getTag() and setTag() are used so unless that propagation is done somewhere else the comment is definitely wrong.
Also I’m not sure if it’s the correct thing to do anyway - if the tag value gets propagated via View.setContentDescription() then we’re again in the territory of test ids being exposed to users.

Content descriptions on Android are always user facing. You might want to ask the react team how you’d find a testID with uiautomator, then you could do the same with appium.

React Native put testID into the tag of view, and accessibilityLabel into content description:

I don’t think Appium can get info from tag, am I right?

I guess the React Native team used the tag because it’s one of the few non user-facing places in View to store custom data.
I don’t think uiautomator can find by tag so presumably their automated tests use something that can (e.g. Calabash).

Any thoughts for workarounds in Appium? I could add test ids via accessibilityLabel for testing and then remove them for production but that’s cumbersome and also kind of goes against the Appium ethos.

Appium is in the process of upgrading to uiautomator v2 which can find by tags because we have the full instrumentation API available. It’ll probably take a very long time to be ready though. In uiautomator v1 (what appium currently uses), this isn’t possible.

The only work around I know of is exactly what you mentioned, strip the automaton only content descriptions out of production builds.

Oh. I thought of a good work around. Set the resource id on the view instead since uiautomator can locate that in API >= 18.

http://developer.android.com/reference/android/view/View.html#setId(int)
http://developer.android.com/reference/android/view/View.html#attr_android:id

Would that need modifications to React Native? I don’t think there’s currently a way to specify the resource id of the Android View that backs a React Native View so it might need a new property (can’t use the testID because that’s a string and Android View.setId() takes an int).

Yes, you’d need the setId method to be exposed. Also you’d need a resource reference (what the int refers to). I don’t think arbitrary ints would work well.

One workaround you could do is to set accessibilityLabel to a conditional value depending if you are building for debug or production (or just have some global flag to indicate that). While not ideal, it will minimize code changes and will allow you to access elements for testing.

However, I would like to ask you a related question… I was not able to set accessibilityLabel which could map to content description for Inputs and Buttons (TouchableHighlight / TouchableOpacity elements). I could see content-desc field in UI Automator for other elements but not for anything actionable. Have you been able to see / access those elements in your test??

It is a bug in react native.
In their code they left out accessibilityLabel

I submit a PR to add it

In the mean while my question for Appium team. @bootstrap
There is no accessibilityIdentifier equivalent on Android. What is the best strategy to set some id-type string to locate elements without messing with content description?
release/debug build is an option but not ideal.

The options on Android are: resource ids, content descriptions, and view tags. Appium supports the first two.

any update on viewtag support?
The PR for Reactive Native Touchables is merged BTW so at least that part is working.

1 Like

I recommend opening an issue on the appium github tracker. I don’t work on appium anymore so it’ll be up to the other devs.

React Native is pretty cool so it seems like something appium should support.

Hey all, I have a PR against react-native to add proper support for resource-id. Check it out and up-vote please: https://github.com/facebook/react-native/pull/9942

Once that’s merged in testID will add resource-id so long as the Id is defined in res/values/ids.xml.

FYI there has been some activity on this:

The appium issue is:

How to click on ReactNative component in which resource-id is not present & clickable= ‘False’

https://github.com/wix/detox has react-native support, may be worth looking at.