From 113417fe0cb3f26cf098d440936f6f53a1ced54a Mon Sep 17 00:00:00 2001 From: Thiago Brezinski Date: Thu, 2 Jul 2026 14:17:03 +0100 Subject: [PATCH] fix(android): expose tab test ids to UIAutomator --- .changeset/maestro-android-testid.md | 5 +++ .../main/java/com/rcttabview/RCTTabView.kt | 32 +++++++++++++++---- 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 .changeset/maestro-android-testid.md diff --git a/.changeset/maestro-android-testid.md b/.changeset/maestro-android-testid.md new file mode 100644 index 00000000..e0879f7d --- /dev/null +++ b/.changeset/maestro-android-testid.md @@ -0,0 +1,5 @@ +--- +"react-native-bottom-tabs": patch +--- + +Expose Android tab button test IDs as accessibility resource IDs for UIAutomator-based E2E tools. diff --git a/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt b/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt index 911d2789..588ed293 100644 --- a/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt +++ b/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt @@ -20,7 +20,10 @@ import android.view.ViewGroup import android.widget.FrameLayout import android.widget.LinearLayout import android.widget.TextView +import androidx.core.view.AccessibilityDelegateCompat import androidx.core.view.MenuItemCompat +import androidx.core.view.ViewCompat +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat import androidx.core.view.forEachIndexed import coil3.ImageLoader import coil3.asDrawable @@ -281,12 +284,7 @@ class ReactBottomNavigationView(context: Context) : LinearLayout(context) { onTabSelected(menuItem) } - item.testID?.let { testId -> - view.findViewById(com.google.android.material.R.id.navigation_bar_item_content_container) - ?.apply { - tag = testId - } - } + applyTestID(view, item.testID) } } } @@ -301,6 +299,28 @@ class ReactBottomNavigationView(context: Context) : LinearLayout(context) { return bottomNavigation.menu.findItem(index) ?: bottomNavigation.menu.add(0, index, 0, title) } + private fun applyTestID(itemView: View, testID: String?) { + val contentContainer = + itemView.findViewById(com.google.android.material.R.id.navigation_bar_item_content_container) + ?: return + + contentContainer.tag = testID + if (testID == null) { + ViewCompat.setAccessibilityDelegate(contentContainer, null) + return + } + + ViewCompat.setAccessibilityDelegate(contentContainer, object : AccessibilityDelegateCompat() { + override fun onInitializeAccessibilityNodeInfo( + host: View, + info: AccessibilityNodeInfoCompat + ) { + super.onInitializeAccessibilityNodeInfo(host, info) + info.viewIdResourceName = testID + } + }) + } + private fun updateIconTintMode(menuItem: MenuItem, item: TabInfo) { MenuItemCompat.setIconTintMode( menuItem,