diff --git a/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityTest.kt index 4a340d416ca..a94b4475087 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityTest.kt @@ -6,11 +6,9 @@ import android.content.Intent import android.view.View import android.view.ViewParent import android.widget.FrameLayout -import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity import androidx.core.widget.NestedScrollView import androidx.drawerlayout.widget.DrawerLayout -import androidx.recyclerview.widget.RecyclerView import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario.launch import androidx.test.core.app.ApplicationProvider @@ -21,9 +19,7 @@ import androidx.test.espresso.UiController import androidx.test.espresso.ViewAction import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.scrollTo -import androidx.test.espresso.assertion.ViewAssertions.doesNotExist import androidx.test.espresso.assertion.ViewAssertions.matches -import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition import androidx.test.espresso.intent.Intents import androidx.test.espresso.intent.Intents.intended import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent @@ -67,6 +63,12 @@ import org.oppia.android.app.model.ScreenName import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.profile.ProfileChooserActivity import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView +import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.scrollToPosition +import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.verifyItemDisplayedOnListItem +import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.verifyItemDisplayedOnListItemDoesNotExist +import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.verifyTextInDialog +import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.verifyTextOnListItemAtPosition +import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.verifyTextViewOnListItemAtPositionDoesNotExist import org.oppia.android.app.settings.profile.ProfileListActivity import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.translation.testing.ActivityRecreatorTestModule @@ -157,6 +159,8 @@ class AdministratorControlsActivityTest { @Inject lateinit var context: Context + private val administratorControlsListRecyclerViewId: Int = R.id.administrator_controls_list + @get:Rule val activityTestRule = ActivityTestRule( AdministratorControlsActivity::class.java, @@ -214,11 +218,13 @@ class AdministratorControlsActivityTest { ) ).use { testCoroutineDispatchers.runCurrent() - verifyItemDisplayedOnAdministratorControlListItem( + verifyItemDisplayedOnListItem( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 0, targetView = R.id.general_text_view ) - verifyTextOnAdministratorListItemAtPosition( + verifyTextOnListItemAtPosition( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 0, targetViewId = R.id.edit_account_text_view, stringIdToMatch = R.string.administrator_controls_edit_account @@ -236,13 +242,15 @@ class AdministratorControlsActivityTest { ) ).use { testCoroutineDispatchers.runCurrent() - verifyItemDisplayedOnAdministratorControlListItemDoesNotExist( + verifyItemDisplayedOnListItemDoesNotExist( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 0, targetView = R.id.general_text_view ) - verifyTextViewOnAdministratorListItemAtPositionDoesNotExist( + verifyTextViewOnListItemAtPositionDoesNotExist( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 0, - targetViewId = R.id.edit_account_text_view, + targetViewId = R.id.edit_account_text_view ) } } @@ -255,11 +263,13 @@ class AdministratorControlsActivityTest { ) ).use { testCoroutineDispatchers.runCurrent() - verifyItemDisplayedOnAdministratorControlListItem( + verifyItemDisplayedOnListItem( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 1, targetView = R.id.profile_management_text_view ) - verifyTextOnAdministratorListItemAtPosition( + verifyTextOnListItemAtPosition( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 1, targetViewId = R.id.edit_profiles_text_view, stringIdToMatch = R.string.administrator_controls_edit_profiles @@ -275,7 +285,7 @@ class AdministratorControlsActivityTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 3) + scrollToPosition(position = 3, recyclerViewId = administratorControlsListRecyclerViewId) onView(withId(R.id.log_out_text_view)).perform(click()) verifyTextInDialog(textInDialogId = R.string.log_out_dialog_message) onView(withText(R.string.log_out_dialog_okay_button)).perform(click()) @@ -291,7 +301,7 @@ class AdministratorControlsActivityTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) onView(withId(R.id.app_version_text_view)).perform(click()) intended(hasComponent(AppVersionActivity::class.java.name)) } @@ -320,7 +330,7 @@ class AdministratorControlsActivityTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 3) + scrollToPosition(position = 3, recyclerViewId = administratorControlsListRecyclerViewId) onView(withId(R.id.log_out_text_view)).perform(click()) verifyTextInDialog(textInDialogId = R.string.log_out_dialog_message) verifyTextInDialog(textInDialogId = R.string.log_out_dialog_okay_button) @@ -336,9 +346,9 @@ class AdministratorControlsActivityTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 3) + scrollToPosition(position = 3, recyclerViewId = administratorControlsListRecyclerViewId) onView(isRoot()).perform(orientationLandscape()) - scrollToPosition(position = 3) + scrollToPosition(position = 3, recyclerViewId = administratorControlsListRecyclerViewId) onView(withId(R.id.log_out_text_view)).perform(click()) verifyTextInDialog(textInDialogId = R.string.log_out_dialog_message) verifyTextInDialog(textInDialogId = R.string.log_out_dialog_okay_button) @@ -354,7 +364,7 @@ class AdministratorControlsActivityTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 3) + scrollToPosition(position = 3, recyclerViewId = administratorControlsListRecyclerViewId) onView(withId(R.id.log_out_text_view)).perform(click()) onView(isRoot()).perform(orientationLandscape()) verifyTextInDialog(textInDialogId = R.string.log_out_dialog_message) @@ -371,7 +381,7 @@ class AdministratorControlsActivityTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 3) + scrollToPosition(position = 3, recyclerViewId = administratorControlsListRecyclerViewId) onView(withId(R.id.log_out_text_view)).perform(click()) verifyTextInDialog(textInDialogId = R.string.log_out_dialog_message) onView(withText(R.string.log_out_dialog_cancel_button)).perform(click()) @@ -407,7 +417,7 @@ class AdministratorControlsActivityTest { ) // Open the app version fragment - scrollToPosition(position = 3) + scrollToPosition(position = 3, recyclerViewId = administratorControlsListRecyclerViewId) onView(withId(R.id.app_version_text_view)).perform(click()) // Check that the multipane container has only one child and it is the app version fragment @@ -880,70 +890,6 @@ class AdministratorControlsActivityTest { return view.getParent() } - private fun verifyItemDisplayedOnAdministratorControlListItem( - itemPosition: Int, - targetView: Int - ) { - onView( - atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, - position = itemPosition, - targetViewId = targetView - ) - ).check(matches(isDisplayed())) - } - - private fun verifyItemDisplayedOnAdministratorControlListItemDoesNotExist( - itemPosition: Int, - targetView: Int - ) { - onView( - atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, - position = itemPosition, - targetViewId = targetView - ) - ).check(doesNotExist()) - } - - private fun verifyTextOnAdministratorListItemAtPosition( - itemPosition: Int, - targetViewId: Int, - @StringRes stringIdToMatch: Int - ) { - onView( - atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, - position = itemPosition, - targetViewId = targetViewId - ) - ).check(matches(withText(context.getString(stringIdToMatch)))) - } - - private fun verifyTextViewOnAdministratorListItemAtPositionDoesNotExist( - itemPosition: Int, - targetViewId: Int, - ) { - onView( - atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, - position = itemPosition, - targetViewId = targetViewId - ) - ).check(doesNotExist()) - } - - private fun scrollToPosition(position: Int) { - onView(withId(R.id.administrator_controls_list)) - .perform(scrollToPosition(position)) - } - - private fun verifyTextInDialog(@StringRes textInDialogId: Int) { - onView(withText(context.getString(textInDialogId))) - .inRoot(isDialog()) - .check(matches(isDisplayed())) - } - // TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them. @Singleton @Component( diff --git a/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsFragmentTest.kt index b50d9c099f2..6d7e7b9ee87 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/AdministratorControlsFragmentTest.kt @@ -6,10 +6,8 @@ import android.content.Intent import android.view.View import android.view.ViewParent import android.widget.FrameLayout -import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity import androidx.core.widget.NestedScrollView -import androidx.recyclerview.widget.RecyclerView import androidx.test.core.app.ActivityScenario.launch import androidx.test.core.app.ApplicationProvider import androidx.test.espresso.Espresso.onView @@ -17,18 +15,12 @@ import androidx.test.espresso.PerformException import androidx.test.espresso.UiController import androidx.test.espresso.ViewAction import androidx.test.espresso.action.ViewActions.click -import androidx.test.espresso.assertion.ViewAssertions.doesNotExist import androidx.test.espresso.assertion.ViewAssertions.matches -import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition import androidx.test.espresso.intent.Intents -import androidx.test.espresso.matcher.RootMatchers import androidx.test.espresso.matcher.ViewMatchers 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.withId -import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.util.HumanReadables import androidx.test.ext.junit.runners.AndroidJUnit4 import dagger.Component @@ -54,6 +46,10 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView +import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.scrollToPosition +import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.verifyItemDisplayedOnListItem +import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.verifyItemDisplayedOnListItemDoesNotExist +import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.verifyTextOnListItemAtPosition import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.testing.AdministratorControlsFragmentTestActivity import org.oppia.android.app.translation.testing.ActivityRecreatorTestModule @@ -144,6 +140,8 @@ class AdministratorControlsFragmentTest { @Inject lateinit var context: Context + private val administratorControlsListRecyclerViewId: Int = R.id.administrator_controls_list + @Before fun setUp() { TestPlatformParameterModule.forceEnableEditAccountsOptionsUi(true) @@ -172,20 +170,25 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - verifyItemDisplayedOnAdministratorControlListItem( + + verifyItemDisplayedOnListItem( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 0, targetView = R.id.general_text_view ) - verifyTextOnAdministratorListItemAtPosition( + verifyTextOnListItemAtPosition( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 0, targetViewId = R.id.edit_account_text_view, stringIdToMatch = R.string.administrator_controls_edit_account ) - verifyItemDisplayedOnAdministratorControlListItem( + verifyItemDisplayedOnListItem( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 1, targetView = R.id.profile_management_text_view ) - verifyTextOnAdministratorListItemAtPosition( + verifyTextOnListItemAtPosition( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 1, targetViewId = R.id.edit_profiles_text_view, stringIdToMatch = R.string.administrator_controls_edit_profiles @@ -201,17 +204,20 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - verifyTextOnAdministratorListItemAtPosition( + verifyTextOnListItemAtPosition( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 2, targetViewId = R.id.download_permissions_text_view, stringIdToMatch = R.string.administrator_controls_download_permissions_label ) - verifyItemDisplayedOnAdministratorControlListItem( + verifyItemDisplayedOnListItem( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 2, targetView = R.id.topic_update_on_wifi_constraint_layout ) - scrollToPosition(position = 2) - verifyItemDisplayedOnAdministratorControlListItem( + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) + verifyItemDisplayedOnListItem( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 2, targetView = R.id.auto_update_topic_constraint_layout ) @@ -227,12 +233,14 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 2) - verifyItemDoesNotExistInAdministratorControlListItem( + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) + verifyItemDisplayedOnListItemDoesNotExist( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 2, targetView = R.id.download_permissions_text_view ) - verifyItemDoesNotExistInAdministratorControlListItem( + verifyItemDisplayedOnListItemDoesNotExist( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 2, targetView = R.id.auto_update_topic_constraint_layout ) @@ -247,21 +255,25 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 3) - verifyItemDisplayedOnAdministratorControlListItem( + scrollToPosition(position = 3, recyclerViewId = administratorControlsListRecyclerViewId) + verifyItemDisplayedOnListItem( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 3, targetView = R.id.app_information_text_view ) - verifyTextOnAdministratorListItemAtPosition( + verifyTextOnListItemAtPosition( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 3, targetViewId = R.id.app_version_text_view, stringIdToMatch = R.string.administrator_controls_app_version ) - verifyItemDisplayedOnAdministratorControlListItem( + verifyItemDisplayedOnListItem( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 4, targetView = R.id.account_actions_text_view ) - verifyTextOnAdministratorListItemAtPosition( + verifyTextOnListItemAtPosition( + recyclerViewId = administratorControlsListRecyclerViewId, itemPosition = 4, targetViewId = R.id.log_out_text_view, stringIdToMatch = R.string.administrator_controls_log_out @@ -289,7 +301,7 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) checkAutoUpdateSwitchIsUnchecked() } } @@ -302,7 +314,7 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) clickUpdateOnWifiSwitch() atAdminControlsItem(position = 2, viewId = R.id.topic_update_on_wifi_constraint_layout) testCoroutineDispatchers.runCurrent() @@ -318,12 +330,12 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) clickUpdateOnWifiSwitch() atAdminControlsItem(position = 2, viewId = R.id.topic_update_on_wifi_constraint_layout) testCoroutineDispatchers.runCurrent() onView(isRoot()).perform(orientationLandscape()) - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) checkUpdateOnWifiSwitchIsChecked() } } @@ -336,13 +348,13 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) clickUpdateOnWifiSwitch() atAdminControlsItem(position = 2, viewId = R.id.topic_update_on_wifi_constraint_layout) testCoroutineDispatchers.runCurrent() onView(isRoot()).perform(orientationLandscape()) onView(isRoot()).perform(orientationPortrait()) - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) checkUpdateOnWifiSwitchIsChecked() } } @@ -355,11 +367,11 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) clickAutoUpdateTopicSwitch() testCoroutineDispatchers.runCurrent() onView(isRoot()).perform(orientationLandscape()) - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) checkAutoUpdateTopicSwitchIsChecked() } } @@ -372,12 +384,12 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) clickAutoUpdateTopicSwitch() testCoroutineDispatchers.runCurrent() onView(isRoot()).perform(orientationLandscape()) onView(isRoot()).perform(orientationPortrait()) - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) checkAutoUpdateTopicSwitchIsChecked() } } @@ -390,7 +402,7 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) clickAutoUpdateTopicContainer() testCoroutineDispatchers.runCurrent() checkAutoUpdateTopicSwitchIsChecked() @@ -405,7 +417,7 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) checkUpdateOnWifiSwitchNotClickable() } } @@ -418,7 +430,7 @@ class AdministratorControlsFragmentTest { ) ).use { testCoroutineDispatchers.runCurrent() - scrollToPosition(position = 2) + scrollToPosition(position = 2, recyclerViewId = administratorControlsListRecyclerViewId) checkAutoUpdateTopicSwitchNotClickable() } } @@ -426,7 +438,7 @@ class AdministratorControlsFragmentTest { private fun clickAutoUpdateTopicContainer() { onView( atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, + recyclerViewId = administratorControlsListRecyclerViewId, position = 2, targetViewId = R.id.auto_update_topic_constraint_layout ) @@ -436,7 +448,7 @@ class AdministratorControlsFragmentTest { private fun checkUpdateOnWifiSwitchNotClickable() { onView( atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, + recyclerViewId = administratorControlsListRecyclerViewId, position = 2, targetViewId = R.id.topic_update_on_wifi_switch ) @@ -446,7 +458,7 @@ class AdministratorControlsFragmentTest { private fun checkAutoUpdateTopicSwitchNotClickable() { onView( atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, + recyclerViewId = administratorControlsListRecyclerViewId, position = 2, targetViewId = R.id.auto_update_topic_switch ) @@ -456,7 +468,7 @@ class AdministratorControlsFragmentTest { private fun checkUpdateOnWifiSwitchNotChecked() { onView( atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, + recyclerViewId = administratorControlsListRecyclerViewId, position = 2, targetViewId = R.id.topic_update_on_wifi_switch ) @@ -466,7 +478,7 @@ class AdministratorControlsFragmentTest { private fun clickAutoUpdateTopicSwitch() { onView( atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, + recyclerViewId = administratorControlsListRecyclerViewId, position = 2, targetViewId = R.id.auto_update_topic_switch ) @@ -476,7 +488,7 @@ class AdministratorControlsFragmentTest { private fun checkAutoUpdateTopicSwitchIsChecked() { onView( atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, + recyclerViewId = administratorControlsListRecyclerViewId, position = 2, targetViewId = R.id.auto_update_topic_switch ) @@ -486,7 +498,7 @@ class AdministratorControlsFragmentTest { private fun checkAutoUpdateSwitchIsUnchecked() { onView( atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, + recyclerViewId = administratorControlsListRecyclerViewId, position = 2, targetViewId = R.id.auto_update_topic_switch ) @@ -496,7 +508,7 @@ class AdministratorControlsFragmentTest { private fun checkUpdateOnWifiSwitchIsChecked() { onView( atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, + recyclerViewId = administratorControlsListRecyclerViewId, position = 2, targetViewId = R.id.topic_update_on_wifi_switch ) @@ -510,7 +522,11 @@ class AdministratorControlsFragmentTest { } private fun atAdminControlsItem(position: Int, viewId: Int): Matcher { - return atPositionOnView(recyclerViewId = R.id.administrator_controls_list, position, viewId) + return atPositionOnView( + recyclerViewId = administratorControlsListRecyclerViewId, + position, + viewId + ) } private fun createAdministratorControlsFragmentTestActivityIntent(profileId: Int): Intent { @@ -575,60 +591,6 @@ class AdministratorControlsFragmentTest { return view.getParent() } - private fun verifyItemDisplayedOnAdministratorControlListItem( - itemPosition: Int, - targetView: Int - ) { - onView( - atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, - position = itemPosition, - targetViewId = targetView - ) - ).check(matches(isDisplayed())) - } - - private fun verifyItemDoesNotExistInAdministratorControlListItem( - itemPosition: Int, - targetView: Int - ) { - onView( - atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, - position = itemPosition, - targetViewId = targetView - ) - ).check(doesNotExist()) - } - - private fun verifyTextOnAdministratorListItemAtPosition( - itemPosition: Int, - targetViewId: Int, - @StringRes stringIdToMatch: Int - ) { - onView( - atPositionOnView( - recyclerViewId = R.id.administrator_controls_list, - position = itemPosition, - targetViewId = targetViewId - ) - ).check(matches(withText(context.getString(stringIdToMatch)))) - } - - private fun scrollToPosition(position: Int) { - onView(withId(R.id.administrator_controls_list)).perform( - scrollToPosition( - position - ) - ) - } - - private fun verifyTextInDialog(@StringRes textInDialogId: Int) { - onView(withText(context.getString(textInDialogId))) - .inRoot(RootMatchers.isDialog()) - .check(matches(isDisplayed())) - } - @Singleton @Component( modules = [ diff --git a/app/src/sharedTest/java/org/oppia/android/app/recyclerview/RecyclerViewMatcher.kt b/app/src/sharedTest/java/org/oppia/android/app/recyclerview/RecyclerViewMatcher.kt index a2ac0544c37..8719f9a5090 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/recyclerview/RecyclerViewMatcher.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/recyclerview/RecyclerViewMatcher.kt @@ -2,11 +2,20 @@ package org.oppia.android.app.recyclerview import android.content.res.Resources import android.view.View +import androidx.annotation.StringRes import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView +import androidx.test.espresso.Espresso.onView import androidx.test.espresso.NoMatchingViewException import androidx.test.espresso.ViewAssertion +import androidx.test.espresso.assertion.ViewAssertions.doesNotExist +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition +import androidx.test.espresso.matcher.RootMatchers.isDialog import androidx.test.espresso.matcher.ViewMatchers.assertThat +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText import org.hamcrest.CoreMatchers.equalTo import org.hamcrest.Description import org.hamcrest.Matcher @@ -14,7 +23,9 @@ import org.hamcrest.TypeSafeMatcher // Reference Link: https://github.com/dannyroa/espresso-samples/blob/master/RecyclerView/app/src/androidTest/java/com/dannyroa/espresso_samples/recyclerview/RecyclerViewMatcher.java class RecyclerViewMatcher { + companion object { + /** * This function returns a Matcher for an item inside RecyclerView from a specified position. */ @@ -74,6 +85,114 @@ class RecyclerViewMatcher { fun hasGridColumnCount(expectedColumnCount: Int): ViewAssertion { return GridLayoutManagerColumnCountAssertion(expectedColumnCount) } + + /** + * Verifies if an item at a specified position in a RecyclerView with the given ID contains a target view that is displayed. + * + * @param recyclerViewId The resource ID of the RecyclerView. + * @param itemPosition The position of the item in the RecyclerView. + * @param targetView The resource ID of the target view within the item. + */ + fun verifyItemDisplayedOnListItem( + recyclerViewId: Int, + itemPosition: Int, + targetView: Int + ) { + onView( + atPositionOnView( + recyclerViewId = recyclerViewId, + position = itemPosition, + targetViewId = targetView + ) + ).check(matches(isDisplayed())) + } + + /** + * Verifies if an item at a specified position in a RecyclerView with the given ID does not contain a target view. + * + * @param recyclerViewId The resource ID of the RecyclerView. + * @param itemPosition The position of the item in the RecyclerView. + * @param targetView The resource ID of the target view within the item. + */ + fun verifyItemDisplayedOnListItemDoesNotExist( + recyclerViewId: Int, + itemPosition: Int, + targetView: Int + ) { + onView( + atPositionOnView( + recyclerViewId = recyclerViewId, + position = itemPosition, + targetViewId = targetView + ) + ).check(doesNotExist()) + } + + /** + * Verifies if the text of a target view within an item at a specified position in a RecyclerView with the given ID matches the provided string resource. + * + * @param recyclerViewId The resource ID of the RecyclerView. + * @param itemPosition The position of the item in the RecyclerView. + * @param targetViewId The resource ID of the target view within the item. + * @param stringIdToMatch The resource ID of the string to match against the target view's text. + */ + fun verifyTextOnListItemAtPosition( + recyclerViewId: Int, + itemPosition: Int, + targetViewId: Int, + @StringRes stringIdToMatch: Int, + ) { + onView( + atPositionOnView( + recyclerViewId = recyclerViewId, + position = itemPosition, + targetViewId = targetViewId + ) + ).check(matches(withText(stringIdToMatch))) + } + + /** + * Verifies if a target view within an item at a specified position in a RecyclerView with the given ID does not exist. + * + * @param recyclerViewId The resource ID of the RecyclerView. + * @param itemPosition The position of the item in the RecyclerView. + * @param targetViewId The resource ID of the target view within the item. + */ + fun verifyTextViewOnListItemAtPositionDoesNotExist( + recyclerViewId: Int, + itemPosition: Int, + targetViewId: Int + ) { + onView( + atPositionOnView( + recyclerViewId = recyclerViewId, + position = itemPosition, + targetViewId = targetViewId + ) + ).check(doesNotExist()) + } + + /** + * Verifies if the provided text, referenced by its String resource ID, is displayed in a dialog. + * + * @param textInDialogId The resource ID of the text to verify in the dialog. + */ + fun verifyTextInDialog(@StringRes textInDialogId: Int) { + onView(withText(textInDialogId)) + .inRoot(isDialog()) + .check(matches(isDisplayed())) + } + + /** + * Scrolls to the specified position within a RecyclerView. + * + * @param position The position to scroll to within the RecyclerView. + * @param recyclerViewId The resource ID of the RecyclerView to perform scrolling on. + */ + fun scrollToPosition(position: Int, recyclerViewId: Int) { + onView(withId(recyclerViewId)) + .perform(scrollToPosition(position)) + } } private class RecyclerViewItemCountAssertion(private val count: Int) : ViewAssertion {