fix(Android, Tabs): expose tab item testID as viewIdResourceName - #4497
Open
mackbrowne wants to merge 1 commit into
Open
fix(Android, Tabs): expose tab item testID as viewIdResourceName#4497mackbrowne wants to merge 1 commit into
mackbrowne wants to merge 1 commit into
Conversation
A bottom tab item's testID is written to the view's tag property only. That works for Espresso, as the existing comment notes, but UiAutomator-based drivers (Maestro, Appium) match on AccessibilityNodeInfo.viewIdResourceName and never read the tag, so for them the id is invisible and selectors silently match nothing. This is inconsistent with the rest of React Native: ReactAccessibilityDelegate sets info.viewIdResourceName = testId for every ordinary view, which is why id selectors work everywhere else in an RN app on Android but not on native tab items. Mirror the testID onto the accessibility node while keeping the tag assignment, so both driver families work. super is called first so Material's own node population, including the contentDescription and the "tab, N of M" announcement, is preserved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Closes #4496.
A bottom tab item's
testIDis written to the view'stagproperty only:As the comment says, that works for Espresso. But UiAutomator-based drivers — Maestro and Appium — match on
AccessibilityNodeInfo.getViewIdResourceName()(exposed asresource-id) and never read the view tag. For them the id is invisible, and a selector silently matches nothing rather than failing loudly, which reads as a flaky tap.This is inconsistent with the rest of React Native.
ReactAccessibilityDelegatedoesinfo.viewIdResourceName = testIdfor every ordinary view, which is whyidselectors work everywhere else in an RN app on Android but stop working on native tab items specifically.Worth noting the intent behind the prop: the JS-side counterpart, expo/expo#47472, added
testIDtoNativeTabs.Triggerexplicitly "so native tabs can be matched in end-to-end tests". On Android that currently only holds for Espresso.Changes
TabsHostA11yCoordinator.setA11yPropertiesToTabItemnow also setsviewIdResourceNameon the tab item's accessibility node, via aAccessibilityDelegateCompat.tagassignment is kept, so Espresso is unaffected.super.onInitializeAccessibilityNodeInfois called first, so Material's own node population — including thecontentDescriptionand the "tab, N of M" announcement — is preserved.tabsScreen.tabBarItemTestIDat node-init time rather than capturing it, so a prop update is reflected without reinstalling the delegate.No public API change, and no visual change, so the visual documentation section is omitted.
Test plan
Verified on a Pixel 8 emulator (API 34) against
react-native-screens4.26.2 applied as a patch, withexpo-router57.0.11unstable-native-tabsand Maestro 2.6.0. The same change againstmain's shape is what this PR contains;ktlint 1.3.0(matchingandroid/spotless.gradle) reports clean on the modified file.Minimal example:
Inspect the accessibility tree, no test framework required:
resource-idresource-id="tab-home"/resource-id="tab-search"In both cases
content-descstill holds the label andselectedstill tracks the active tab, so the screen-reader behaviour is unchanged. Equivalently, a Maestro step- tapOn: { id: "tab-search" }matches nothing before the change and taps the tab after it; in a real suite all four tabs of an app shell flow now tap by id.I have not been able to run the repo's own Android e2e suite locally, so I would appreciate CI confirming that. Happy to add a
Test*.tsxexample underapps/src/testsif you would like one for this.Checklist