From 5f68d6cb29da9357e6621cefe2af336f9b94e110 Mon Sep 17 00:00:00 2001 From: Oana Horvath Date: Tue, 31 Mar 2020 21:11:41 +0300 Subject: [PATCH] Updated the method to verify system notifications and added new tests for media notifications (#9330) --- -e | 0 .../assets/pages/audioMediaPage.html | 26 ++++ .../assets/pages/videoMediaPage.html | 26 ++++ .../assets/resources/audioSample.mp3 | Bin 0 -> 5517 bytes .../assets/resources/videoSample.webm | Bin 0 -> 35416 bytes .../mozilla/fenix/helpers/TestAssetHelper.kt | 39 ++++-- .../mozilla/fenix/ui/MediaNotificationTest.kt | 131 ++++++++++++++++++ .../mozilla/fenix/ui/TabbedBrowsingTest.kt | 4 + .../mozilla/fenix/ui/robots/BrowserRobot.kt | 61 +++++--- .../fenix/ui/robots/HomeScreenRobot.kt | 99 +++++++++---- .../fenix/ui/robots/NotificationRobot.kt | 83 +++++++++++ 11 files changed, 413 insertions(+), 56 deletions(-) create mode 100644 -e create mode 100644 app/src/androidTest/assets/pages/audioMediaPage.html create mode 100644 app/src/androidTest/assets/pages/videoMediaPage.html create mode 100644 app/src/androidTest/assets/resources/audioSample.mp3 create mode 100644 app/src/androidTest/assets/resources/videoSample.webm create mode 100644 app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt create mode 100644 app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt diff --git a/-e b/-e new file mode 100644 index 000000000..e69de29bb diff --git a/app/src/androidTest/assets/pages/audioMediaPage.html b/app/src/androidTest/assets/pages/audioMediaPage.html new file mode 100644 index 000000000..1a8720a85 --- /dev/null +++ b/app/src/androidTest/assets/pages/audioMediaPage.html @@ -0,0 +1,26 @@ + + + Audio_Test_Page + + +

Page content: audio player

+
+ +
+
+
+ + + \ No newline at end of file diff --git a/app/src/androidTest/assets/pages/videoMediaPage.html b/app/src/androidTest/assets/pages/videoMediaPage.html new file mode 100644 index 000000000..32baa8d78 --- /dev/null +++ b/app/src/androidTest/assets/pages/videoMediaPage.html @@ -0,0 +1,26 @@ + + + Video_Test_Page + + +

Page content: video player

+
+ +
+
+
+ + + \ No newline at end of file diff --git a/app/src/androidTest/assets/resources/audioSample.mp3 b/app/src/androidTest/assets/resources/audioSample.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..eb0420a48b13bce83be42f38a13072833a59c846 GIT binary patch literal 5517 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 S`w1@4m9y*T-0zX)|NTFVz3&D9 literal 0 HcmV?d00001 diff --git a/app/src/androidTest/assets/resources/videoSample.webm b/app/src/androidTest/assets/resources/videoSample.webm new file mode 100644 index 0000000000000000000000000000000000000000..f9afbdde3ea7e945c9a7acdec47ee40c2efcb505 GIT binary patch literal 35416 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 Unit): HomeScreenRobot.Transition { - mDevice.wait(Until.hasObject(text("Close private tabs")), waitingTime) - closePrivateTabsNotification().clickAndWaitForNewWindow(waitingTime) + fun openNotificationShade(interact: NotificationRobot.() -> Unit): NotificationRobot.Transition { + mDevice.openNotification() - HomeScreenRobot().interact() - return HomeScreenRobot.Transition() + NotificationRobot().interact() + return NotificationRobot.Transition() } } } @@ -355,10 +381,9 @@ fun navURLBar() = onView(withId(R.id.mozac_browser_toolbar_url_view)) private fun tabsCounter() = onView(withId(R.id.mozac_browser_toolbar_browser_actions)) -private fun closePrivateTabsNotification() = - mDevice.findObject(UiSelector().text("Close private tabs")) - -private fun assertPrivateTabsNotification() { - mDevice.findObject(UiSelector().text("Firefox Preview (Private)")).exists() - mDevice.findObject(UiSelector().text("Close private tabs")).exists() -} +private fun mediaPlayerPlayButton() = + mDevice.findObject( + By + .clazz("android.widget.Button") + .textContains("Play") + ) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt index d23e68e0a..b87c4e3cb 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt @@ -6,8 +6,8 @@ package org.mozilla.fenix.ui.robots -import androidx.recyclerview.widget.RecyclerView import android.graphics.Bitmap +import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions import androidx.test.espresso.action.ViewActions.click @@ -16,30 +16,32 @@ import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.contrib.RecyclerViewActions import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItem import androidx.test.espresso.matcher.ViewMatchers -import androidx.test.espresso.matcher.ViewMatchers.withId -import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.matcher.ViewMatchers.Visibility import androidx.test.espresso.matcher.ViewMatchers.hasDescendant import androidx.test.espresso.matcher.ViewMatchers.isDisplayed 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.By.text import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until -import org.hamcrest.CoreMatchers.containsString +import androidx.test.uiautomator.Until.findObject import org.hamcrest.CoreMatchers.allOf +import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.not import org.mozilla.fenix.R +import org.mozilla.fenix.components.Search import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime import org.mozilla.fenix.helpers.click import org.mozilla.fenix.helpers.ext.waitNotNull -import org.mozilla.fenix.components.Search -import org.mozilla.fenix.helpers.withBitmapDrawable import org.mozilla.fenix.helpers.matchers.hasItem +import org.mozilla.fenix.helpers.withBitmapDrawable /** * Implementation of Robot Pattern for the home screen menu. @@ -168,7 +170,8 @@ class HomeScreenRobot { fun swipeToBottom() = onView(withId(R.id.homeLayout)).perform(ViewActions.swipeUp()) - fun swipeToTop() = onView(withId(R.id.sessionControlRecyclerView)).perform(ViewActions.swipeDown()) + fun swipeToTop() = + onView(withId(R.id.sessionControlRecyclerView)).perform(ViewActions.swipeDown()) fun swipeTabRight(title: String) = onView(allOf(withId(R.id.tab_title), withText(title))).perform(ViewActions.swipeRight()) @@ -185,10 +188,21 @@ class HomeScreenRobot { fun snackBarButtonClick(expectedText: String) { onView(allOf(withId(R.id.snackbar_btn), withText(expectedText))).check( - matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)) - ).perform(ViewActions.click()) + matches(withEffectiveVisibility(Visibility.VISIBLE)) + ).perform(click()) } + fun verifyTabMediaControlButtonState(action: String) { + mDevice.waitNotNull( + Until.findObject(By.res("org.mozilla.fenix.debug:id/play_pause_button")), + waitingTime + ) + + tabMediaControlButton().check(matches(withContentDescription(action))) + } + + fun clickTabMediaControlButton() = tabMediaControlButton().click() + class Transition { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) @@ -242,16 +256,25 @@ class HomeScreenRobot { return NavigationToolbarRobot.Transition() } - fun openContextMenuOnTopSitesWithTitle(title: String, interact: HomeScreenRobot.() -> Unit): Transition { + fun openContextMenuOnTopSitesWithTitle( + title: String, + interact: HomeScreenRobot.() -> Unit + ): Transition { onView(withId(R.id.top_sites_list)).perform( - actionOnItem(hasDescendant(withText(title)), ViewActions.longClick()) + actionOnItem( + hasDescendant(withText(title)), + ViewActions.longClick() + ) ) HomeScreenRobot().interact() return Transition() } - fun openTopSiteTabWithTitle(title: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + fun openTopSiteTabWithTitle( + title: String, + interact: BrowserRobot.() -> Unit + ): BrowserRobot.Transition { onView(withId(R.id.top_sites_list)).perform( actionOnItem(hasDescendant(withText(title)), click()) ) @@ -280,7 +303,20 @@ class HomeScreenRobot { fun openCommonMythsLink(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { onView(withId(R.id.private_session_common_myths)) - .perform(click()) + .perform(click()) + + BrowserRobot().interact() + return BrowserRobot.Transition() + } + + fun openTab(title: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + mDevice.waitNotNull(findObject(text(title))) + onView( + allOf( + withId(R.id.tab_title), + withText(title) + ) + ).click() BrowserRobot().interact() return BrowserRobot.Transition() @@ -355,12 +391,12 @@ private fun assertCollectionsHeaderIsNotVisible() = .check(doesNotExist()) private fun assertNoCollectionsText() = - onView( - allOf( - withText("Collect the things that matter to you. To start, save open tabs to a new collection.") - ) + onView( + allOf( + withText("Collect the things that matter to you. To start, save open tabs to a new collection.") ) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + ) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertNoCollectionsTextIsNotVisible() = onView( @@ -370,8 +406,9 @@ private fun assertNoCollectionsTextIsNotVisible() = ) .check(doesNotExist()) -private fun assertHomeComponent() = onView(ViewMatchers.withResourceName("sessionControlRecyclerView")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun assertHomeComponent() = + onView(ViewMatchers.withResourceName("sessionControlRecyclerView")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun threeDotButton() = onView(allOf(withId(R.id.menuButton))) @@ -485,10 +522,10 @@ private fun assertPrivacyNoticeButton() = // What's new elements private fun assertWhatsNewHeather() = onView(allOf(withText("See what’s new"))) - .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertWhatsNewLink() = onView(allOf(withText("Get answers here"))) - .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertStartBrowsingButton() = onView(allOf(withText("Start browsing"))) @@ -496,18 +533,20 @@ private fun assertStartBrowsingButton() = // Take a position private fun assertTakePositionheader() = onView(allOf(withText("Take a position"))) - .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -private fun assertTakePositionTopRadioButton() = onView(ViewMatchers.withResourceName("toolbar_top_radio_button")) +private fun assertTakePositionTopRadioButton() = + onView(ViewMatchers.withResourceName("toolbar_top_radio_button")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -private fun assertTakePositionBottomRadioButton() = onView(ViewMatchers.withResourceName("toolbar_bottom_radio_button")) +private fun assertTakePositionBottomRadioButton() = + onView(ViewMatchers.withResourceName("toolbar_bottom_radio_button")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) // Private mode elements private fun assertPrivateSessionHeader() = onView(allOf(withText("Private tabs"))) - .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) const val PRIVATE_SESSION_MESSAGE = "Firefox Preview clears your search and browsing history " + "when you quit the app or close all private tabs. While this doesn’t make you anonymous to websites or " + @@ -521,9 +560,11 @@ private fun assertPrivateSessionMessage(visible: Boolean) = ) private fun assertShareTabsButton(visible: Boolean) = onView(allOf(withId(R.id.share_tabs_button))) - .check( - if (visible) matches(withEffectiveVisibility(Visibility.VISIBLE)) else matches(withEffectiveVisibility(Visibility.INVISIBLE)) + .check( + if (visible) matches(withEffectiveVisibility(Visibility.VISIBLE)) else matches( + withEffectiveVisibility(Visibility.INVISIBLE) ) + ) private fun assertCloseTabsButton(title: String) = onView(allOf(withId(R.id.close_tab_button), withContentDescription("Close tab $title"))) @@ -588,3 +629,5 @@ private fun assertTopSiteContextMenuItems() { waitingTime ) } + +private fun tabMediaControlButton() = onView(withId(R.id.play_pause_button)) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt new file mode 100644 index 000000000..879bf029c --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt @@ -0,0 +1,83 @@ +package org.mozilla.fenix.ui.robots + +import android.content.res.Resources +import androidx.test.uiautomator.By.text +import androidx.test.uiautomator.UiScrollable +import androidx.test.uiautomator.UiSelector +import androidx.test.uiautomator.Until +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.ext.waitNotNull + +class NotificationRobot { + + fun verifySystemNotificationExists(notificationMessage: String) { + + fun notificationTray() = UiScrollable( + UiSelector().resourceId("com.android.systemui:id/notification_stack_scroller") + ) + + mDevice.waitNotNull( + Until.hasObject(text(notificationMessage)), + waitingTime + ) + + var notificationFound = false + while (!notificationFound) { + try { + val notification = notificationTray().getChildByText( + UiSelector().text(notificationMessage), notificationMessage, + true + ) + notification.exists() + notificationFound = true + } catch (e: Resources.NotFoundException) { + e.printStackTrace() + } + } + } + + fun verifyPrivateTabsNotification() { + mDevice.waitNotNull(Until.hasObject(text("Close private tabs")), waitingTime) + assertPrivateTabsNotification() + } + + fun clickMediaSystemNotificationControlButton(action: String) { + mediaSystemNotificationButton(action).waitForExists(waitingTime) + mediaSystemNotificationButton(action).click() + } + + fun verifyMediaSystemNotificationButtonState(action: String) { + mediaSystemNotificationButton(action).waitForExists(waitingTime) + } + + class Transition { + + fun clickClosePrivateTabsNotification(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { + NotificationRobot().verifySystemNotificationExists("Close private tabs") + closePrivateTabsNotification().clickAndWaitForNewWindow() + + HomeScreenRobot().interact() + return HomeScreenRobot.Transition() + } + } +} + +fun notificationShade(interact: NotificationRobot.() -> Unit): NotificationRobot.Transition { + NotificationRobot().interact() + return NotificationRobot.Transition() +} + +private fun assertPrivateTabsNotification() { + mDevice.findObject(UiSelector().text("Firefox Preview (Private)")).exists() + mDevice.findObject(UiSelector().text("Close private tabs")).exists() +} + +private fun closePrivateTabsNotification() = + mDevice.findObject(UiSelector().text("Close private tabs")) + +private fun mediaSystemNotificationButton(action: String) = + mDevice.findObject( + UiSelector() + .resourceId("android:id/action0") + .descriptionContains(action) + )