diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/SessionLoadedIdlingResource.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/SessionLoadedIdlingResource.kt new file mode 100644 index 000000000..a32fe743d --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/SessionLoadedIdlingResource.kt @@ -0,0 +1,48 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +package org.mozilla.fenix.helpers + +import androidx.test.core.app.ApplicationProvider +import androidx.test.espresso.IdlingResource +import org.mozilla.fenix.FenixApplication + +/** + * An IdlingResource implementation that waits until the current session is not loading anymore. + * Only after loading has completed further actions will be performed. + */ + +class SessionLoadedIdlingResource : IdlingResource { + private var resourceCallback: IdlingResource.ResourceCallback? = null + + override fun getName(): String { + return SessionLoadedIdlingResource::class.java.simpleName + } + + override fun isIdleNow(): Boolean { + val context = ApplicationProvider.getApplicationContext() + val sessionManager = context.components.core.sessionManager + val session = sessionManager.selectedSession + + return if (session?.loading == true) { + false + } else { + if (session?.progress == 100) { + invokeCallback() + true + } else { + false + } + } + } + + private fun invokeCallback() { + if (resourceCallback != null) { + resourceCallback!!.onTransitionToIdle() + } + } + + override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback) { + this.resourceCallback = callback + } +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt index eb3fe0f0b..4cd54dcd7 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt @@ -79,7 +79,7 @@ class BrowserRobot { */ fun verifyPageContent(expectedText: String) { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) - mDevice.waitNotNull(Until.findObject(text(expectedText)), waitingTime) + mDevice.waitNotNull(Until.findObject(By.textContains(expectedText)), waitingTime) } fun verifyTabCounter(expectedText: String) { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt index 51f3a80a9..82f1be6c9 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt @@ -8,25 +8,31 @@ package org.mozilla.fenix.ui.robots import android.net.Uri import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.IdlingRegistry +import androidx.test.espresso.IdlingResource import androidx.test.espresso.action.ViewActions.pressImeActionButton import androidx.test.espresso.action.ViewActions.replaceText import androidx.test.espresso.action.ViewActions.typeText import androidx.test.espresso.assertion.ViewAssertions.matches -import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.hasDescendant -import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.matcher.ViewMatchers.withContentDescription +import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.Until +import org.hamcrest.CoreMatchers.anyOf import org.hamcrest.CoreMatchers.not import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.SessionLoadedIdlingResource import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime -import org.mozilla.fenix.helpers.click -import org.mozilla.fenix.helpers.ext.waitNotNull import org.mozilla.fenix.helpers.assertions.AwesomeBarAssertion.Companion.suggestionsAreEqualTo import org.mozilla.fenix.helpers.assertions.AwesomeBarAssertion.Companion.suggestionsAreGreaterThan +import org.mozilla.fenix.helpers.click +import org.mozilla.fenix.helpers.ext.waitNotNull /** * Implementation of Robot Pattern for the URL toolbar. @@ -43,12 +49,15 @@ class NavigationToolbarRobot { class Transition { + private lateinit var sessionLoadedIdlingResource: SessionLoadedIdlingResource val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) fun enterURLAndEnterToBrowser( url: Uri, interact: BrowserRobot.() -> Unit ): BrowserRobot.Transition { + sessionLoadedIdlingResource = SessionLoadedIdlingResource() + mDevice.waitNotNull( Until.findObject(By.res("org.mozilla.fenix.debug:id/toolbar")), waitingTime @@ -58,14 +67,28 @@ class NavigationToolbarRobot { Until.findObject(By.res("org.mozilla.fenix.debug:id/mozac_browser_toolbar_edit_url_view")), waitingTime ) + awesomeBar().perform(replaceText(url.toString()), pressImeActionButton()) + runWithIdleRes(sessionLoadedIdlingResource) { + onView( + anyOf( + ViewMatchers.withResourceName("browserLayout"), + ViewMatchers.withResourceName("onboarding_message") // Req ETP dialog + ) + ) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + } + BrowserRobot().interact() return BrowserRobot.Transition() } fun openThreeDotMenu(interact: ThreeDotMenuMainRobot.() -> Unit): ThreeDotMenuMainRobot.Transition { - mDevice.waitNotNull(Until.findObject(By.res("org.mozilla.fenix.debug:id/mozac_browser_toolbar_menu")), waitingTime) + mDevice.waitNotNull( + Until.findObject(By.res("org.mozilla.fenix.debug:id/mozac_browser_toolbar_menu")), + waitingTime + ) threeDotButton().click() ThreeDotMenuMainRobot().interact() @@ -76,10 +99,21 @@ class NavigationToolbarRobot { url: Uri, interact: BrowserRobot.() -> Unit ): BrowserRobot.Transition { + sessionLoadedIdlingResource = SessionLoadedIdlingResource() mDevice.waitNotNull(Until.findObject(By.descContains("Add tab")), waitingTime) newTab().click() awesomeBar().perform(replaceText(url.toString()), pressImeActionButton()) + runWithIdleRes(sessionLoadedIdlingResource) { + onView( + anyOf( + ViewMatchers.withResourceName("browserLayout"), + ViewMatchers.withResourceName("onboarding_message") // Req for ETP dialog + ) + ) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + } + BrowserRobot().interact() return BrowserRobot.Transition() } @@ -151,3 +185,11 @@ private fun newTab() = onView(withContentDescription("Add tab")) private fun fillLinkButton() = onView(withId(R.id.fill_link_from_clipboard)) private fun clearAddressBar() = onView(withId(R.id.mozac_browser_toolbar_clear_view)) private fun goBackButton() = mDevice.pressBack() +inline fun runWithIdleRes(ir: IdlingResource?, pendingCheck: () -> Unit) { + try { + IdlingRegistry.getInstance().register(ir) + pendingCheck() + } finally { + IdlingRegistry.getInstance().unregister(ir) + } +}