From 9750ce93cb0a6457e7f31d38fea34605d31ac7d9 Mon Sep 17 00:00:00 2001 From: Vraj Desai <43074241+vrajdesai78@users.noreply.github.com> Date: Fri, 28 Oct 2022 16:55:16 +0530 Subject: [PATCH] Fixes #3906: Incorrect output for rich text in hints and solution (#4666) ## Explanation Fixes #3906: Fixed the overall accessibility of Hints and Solution as follows: - Parse HTML to normal string for content description - Improved flow of screen reader by removing repetitive content description. - Changed content description of expand_list_icon and also improve the flow by making expand_list_icon clickable and not clickable based on talkback reader. ## Essential Checklist - [x] The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".) - [x] Any changes to [scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets) files have their rationale included in the PR explanation. - [x] The PR follows the [style guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide). - [x] The PR does not contain any unnecessary code changes from Android Studio ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)). - [x] The PR is made from a branch that's **not** called "develop" and is up-to-date with "develop". - [x] The PR is **assigned** to the appropriate reviewers ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)). ### Video for Hints https://user-images.githubusercontent.com/43074241/198126083-88b1ea29-3726-43e5-895e-de64166a6515.mp4 ### Video for Solution https://user-images.githubusercontent.com/43074241/198126121-59b56e5c-4003-4047-a6c9-4595430f3a8b.mp4 --- ...HintsAndSolutionDialogFragmentPresenter.kt | 31 +++++ .../app/hintsandsolution/HintsViewModel.kt | 14 ++- .../app/hintsandsolution/SolutionViewModel.kt | 11 ++ app/src/main/res/layout/hints_summary.xml | 10 +- app/src/main/res/layout/solution_summary.xml | 12 +- app/src/main/res/values-ar/strings.xml | 2 - app/src/main/res/values-pt-rBR/strings.xml | 3 - app/src/main/res/values-sw/strings.xml | 2 - app/src/main/res/values/strings.xml | 6 +- .../exploration/ExplorationActivityTest.kt | 117 ++++++++++++++++++ .../QuestionPlayerActivityTest.kt | 67 ++++++++++ .../player/state/StateFragmentLocalTest.kt | 71 ++++++++++- 12 files changed, 322 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragmentPresenter.kt index 493f31042c1..d0518034c59 100644 --- a/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragmentPresenter.kt @@ -20,6 +20,7 @@ import org.oppia.android.databinding.HintsAndSolutionFragmentBinding import org.oppia.android.databinding.HintsSummaryBinding import org.oppia.android.databinding.ReturnToLessonButtonItemBinding import org.oppia.android.databinding.SolutionSummaryBinding +import org.oppia.android.util.accessibility.AccessibilityService import org.oppia.android.util.gcsresource.DefaultResourceBucketName import org.oppia.android.util.parser.html.ExplorationHtmlParserEntityType import org.oppia.android.util.parser.html.HtmlParser @@ -39,6 +40,8 @@ class HintsAndSolutionDialogFragmentPresenter @Inject constructor( private val multiTypeBuilderFactory: BindableAdapter.MultiTypeBuilder.Factory ) { + @Inject + lateinit var accessibilityService: AccessibilityService private var index: Int? = null private var expandedItemsList = ArrayList() private var isHintRevealed: Boolean? = null @@ -228,11 +231,25 @@ class HintsAndSolutionDialogFragmentPresenter @Inject constructor( } } + binding.expandHintListIcon.setOnClickListener { + if (hintsViewModel.isHintRevealed.get()!!) { + expandOrCollapseItem(position) + } + } + binding.root.setOnClickListener { if (hintsViewModel.isHintRevealed.get()!!) { expandOrCollapseItem(position) } } + + if (accessibilityService.isScreenReaderEnabled()) { + binding.root.isClickable = false + binding.expandHintListIcon.isClickable = true + } else { + binding.root.isClickable = true + binding.expandHintListIcon.isClickable = false + } } private fun expandOrCollapseItem(position: Int) { @@ -289,11 +306,25 @@ class HintsAndSolutionDialogFragmentPresenter @Inject constructor( } } + binding.expandSolutionListIcon.setOnClickListener { + if (solutionViewModel.isSolutionRevealed.get()!!) { + expandOrCollapseItem(position) + } + } + binding.root.setOnClickListener { if (solutionViewModel.isSolutionRevealed.get()!!) { expandOrCollapseItem(position) } } + + if (accessibilityService.isScreenReaderEnabled()) { + binding.root.isClickable = false + binding.expandSolutionListIcon.isClickable = true + } else { + binding.root.isClickable = true + binding.expandSolutionListIcon.isClickable = false + } } private fun bindReturnToLessonViewModel( diff --git a/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsViewModel.kt b/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsViewModel.kt index 63c4ac2c6c0..b722a9f4a0b 100644 --- a/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/hintsandsolution/HintsViewModel.kt @@ -12,6 +12,7 @@ import org.oppia.android.app.translation.AppLanguageResourceHandler import org.oppia.android.domain.hintsandsolution.isHintRevealed import org.oppia.android.domain.hintsandsolution.isSolutionRevealed import org.oppia.android.domain.translation.TranslationController +import org.oppia.android.util.parser.html.CustomHtmlContentHandler import javax.inject.Inject private const val DEFAULT_HINT_AND_SOLUTION_SUMMARY = "" @@ -79,11 +80,14 @@ class HintsViewModel @Inject constructor( return itemList } - fun computeHintListDropDownIconContentDescription(): String { - return resourceHandler.getStringInLocaleWithWrapping( - R.string.show_hide_hint_list, - hintsAndSolutionSummary.get() ?: DEFAULT_HINT_AND_SOLUTION_SUMMARY - ) + fun computeHintContentDescription(): String { + return hintsAndSolutionSummary.get()?.let { + CustomHtmlContentHandler.fromHtml( + it, + imageRetriever = null, + customTagHandlers = mapOf() + ).toString() + } ?: DEFAULT_HINT_AND_SOLUTION_SUMMARY } private fun addHintToList(hintIndex: Int, hint: Hint) { diff --git a/app/src/main/java/org/oppia/android/app/hintsandsolution/SolutionViewModel.kt b/app/src/main/java/org/oppia/android/app/hintsandsolution/SolutionViewModel.kt index 84a9befdff5..82c1c38d997 100644 --- a/app/src/main/java/org/oppia/android/app/hintsandsolution/SolutionViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/hintsandsolution/SolutionViewModel.kt @@ -2,6 +2,7 @@ package org.oppia.android.app.hintsandsolution import androidx.databinding.ObservableField import androidx.lifecycle.ViewModel +import org.oppia.android.util.parser.html.CustomHtmlContentHandler /** [ViewModel] for Solution in [HintsAndSolutionDialogFragment]. */ class SolutionViewModel : HintsAndSolutionItemViewModel() { @@ -14,4 +15,14 @@ class SolutionViewModel : HintsAndSolutionItemViewModel() { val title = ObservableField("") val isSolutionRevealed = ObservableField(false) val solutionCanBeRevealed = ObservableField(false) + + fun computeSolutionContentDescription(): String { + return solutionSummary.get()?.let { + CustomHtmlContentHandler.fromHtml( + it, + imageRetriever = null, + customTagHandlers = mapOf() + ).toString() + } ?: "" + } } diff --git a/app/src/main/res/layout/hints_summary.xml b/app/src/main/res/layout/hints_summary.xml index aadbffdfecb..bfddb1539a7 100644 --- a/app/src/main/res/layout/hints_summary.xml +++ b/app/src/main/res/layout/hints_summary.xml @@ -17,7 +17,8 @@ + android:layout_height="wrap_content" + android:importantForAccessibility="no"> - + android:layout_height="wrap_content" + android:importantForAccessibility="no"> - diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 3883cb905b2..518f65a1232 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -355,8 +355,6 @@ الملاحظات عرض الحل عرض الملاحظة - عرض/إخفاء قائمة الملاحظات الخاصة ب%s - عرض/إخفاء الحل الحل الوحيد هو : سوف يتم إظهار الحل. هل أنت متأكد؟ إظهار diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 2fdac03129f..3ecdc80d40a 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -383,11 +383,8 @@ Mostrar dicas e solução Navegar para cima Dicas - Exibir Revelar Solução Revelar Dica - Mostrar/Esconder lista de dicas de %s - Mostrar/Esconder solução A única solução é : Isso revelará a solução. Tem certeza? Revelar diff --git a/app/src/main/res/values-sw/strings.xml b/app/src/main/res/values-sw/strings.xml index 4f29e0b85db..e363a4ea0a9 100644 --- a/app/src/main/res/values-sw/strings.xml +++ b/app/src/main/res/values-sw/strings.xml @@ -362,8 +362,6 @@ Vidokezo Fichua Suluhisho Fichua Kidokezo - Onyesha/Ficha orodha ya vidokezo ya %s - Onyesha/Ficha suluhisho Suluhisho pekee ni: Hii itafichua suluhisho. Una uhakika? Fichua diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8fb3f074919..e3a2f70b5ce 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -440,11 +440,11 @@ Hint %s Navigate up Hints - Show + Show solution Reveal Solution Show Hint - Show/Hide hint list of %s - Show/Hide solution + Hide Hint + Hide solution The only solution is : This will reveal the solution. Are you sure? Reveal diff --git a/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt index f5f96f666ab..485226f4e34 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt @@ -30,6 +30,7 @@ import androidx.test.espresso.matcher.RootMatchers.isDialog import androidx.test.espresso.matcher.ViewMatchers.Visibility import androidx.test.espresso.matcher.ViewMatchers.assertThat import androidx.test.espresso.matcher.ViewMatchers.isChecked +import androidx.test.espresso.matcher.ViewMatchers.isClickable import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.espresso.matcher.ViewMatchers.withContentDescription @@ -145,6 +146,7 @@ import org.oppia.android.testing.threading.TestDispatcherModule import org.oppia.android.testing.time.FakeOppiaClock import org.oppia.android.testing.time.FakeOppiaClockModule import org.oppia.android.util.accessibility.AccessibilityTestModule +import org.oppia.android.util.accessibility.FakeAccessibilityService import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule import org.oppia.android.util.gcsresource.GcsResourceModule @@ -209,6 +211,9 @@ class ExplorationActivityTest { @Inject lateinit var monitorFactory: DataProviderTestMonitor.Factory + @Inject + lateinit var fakeAccessibilityService: FakeAccessibilityService + private val internalProfileId: Int = 0 @Before @@ -1617,6 +1622,118 @@ class ExplorationActivityTest { explorationDataController.stopPlayingExploration(isCompletion = false) } + @Test + @RunOn(TestPlatform.ROBOLECTRIC) // TODO(#3858): Enable for Espresso. + fun testExpActivity_showHint_hasCorrectContentDescription() { + launch( + createExplorationActivityIntent( + internalProfileId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2, + shouldSavePartialProgress = false + ) + ).use { + explorationDataController.startPlayingNewExploration( + internalProfileId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2 + ) + testCoroutineDispatchers.runCurrent() + clickContinueButton() + // Submit two incorrect answers. + submitFractionAnswer(answerText = "1/3") + submitFractionAnswer(answerText = "1/4") + + // Reveal the hint. + openHintsAndSolutionsDialog() + pressRevealHintButton(hintPosition = 0) + + // Ensure the hint description is correct and doesn't contain any HTML. + onView(withId(R.id.hints_and_solution_summary)) + .check( + matches( + withContentDescription( + "Remember that two halves, when added together," + + " make one whole.\n\n" + ) + ) + ) + } + explorationDataController.stopPlayingExploration(isCompletion = false) + } + + @Test + @RunOn(TestPlatform.ROBOLECTRIC) // TODO(#3858): Enable for Espresso. + fun testExpActivity_showHint_checkExpandListIconWithScreenReader_isClickable() { + launch( + createExplorationActivityIntent( + internalProfileId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2, + shouldSavePartialProgress = false + ) + ).use { + explorationDataController.startPlayingNewExploration( + internalProfileId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2 + ) + testCoroutineDispatchers.runCurrent() + clickContinueButton() + // Enable screen reader. + fakeAccessibilityService.setScreenReaderEnabled(true) + // Submit two incorrect answers. + submitFractionAnswer(answerText = "1/3") + submitFractionAnswer(answerText = "1/4") + + // Reveal the hint. + openHintsAndSolutionsDialog() + pressRevealHintButton(hintPosition = 0) + // Check whether expand list icon is clickable or not. + onView(withId(R.id.expand_hint_list_icon)).check(matches(isClickable())) + } + explorationDataController.stopPlayingExploration(isCompletion = false) + } + + @Test + @RunOn(TestPlatform.ROBOLECTRIC) // TODO(#3858): Enable for Espresso. + fun testExpActivity_showHint_checkExpandListIconWithoutScreenReader_isNotClickable() { + launch( + createExplorationActivityIntent( + internalProfileId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2, + shouldSavePartialProgress = false + ) + ).use { + explorationDataController.startPlayingNewExploration( + internalProfileId, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2 + ) + testCoroutineDispatchers.runCurrent() + clickContinueButton() + // Disable screen reader. + fakeAccessibilityService.setScreenReaderEnabled(false) + // Submit two incorrect answers. + submitFractionAnswer(answerText = "1/3") + submitFractionAnswer(answerText = "1/4") + + // Reveal the hint. + openHintsAndSolutionsDialog() + pressRevealHintButton(hintPosition = 0) + // Check whether expand list icon is clickable or not. + onView(withId(R.id.expand_hint_list_icon)).check(matches(not(isClickable()))) + } + explorationDataController.stopPlayingExploration(isCompletion = false) + } + // TODO(#3858): Enable for Espresso. @Test @RunOn(TestPlatform.ROBOLECTRIC, buildEnvironments = [BuildEnvironment.BAZEL]) diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityTest.kt index 7f57ce460ce..fcb1989f505 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityTest.kt @@ -20,9 +20,11 @@ import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.contrib.RecyclerViewActions.scrollToHolder import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition import androidx.test.espresso.matcher.RootMatchers.isDialog +import androidx.test.espresso.matcher.ViewMatchers.isClickable import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isRoot +import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -39,6 +41,7 @@ import kotlinx.coroutines.CoroutineDispatcher import org.hamcrest.BaseMatcher import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString +import org.hamcrest.CoreMatchers.not import org.hamcrest.Description import org.hamcrest.Matcher import org.hamcrest.TypeSafeMatcher @@ -133,6 +136,7 @@ import org.oppia.android.testing.threading.TestCoroutineDispatchers import org.oppia.android.testing.threading.TestDispatcherModule import org.oppia.android.testing.time.FakeOppiaClockModule import org.oppia.android.util.accessibility.AccessibilityTestModule +import org.oppia.android.util.accessibility.FakeAccessibilityService import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule import org.oppia.android.util.gcsresource.GcsResourceModule @@ -199,6 +203,9 @@ class QuestionPlayerActivityTest { @Inject lateinit var monitorFactory: DataProviderTestMonitor.Factory + @Inject + lateinit var fakeAccessibilityService: FakeAccessibilityService + private val profileId = ProfileId.newBuilder().apply { internalId = 1 }.build() @Before @@ -429,6 +436,66 @@ class QuestionPlayerActivityTest { } } + @Test + @RunOn(TestPlatform.ROBOLECTRIC) // TODO(#3858): Enable for Espresso. + fun testQuestionPlayer_showHint_hasCorrectContentDescription() { + updateContentLanguage(profileId, OppiaLanguage.ENGLISH) + launchForSkillList(SKILL_ID_LIST).use { + // Submit two incorrect answers. + selectMultipleChoiceOption(optionPosition = 3) + selectMultipleChoiceOption(optionPosition = 3) + + // Reveal the hint. + openHintsAndSolutionsDialog() + pressRevealHintButton(hintPosition = 0) + + // Ensure the hint description is correct and doesn't contain any HTML. + onView(withId(R.id.hints_and_solution_summary)) + .check( + matches( + withContentDescription( + "To write a fraction, you need to know its denominator, which is the total " + + "number of pieces in the whole. All of these pieces should be the same size.\n\n" + ) + ) + ) + } + } + + @Test + @RunOn(TestPlatform.ROBOLECTRIC) // TODO(#3858): Enable for Espresso. + fun testQuestionPlayer_showHint_checkExpandListIconWithScreenReader_isClickable() { + launchForSkillList(SKILL_ID_LIST).use { + // Enable screen reader. + fakeAccessibilityService.setScreenReaderEnabled(true) + // Submit two incorrect answers. + selectMultipleChoiceOption(optionPosition = 3) + selectMultipleChoiceOption(optionPosition = 3) + // Reveal the hint. + openHintsAndSolutionsDialog() + pressRevealHintButton(hintPosition = 0) + // Check whether expand list icon is clickable or not. + onView(withId(R.id.expand_hint_list_icon)).check(matches(isClickable())) + } + } + + @Test + @RunOn(TestPlatform.ROBOLECTRIC) // TODO(#3858): Enable for Espresso. + fun testQuestionPlayer_showHint_checkExpandListIconWithoutScreenReader_isNotClickable() { + launchForSkillList(SKILL_ID_LIST).use { + // Disable screen reader. + fakeAccessibilityService.setScreenReaderEnabled(false) + // Submit two incorrect answers. + selectMultipleChoiceOption(optionPosition = 3) + selectMultipleChoiceOption(optionPosition = 3) + // Reveal the hint. + openHintsAndSolutionsDialog() + pressRevealHintButton(hintPosition = 0) + // Check whether expand list icon is clickable or not. + onView(withId(R.id.expand_hint_list_icon)).check(matches(not(isClickable()))) + } + } + // TODO(#3858): Enable for Espresso. @Test @RunOn(TestPlatform.ROBOLECTRIC, buildEnvironments = [BuildEnvironment.BAZEL]) diff --git a/app/src/test/java/org/oppia/android/app/player/state/StateFragmentLocalTest.kt b/app/src/test/java/org/oppia/android/app/player/state/StateFragmentLocalTest.kt index 3dd28fe6c8f..40c10395201 100644 --- a/app/src/test/java/org/oppia/android/app/player/state/StateFragmentLocalTest.kt +++ b/app/src/test/java/org/oppia/android/app/player/state/StateFragmentLocalTest.kt @@ -22,6 +22,7 @@ import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.contrib.RecyclerViewActions.scrollToHolder import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition import androidx.test.espresso.matcher.RootMatchers.isDialog +import androidx.test.espresso.matcher.ViewMatchers.isClickable import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isRoot @@ -210,6 +211,9 @@ class StateFragmentLocalTest { @Inject lateinit var monitorFactory: DataProviderTestMonitor.Factory + @Inject + lateinit var fakeAccessibilityService: FakeAccessibilityService + private val profileId = ProfileId.newBuilder().apply { internalId = 1 }.build() private val solutionIndex: Int = 4 @@ -1109,6 +1113,71 @@ class StateFragmentLocalTest { } } + @Test + fun testStateFragment_showSolution_hasCorrectContentDescription() { + launchForExploration(FRACTIONS_EXPLORATION_ID_1).use { scenario -> + startPlayingExploration() + playThroughFractionsState1() + produceAndViewFourHintsInFractionState2() + + submitWrongAnswerToFractionsState2() + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) + + openHintsAndSolutionsDialog() + showRevealSolutionDialog() + clickConfirmRevealSolutionButton(scenario) + + onView(withId(R.id.solution_summary)).check( + matches( + withContentDescription( + "Start by dividing the cake into equal parts:\n\nThree of " + + "the four equal parts are red. So, the answer is 3/4.\n\n" + ) + ) + ) + } + } + + @Test + fun testStateFragment_showSolution_checkExpandListIconWithScreenReader_isClickable() { + launchForExploration(FRACTIONS_EXPLORATION_ID_1).use { scenario -> + startPlayingExploration() + playThroughFractionsState1() + produceAndViewFourHintsInFractionState2() + + submitWrongAnswerToFractionsState2() + // Enable screen reader. + fakeAccessibilityService.setScreenReaderEnabled(true) + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) + + openHintsAndSolutionsDialog() + showRevealSolutionDialog() + clickConfirmRevealSolutionButton(scenario) + // Check whether expand list icon is clickable or not. + onView(withId(R.id.expand_solution_list_icon)).check(matches(isClickable())) + } + } + + @Test + fun testStateFragment_showSolution_checkExpandListIconWithoutScreenReader_isNotClickable() { + launchForExploration(FRACTIONS_EXPLORATION_ID_1).use { scenario -> + startPlayingExploration() + playThroughFractionsState1() + produceAndViewFourHintsInFractionState2() + + submitWrongAnswerToFractionsState2() + // Enable screen reader. + fakeAccessibilityService.setScreenReaderEnabled(false) + testCoroutineDispatchers.advanceTimeBy(TimeUnit.SECONDS.toMillis(10)) + + openHintsAndSolutionsDialog() + showRevealSolutionDialog() + clickConfirmRevealSolutionButton(scenario) + // Check whether expand list icon is clickable or not. + onView(withId(R.id.expand_solution_list_icon)).check(matches(not(isClickable()))) + } + } + @Test fun testStateFragment_nextState_viewRevealSolutionDialog_clickCancel_solutionIsNotRevealed() { launchForExploration(FRACTIONS_EXPLORATION_ID_1).use { scenario -> @@ -1143,7 +1212,7 @@ class StateFragmentLocalTest { showRevealSolutionDialog() clickCancelInRevealSolutionDialog(scenario) - onView(withText("Show")) + onView(withText("SHOW SOLUTION")) .inRoot(isDialog()) .check(matches(isDisplayed())) }