Improve accessibility to ForYou topics (#1309)

* Clear semantics.

Change-Id: I69a48798f6be8433e877c38166bd73cd776d71ac

* Merge the descendants semantics.

Change-Id: Ifbe91bb694b393e6780f93732a7d38f5ee355680

* Add string for icon description.

Change-Id: Ibf35c651aeacfbe317794ed898f0fb0e8bc1ec15

* Change icon description.

Change-Id: I9359bf8c9272b247669ae58fd79e5f79466ec0a9

* Change state of icon check logic.

Change-Id: I3e5e89fc1c469c3f3c4744d18f697f68d070996b

* Merge only text.

Change-Id: I36eefc6dd9f56f7a1f63003f0f95f6755ae16def

* Add stateDescription.

Change-Id: Id4d32e49374dbdb6e666048937e37060cbd4b454

* Add toggleableState.

Change-Id: I9f836e2463bf800786d11f9e0997a7d570ff90b0

* Set clearAndSetSemantics at Row.

Change-Id: Ic25b9ca11bbcc40c8ff24172669b07ea9b7642a9

* Set stateDescription "Following" and "Not Following".

Change-Id: Ib82ac94b05a5d373ac10787aac5241fb4f03c7b2

* Find topic by onNodeWithContentDescription.

Change-Id: I2423e3846c02169f6bf1fc30d9b4034b5f79efb3

* Find topic by onNodeWithContentDescription.

Change-Id: Iefc97fd9e52227f51f7d40f8c10cb4878cde90c0
pull/1732/head
Jaehwa Noh 2 weeks ago committed by GitHub
parent 90b992b950
commit 48544194f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -18,7 +18,8 @@ package com.google.samples.apps.nowinandroid.ui
import androidx.compose.ui.semantics.SemanticsActions.ScrollBy
import androidx.compose.ui.test.assertCountEquals
import androidx.compose.ui.test.assertIsOn
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.assertIsSelected
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText
@ -87,6 +88,8 @@ class NavigationTest {
private val forYou by composeTestRule.stringResource(FeatureForyouR.string.feature_foryou_title)
private val interests by composeTestRule.stringResource(FeatureSearchR.string.feature_search_interests)
private val sampleTopic = "Headlines"
private val sampleTopicCheckIconDescription = "Headlines checked"
private val sampleTopicAddIconDescription = "Headlines add"
private val appName by composeTestRule.stringResource(R.string.app_name)
private val saved by composeTestRule.stringResource(BookmarksR.string.feature_bookmarks_title)
private val settings by composeTestRule.stringResource(SettingsR.string.feature_settings_top_app_bar_action_icon_description)
@ -115,13 +118,20 @@ class NavigationTest {
fun navigationBar_navigateToPreviouslySelectedTab_restoresContent() {
composeTestRule.apply {
// GIVEN the user follows a topic
onNodeWithText(sampleTopic).performClick()
onNodeWithContentDescription(sampleTopic).performClick()
// WHEN the user navigates to the Interests destination
onNodeWithText(interests).performClick()
// AND the user navigates to the For You destination
onNodeWithText(forYou).performClick()
// THEN the state of the For You destination is restored
onNodeWithContentDescription(sampleTopic).assertIsOn()
onNodeWithContentDescription(
sampleTopicCheckIconDescription,
useUnmergedTree = true,
).assertIsDisplayed()
onNodeWithContentDescription(
sampleTopicAddIconDescription,
useUnmergedTree = true,
).assertIsNotDisplayed()
}
}
@ -132,11 +142,18 @@ class NavigationTest {
fun navigationBar_reselectTab_keepsState() {
composeTestRule.apply {
// GIVEN the user follows a topic
onNodeWithText(sampleTopic).performClick()
onNodeWithContentDescription(sampleTopic).performClick()
// WHEN the user taps the For You navigation bar item
onNodeWithText(forYou).performClick()
// THEN the state of the For You destination is restored
onNodeWithContentDescription(sampleTopic).assertIsOn()
onNodeWithContentDescription(
sampleTopicCheckIconDescription,
useUnmergedTree = true,
).assertIsDisplayed()
onNodeWithContentDescription(
sampleTopicAddIconDescription,
useUnmergedTree = true,
).assertIsNotDisplayed()
}
}

@ -128,7 +128,7 @@ class ForYouScreenTest {
testData.forEach { testTopic ->
composeTestRule
.onNodeWithText(testTopic.topic.name)
.onNodeWithContentDescription(testTopic.topic.name)
.assertExists()
.assertHasClickAction()
}
@ -175,7 +175,7 @@ class ForYouScreenTest {
followableTopicTestData.forEach { testTopic ->
composeTestRule
.onNodeWithText(testTopic.topic.name)
.onNodeWithContentDescription(testTopic.topic.name)
.assertExists()
.assertHasClickAction()
}

@ -75,6 +75,13 @@ import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.semantics.toggleableState
import androidx.compose.ui.state.ToggleableState.Off
import androidx.compose.ui.state.ToggleableState.On
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
@ -268,23 +275,30 @@ private fun LazyStaggeredGridScope.onboarding(
is OnboardingUiState.Shown -> {
item(span = StaggeredGridItemSpan.FullLine, contentType = "onboarding") {
Column(modifier = interestsItemModifier) {
Text(
text = stringResource(R.string.feature_foryou_onboarding_guidance_title),
textAlign = TextAlign.Center,
Column(
modifier = interestsItemModifier,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(top = 24.dp),
style = MaterialTheme.typography.titleMedium,
)
Text(
text = stringResource(R.string.feature_foryou_onboarding_guidance_subtitle),
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp, start = 24.dp, end = 24.dp),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyMedium,
)
.semantics(mergeDescendants = true) { },
) {
Text(
text = stringResource(R.string.feature_foryou_onboarding_guidance_title),
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.padding(top = 24.dp),
style = MaterialTheme.typography.titleMedium,
)
Text(
text = stringResource(R.string.feature_foryou_onboarding_guidance_subtitle),
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp, start = 24.dp, end = 24.dp),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyMedium,
)
}
TopicSelection(
onboardingUiState,
onTopicCheckedChanged,
@ -384,7 +398,21 @@ private fun SingleTopicButton(
Surface(
modifier = Modifier
.width(312.dp)
.heightIn(min = 56.dp),
.heightIn(min = 56.dp)
.semantics(mergeDescendants = true) {
toggleableState = if (isSelected) {
On
} else {
Off
}
stateDescription = if (isSelected) {
"Following"
} else {
"Not Following"
}
contentDescription = name
},
shape = RoundedCornerShape(corner = CornerSize(8.dp)),
color = MaterialTheme.colorScheme.surface,
selected = isSelected,
@ -394,7 +422,9 @@ private fun SingleTopicButton(
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(start = 12.dp, end = 8.dp),
modifier = Modifier
.padding(start = 12.dp, end = 8.dp)
.clearAndSetSemantics { },
) {
TopicIcon(
imageUrl = imageUrl,
@ -413,13 +443,19 @@ private fun SingleTopicButton(
icon = {
Icon(
imageVector = NiaIcons.Add,
contentDescription = name,
contentDescription = stringResource(
id = R.string.feature_foryou_topic_icon_add,
name,
),
)
},
checkedIcon = {
Icon(
imageVector = NiaIcons.Check,
contentDescription = name,
contentDescription = stringResource(
id = R.string.feature_foryou_topic_icon_checked,
name,
),
)
},
)

@ -21,5 +21,7 @@
<string name="feature_foryou_navigate_up">Navigate up</string>
<string name="feature_foryou_onboarding_guidance_title">What are you interested in?</string>
<string name="feature_foryou_onboarding_guidance_subtitle">Updates from topics you follow will appear here. Follow some things to get started.</string>
<string name="feature_foryou_topic_icon_checked">%s checked</string>
<string name="feature_foryou_topic_icon_add">%s add</string>
</resources>

Loading…
Cancel
Save