Skip to content
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

Fix #2536: Introduce a central utility for matching item in RecyclerView #5391

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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
)
}
}
Expand All @@ -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
Expand All @@ -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())
Expand All @@ -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))
}
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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())
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<RecyclerView.ViewHolder>(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(
Expand Down
Loading
Loading