diff --git a/instrumentation/src/java/org/oppia/android/instrumentation/testing/EndToEndTestHelper.kt b/instrumentation/src/java/org/oppia/android/instrumentation/testing/EndToEndTestHelper.kt index 776b59a704b..3074b255a1e 100644 --- a/instrumentation/src/java/org/oppia/android/instrumentation/testing/EndToEndTestHelper.kt +++ b/instrumentation/src/java/org/oppia/android/instrumentation/testing/EndToEndTestHelper.kt @@ -49,16 +49,32 @@ object EndToEndTestHelper { wait(Until.hasObject(By.text(text)), TRANSITION_TIMEOUT_SECONDS) } + /** Waits for the view with given content description to appear. */ + fun UiDevice.waitForDesc(text: String) { + wait(Until.hasObject(By.desc(text)), TRANSITION_TIMEOUT_SECONDS) + } + /** Return the UiObject with the given text. */ - fun UiDevice.findObjectByText(text: String): UiObject2? { + fun UiDevice.findObjectByText(text: String): UiObject2 { waitForText(text) - return findObject(By.text(text)) + return checkNotNull(findObject(By.text(text))) } /** Returns the UiObject for the given resourceId. */ - fun UiDevice.findObjectByRes(resourceId: String): UiObject2? { + fun UiDevice.findObjectByRes(resourceId: String): UiObject2 { waitForRes(resourceId) - return findObject(By.res("$OPPIA_PACKAGE:id/$resourceId")) + return checkNotNull(findObject(By.res("$OPPIA_PACKAGE:id/$resourceId"))) + } + + /** Returns the UiObject for the given resourceId. */ + fun UiObject2.findObjectByRes(resourceId: String): UiObject2 { + return checkNotNull(findObject(By.res("$OPPIA_PACKAGE:id/$resourceId"))) + } + + /** Returns the UiObject for the given content description. */ + fun UiDevice.findObjectByDesc(text: String): UiObject2 { + waitForDesc(text) + return checkNotNull(findObject(By.desc(text))) } /** Performs a scroll until the view with the give text is visible. */ diff --git a/instrumentation/src/javatests/org/oppia/android/instrumentation/player/ExplorationPlayerTest.kt b/instrumentation/src/javatests/org/oppia/android/instrumentation/player/ExplorationPlayerTest.kt index a6d16c181c0..4bf77e7610b 100644 --- a/instrumentation/src/javatests/org/oppia/android/instrumentation/player/ExplorationPlayerTest.kt +++ b/instrumentation/src/javatests/org/oppia/android/instrumentation/player/ExplorationPlayerTest.kt @@ -4,7 +4,9 @@ import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.google.common.truth.Truth.assertThat import org.junit.Before +import org.junit.Ignore import org.junit.Test +import org.oppia.android.instrumentation.testing.EndToEndTestHelper.findObjectByDesc import org.oppia.android.instrumentation.testing.EndToEndTestHelper.findObjectByRes import org.oppia.android.instrumentation.testing.EndToEndTestHelper.findObjectByText import org.oppia.android.instrumentation.testing.EndToEndTestHelper.scrollRecyclerViewTextIntoView @@ -23,22 +25,162 @@ class ExplorationPlayerTest { } @Test - fun testExploration_prototypeExploration_toolbarTitle_isDisplayedSuccessfully() { + fun testPlayExploration_prototypeExploration_playedFullyThrough_finishesSuccessfully() { navigateToPrototypeExploration() - assertThat(device.findObjectByRes("exploration_toolbar_title")).isNotNull() + + // Play through all interactions. + playContinueInteraction() + playFractionInputInteraction() + playMultipleChoiceIntearction1() + playMultipleChoiceIntearction2() + playItemSelectionInteraction() + playNumericInputInteraction() + playRatioInputInteraction() + playTextInputInteraction() + playDragAndDropInteraction() + playDragDropMergeInteraction() + playEndExplorationInteraction() + + // Assert Topic Completed. + scrollRecyclerViewTextIntoView("Chapter 1: Prototype Exploration") + val chapterCompletedTick = device.findObjectByText( + "Chapter 1: Prototype Exploration" + ).parent.findObjectByRes("chapter_completed_tick") + assertThat(chapterCompletedTick).isNotNull() + } + + // TODO(#3697): Update e2e tests when backend support is introduced. + @Test + @Ignore("Need backend connection support to test the ImageRegionSelectionInteraction") + fun testPlayExploration_imageRegionInteractionExp_playedFullyThrough_finishesSuccessfully() { + navigateToImageRegionSelectionInteraction() + + // Image Region Selection Interaction. + val imageSelectionView = device.findObjectByRes("interaction_container_frame_layout") + device.waitForRes("image_click_interaction_image_view") + // TODO(#3712): Use content description to fetch the image region. + imageSelectionView.children.get(2).click() + device.findObjectByText("SUBMIT").click() + device.findObjectByText("CONTINUE").click() + + // End Exploration. + playEndExplorationInteraction() + + // Assert Topic Completed. + scrollRecyclerViewTextIntoView("Chapter 2: Image Region Selection Exploration") + val chapterCompletedTick = device.findObjectByText( + "Chapter 2: Image Region Selection Exploration" + ).parent.findObjectByRes("chapter_completed_tick") + assertThat(chapterCompletedTick).isNotNull() } /** Navigates and opens the Prototype Exploration using the admin profile. */ private fun navigateToPrototypeExploration() { - device.findObjectByRes("skip_text_view")?.click() - device.findObjectByRes("get_started_button")?.click() + device.findObjectByRes("skip_text_view").click() + device.findObjectByRes("get_started_button").click() + device.waitForRes("profile_select_text") + device.findObjectByText("Admin").click() + scrollRecyclerViewTextIntoView("First Test Topic") + device.findObjectByText("First Test Topic").click() + device.findObjectByText("LESSONS").click() + device.findObjectByText("First Story").click() + scrollRecyclerViewTextIntoView("Chapter 1: Prototype Exploration") + device.findObjectByText("Chapter 1: Prototype Exploration").click() + } + + private fun completePrototypeExploration() { + playContinueInteraction() + playFractionInputInteraction() + playMultipleChoiceIntearction1() + playMultipleChoiceIntearction2() + playItemSelectionInteraction() + playNumericInputInteraction() + playRatioInputInteraction() + playTextInputInteraction() + playDragAndDropInteraction() + playDragDropMergeInteraction() + playEndExplorationInteraction() + } + + private fun playContinueInteraction() { + device.findObjectByText("CONTINUE").click() + } + + private fun playFractionInputInteraction() { + device.findObjectByRes("fraction_input_interaction_view").text = "1/2" + device.findObjectByText("SUBMIT").click() + playContinueInteraction() + } + + private fun playMultipleChoiceIntearction1() { + device.findObjectByText("Eagle").click() + playContinueInteraction() + } + + private fun playMultipleChoiceIntearction2() { + device.findObjectByText("Green").click() + playContinueInteraction() + } + + private fun playItemSelectionInteraction() { + device.findObjectByText("Red").click() + device.findObjectByText("Green").click() + device.findObjectByText("Blue").click() + device.findObjectByText("SUBMIT").click() + playContinueInteraction() + } + + private fun playNumericInputInteraction() { + device.findObjectByRes("numeric_input_interaction_view").text = "121" + device.findObjectByText("SUBMIT").click() + playContinueInteraction() + } + + private fun playRatioInputInteraction() { + device.findObjectByRes("ratio_input_interaction_view").text = "4:5" + device.findObjectByText("SUBMIT").click() + playContinueInteraction() + } + + private fun playTextInputInteraction() { + device.findObjectByRes("text_input_interaction_view").text = "Finnish" + device.findObjectByText("SUBMIT").click() + playContinueInteraction() + } + + private fun playDragAndDropInteraction() { + device.findObjectByDesc("Move item down to 2").click() + device.findObjectByDesc("Move item down to 3").click() + device.findObjectByDesc("Move item down to 4").click() + device.findObjectByText("SUBMIT").click() + playContinueInteraction() + } + + private fun playDragDropMergeInteraction() { + device.findObjectByDesc("Link to item 2").click() + device.findObjectByDesc("Move item down to 3").click() + device.findObjectByText("SUBMIT").click() + playContinueInteraction() + } + + private fun playEndExplorationInteraction() { + device.findObjectByText("RETURN TO TOPIC").click() + } + + /** Navigates and opens the Image Region Selection Exploration using the admin profile. */ + private fun navigateToImageRegionSelectionInteraction() { + device.findObjectByRes("skip_text_view").click() + device.findObjectByRes("get_started_button").click() device.waitForRes("profile_select_text") - device.findObjectByText("Admin")?.click() + device.findObjectByText("Admin").click() scrollRecyclerViewTextIntoView("First Test Topic") - device.findObjectByText("First Test Topic")?.click() - device.findObjectByText("LESSONS")?.click() - device.findObjectByText("First Story")?.click() + device.findObjectByText("First Test Topic").click() + device.findObjectByText("LESSONS").click() + device.findObjectByText("First Story").click() scrollRecyclerViewTextIntoView("Chapter 1: Prototype Exploration") - device.findObjectByText("Chapter 1: Prototype Exploration")?.click() + device.findObjectByText("Chapter 1: Prototype Exploration").click() + completePrototypeExploration() + scrollRecyclerViewTextIntoView("Chapter 2: Image Region Selection Exploration") + device.findObjectByText("Chapter 2: Image Region Selection Exploration").click() } }