-
-
Notifications
You must be signed in to change notification settings - Fork 611
feat: Add testId and accessibilityLabel for BottomTabsScreen and Item #3497
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
kkafar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job! The code looks good here, I have just few remarks regarding it's exact structure. Please answer them.
android/src/main/java/com/swmansion/rnscreens/gamma/tabs/TabsHost.kt
Outdated
Show resolved
Hide resolved
| tabBarItem = [[UITabBarItem alloc] init]; | ||
| } | ||
|
|
||
| tabBarItem.accessibilityIdentifier = _tabBarItemTestId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks good, but I think it is in wrong place.
We should keep the flow. Instead of setting these props here, the intention of update should be propagated to tab bar controller (see how appearance is handled) and then actual props should be updated in RNSTabBarController.reactMoutingTransactionDidMount, e.g. after appearance pass is done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let me know if it could be implemented this way?
35384a8 to
fe47106
Compare
|
I'm not 100% positive we don't need to recreate the tab item when changing the id / label. Please check and let me know if adding the following code to bottom tabs' index.tsx to update the props programmatically after 2s actually changes the props (on iOS, with accessibility inspector). const [tabConfigs, setTabConfigs] = React.useState(TAB_CONFIGS);
useEffect(() => {
setTimeout(() => {
setTabConfigs([
{ ...TAB_CONFIGS[0], tabScreenProps: { ...TAB_CONFIGS[0].tabScreenProps, tabBarItemTestID: 'pomidor0', tabBarItemAccessibilityLabel: 'pomidor0' } },
{ ...TAB_CONFIGS[1], tabScreenProps: { ...TAB_CONFIGS[1].tabScreenProps, tabBarItemTestID: 'pomidor1', tabBarItemAccessibilityLabel: 'pomidor1' } },
{ ...TAB_CONFIGS[2], tabScreenProps: { ...TAB_CONFIGS[2].tabScreenProps, tabBarItemTestID: 'pomidor2', tabBarItemAccessibilityLabel: 'pomidor2' } },
{ ...TAB_CONFIGS[3], tabScreenProps: { ...TAB_CONFIGS[3].tabScreenProps, tabBarItemTestID: 'pomidor3', tabBarItemAccessibilityLabel: 'pomidor3' } },
])
}, 2000);
}, []);
...
<BottomTabsContainer
tabConfigs={tabConfigs} |
kkafar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good, and seems to work. Thank you!
I've left few more important remarks that need to be answered before we can land these changes.
| /** | ||
| * @summary testID for the BottomTabScreen | ||
| */ | ||
| testID?: string; | ||
|
|
||
| /** | ||
| * @summary accessibilityLabel for the BottomTabScreen | ||
| */ | ||
| accessibilityLabel?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you define testID & accessibilityLabel for the TabScreen itself, however please note that TabScreen Android implementation does not inherit form ReactViewGroup. How does it work then? Could you describe it in PR description, please?
Is is the question of ReactViewManager using the accessibility delegate & not relying on state defined explicitly in ReactViewGroup?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK this is set by BaseViewManager which TabScreenViewManager extends somehow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. So it works provided that BaseViewManager does not rely on any state defined explicitly in ReactViewGroup. This is not perfect, but I guess we should be fine.
Can we please add a note to PR description that this is the case? (that we rely on ReactAndroid here).
android/src/main/java/com/swmansion/rnscreens/gamma/tabs/TabsHostA11yCoordinator.kt
Outdated
Show resolved
Hide resolved
| @property (nonatomic, nullable) NSString *tabItemTestID; | ||
| @property (nonatomic, nullable) NSString *tabItemAccessibilityLabel; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are these properties for here? If they are already defined on screen, then do we need to duplicate those here?
I see them being set in - [RNSBottomTabsScreenComponenView updateProps:oldProps] however I don't see a purpose. Could you explain it please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see them being defined anywhere else? I asked if it could be implemented this way here: #3497 (comment)
| if (tabBarItemNeedsA11yUpdate) { | ||
| [_controller updateTabItemA11yProps]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you wanna cleanup the invalidated flag here?
| if (tabBarItemNeedsA11yUpdate) { | ||
| [_controller updateTabItemA11yProps]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally this update should be deferred & only signalised to the controller. Same as appearance update or orientation update. Can we please align that?
I see now, that we haven't done so for scrollview edgeeffects for some reason. It should be subject of refactor in follow up PR, can we create ticket for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not the same, because here we want to update a specific item, and other deferred ones update the whole tabBar. I'd need to pass some id to get the item again in TabBarController, and I'm not sure it would look good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add state do the screen view controller (or just expose a property on controller & read the state from screen view) that can be read in the main loop of appearance coordinator to decide whether update is required or not.
I think this might be the way to go.
7d55725 to
7c387af
Compare
kkafar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Responded to your concern.
| if (tabBarItemNeedsA11yUpdate) { | ||
| [_controller updateTabItemA11yProps]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add state do the screen view controller (or just expose a property on controller & read the state from screen view) that can be read in the main loop of appearance coordinator to decide whether update is required or not.
I think this might be the way to go.
kligarski
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks good, I left 2 suggestions.
kkafar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Thank you.
Closes https://github.com/software-mansion/react-native-screens-labs/issues/503
Description
This PR adds
testIdandaccessibilityLabelsupport for BottomTabsScreen and Item. For iOS, this maps toaccessibilityIdentifierandaccessibilityLabel, respectively. For android, things are more complicated when it comes to the item (the screen is handled automatically by react native in BaseViewManager):testIdis mapped totagsince this is what appeared to be working with Detox, which uses espresso under the hoodaccessibilityLabelis mapped to the part of the contentDescription that overwrites tab title. With tab badge present, the final description is the title and badge description combined. Detox seems to be matching the parts of the description correctly with only the title/label as the selector. This prop is only available on android on API level 26 and up.Changes
Added 4 props to the bottom tab configuration object:
Added
nativeBottomTabs.e2e.tstest.Test code and steps to reproduce
Run the e2e test. Use e2e-utils from https://github.com/software-mansion/react-native-screens/pull/3430/changes#diff-04033cb65a060a8211fbcd7be662a11be0f32c9b98d2f0d510c489e4e74af450, otherwise iOS won't complete.