Skip to content

[Android] Selected State does not annonce when TextInput Component selected #31144

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
5b6d5ed
fix Selected State does not annonce when TextInput Component selected
fabOnReact Mar 12, 2021
502cac6
add test to verify accessibleState prop is passed to Component
fabOnReact Mar 12, 2021
74674ff
minor change
fabOnReact Mar 12, 2021
94c5af8
java test for setViewState accessibilityState
fabOnReact Mar 15, 2021
b02a426
remove createArray PowerMock
fabOnReact Mar 15, 2021
e04fa92
moving TextInput example to AccessabilityExample
fabOnReact Mar 16, 2021
efd34da
rewriting test case in Accessibility Example
fabOnReact Mar 17, 2021
a6cc587
remove Accessibility TextInput Example
fabOnReact Mar 17, 2021
79486b5
verify in Test that view isSelected after adding accessibilityState
fabOnReact Mar 18, 2021
8e76ab3
revert this change as rn-tester is meant for internal use
fabOnReact Mar 18, 2021
3659930
fix lint issues
fabOnReact Mar 18, 2021
ec338bc
Merge branch 'master' into fix/text-input-accessible-selected
fabOnReact Mar 18, 2021
3a0201b
remove accessibilityState from TextInput.js
fabOnReact Mar 18, 2021
6012e98
remove changes to JS tests as there are no JS changes
fabOnReact Mar 18, 2021
fe7a0fe
adding i to sendAccessiblityEvent_unstable
fabOnReact Mar 18, 2021
1203852
avoid runtime error with sendAccessibilityEvent_unstable
fabOnReact Mar 19, 2021
c5cf843
revert check to avoid runtime error
fabOnReact Mar 19, 2021
969d0c7
revert change - does not fix error and out of scope for https://githu…
fabOnReact Mar 19, 2021
76d3169
Merge branch 'master' into fix/text-input-accessible-selected
fabOnReact Mar 19, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,12 @@ public void setViewState(@NonNull T view, @Nullable ReadableMap accessibilitySta
if (accessibilityState == null) {
return;
}
if (accessibilityState.hasKey("selected")) {
view.setSelected(accessibilityState.getBoolean("selected"));
Copy link
Contributor Author

@fabOnReact fabOnReact Mar 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the java test case does not verify that view.setSelected(true) is invoked, but just verifies view.setTag(R.id.accessibility_state, accessibilityState), I will update the test to verify those scenarios.

This comment was marked as off-topic.

This comment was marked as outdated.

Copy link
Contributor Author

@fabOnReact fabOnReact Mar 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solved with commit 79486b5 more info at #31144 (comment) 🙏 ☮️

} else {
view.setSelected(false);
}
view.setTag(R.id.accessibility_state, accessibilityState);
view.setSelected(false);
view.setEnabled(true);

// For states which don't have corresponding methods in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,49 @@
import static org.fest.assertions.api.Assertions.assertThat;

import com.facebook.react.R;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.JavaOnlyMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole;
import com.facebook.react.views.view.ReactViewGroup;
import com.facebook.react.views.view.ReactViewManager;
import java.util.Locale;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.rule.PowerMockRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;

@PrepareForTest({Arguments.class})
@RunWith(RobolectricTestRunner.class)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "androidx.*", "android.*"})
public class BaseViewManagerTest {

@Rule public PowerMockRule rule = new PowerMockRule();

private BaseViewManager mViewManager;
private ReactViewGroup mView;

@Before
public void setUp() {
mViewManager = new ReactViewManager();
mView = new ReactViewGroup(RuntimeEnvironment.application);
PowerMockito.mockStatic(Arguments.class);
PowerMockito.when(Arguments.createMap())
.thenAnswer(
new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return new JavaOnlyMap();
}
});
}

@Test
Expand All @@ -44,4 +67,13 @@ public void testAccessibilityRoleTurkish() {
mViewManager.setAccessibilityRole(mView, "image");
assertThat(mView.getTag(R.id.accessibility_role)).isEqualTo(AccessibilityRole.IMAGE);
}

@Test
public void testAccessibilityStateSelected() {
WritableMap accessibilityState = Arguments.createMap();
accessibilityState.putBoolean("selected", true);
mViewManager.setViewState(mView, accessibilityState);
assertThat(mView.getTag(R.id.accessibility_state)).isEqualTo(accessibilityState);
assertThat(mView.isSelected()).isEqualTo(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
const React = require('react');
const {
AccessibilityInfo,
TextInput,
Button,
Image,
Text,
Expand All @@ -31,12 +32,32 @@ const mixedCheckboxImageSource = require('./mixed.png');
const {createRef} = require('react');

const styles = StyleSheet.create({
default: {
borderWidth: StyleSheet.hairlineWidth,
borderColor: '#0f0f0f',
flex: 1,
fontSize: 13,
padding: 4,
},
touchable: {
backgroundColor: 'blue',
borderColor: 'red',
borderWidth: 1,
borderRadius: 10,
padding: 10,
borderStyle: 'solid',
},
image: {
width: 20,
height: 20,
resizeMode: 'contain',
marginRight: 10,
},
containerAlignCenter: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
},
});

class AccessibilityExample extends React.Component {
Expand Down Expand Up @@ -230,37 +251,53 @@ class SelectionExample extends React.Component {
};

render() {
const {isSelected, isEnabled} = this.state;
let accessibilityHint = 'click me to select';
if (this.state.isSelected) {
if (isSelected) {
accessibilityHint = 'click me to unselect';
}
if (!this.state.isEnabled) {
if (!isEnabled) {
accessibilityHint = 'use the button on the right to enable selection';
}
let buttonTitle = this.state.isEnabled
? 'Disable selection'
: 'Enable selection';

let buttonTitle = isEnabled ? 'Disable selection' : 'Enable selection';
const touchableHint = ` (touching the TouchableOpacity will ${
isSelected ? 'disable' : 'enable'
} accessibilityState.selected)`;
return (
<View style={{flex: 1, flexDirection: 'row'}}>
<View style={styles.containerAlignCenter}>
<TouchableOpacity
ref={this.selectableElement}
accessible={true}
onPress={() => {
if (this.state.isEnabled) {
if (isEnabled) {
this.setState({
isSelected: !this.state.isSelected,
isSelected: !isSelected,
});
} else {
console.warn('selection is disabled, please enable selection.');
}
}}
accessibilityLabel="element 19"
accessibilityState={{
selected: this.state.isSelected,
disabled: !this.state.isEnabled,
selected: isSelected,
disabled: !isEnabled,
}}
style={styles.touchable}
accessibilityHint={accessibilityHint}>
<Text>Selectable element example</Text>
<Text style={{color: 'white'}}>
{`Selectable TouchableOpacity Example ${touchableHint}`}
</Text>
</TouchableOpacity>
<TextInput
accessibilityLabel="element 20"
accessibilityState={{
selected: isSelected,
}}
multiline={true}
placeholder={`TextInput Example - ${
isSelected ? 'enabled' : 'disabled'
} selection`}
/>
<Button
onPress={() => {
this.setState({
Expand Down