Updated the method to verify system notifications and added new tests for media notifications (#9330)
parent
cee34893ed
commit
5f68d6cb29
|
@ -0,0 +1,26 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Audio_Test_Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<p id="testContent">Page content: audio player</p>
|
||||
<div class="audioPlayer">
|
||||
<audio id="audioSample" controls loop>
|
||||
<source src="../resources/audioSample.mp3">
|
||||
</audio>
|
||||
</div>
|
||||
<div class="playbackState">
|
||||
</div>
|
||||
<script>
|
||||
const audio = document.querySelector('audio');
|
||||
|
||||
audio.addEventListener('playing', (event) => {
|
||||
document.querySelector('.playbackState').innerText="Media file is playing"
|
||||
});
|
||||
|
||||
audio.addEventListener('pause', (event) => {
|
||||
document.querySelector('.playbackState').innerText="Media file is paused"
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,26 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Video_Test_Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<p id="testContent">Page content: video player</p>
|
||||
<div id="video-container">
|
||||
<video id="videoSample" width="320" height="240" controls loop>
|
||||
<source src="../resources/videoSample.webm">
|
||||
</video>
|
||||
</div>
|
||||
<div class="playbackState">
|
||||
</div>
|
||||
<script>
|
||||
const video = document.querySelector('video');
|
||||
|
||||
video.addEventListener('playing', (event) => {
|
||||
document.querySelector('.playbackState').innerText="Media file is playing";
|
||||
});
|
||||
|
||||
video.addEventListener('pause', (event) => {
|
||||
document.querySelector('.playbackState').innerHTML="Media file is paused";
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
Binary file not shown.
|
@ -18,7 +18,7 @@ object TestAssetHelper {
|
|||
val waitingTime: Long = TimeUnit.SECONDS.toMillis(15)
|
||||
val waitingTimeShort: Long = TimeUnit.SECONDS.toMillis(1)
|
||||
|
||||
data class TestAsset(val url: Uri, val content: String)
|
||||
data class TestAsset(val url: Uri, val content: String, val title: String)
|
||||
|
||||
/**
|
||||
* Hosts 3 simple websites, found at androidTest/assets/pages/generic[1|2|3].html
|
||||
|
@ -33,7 +33,8 @@ object TestAssetHelper {
|
|||
return (1..4).map {
|
||||
TestAsset(
|
||||
server.url("pages/generic$it.html").toString().toUri()!!,
|
||||
"Page content: $it"
|
||||
"Page content: $it",
|
||||
""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -41,52 +42,70 @@ object TestAssetHelper {
|
|||
fun getGenericAsset(server: MockWebServer, pageNum: Int): TestAsset {
|
||||
val url = server.url("pages/generic$pageNum.html").toString().toUri()!!
|
||||
val content = "Page content: $pageNum"
|
||||
val title = "Test_Page_$pageNum"
|
||||
|
||||
return TestAsset(url, content)
|
||||
return TestAsset(url, content, title)
|
||||
}
|
||||
|
||||
fun getLoremIpsumAsset(server: MockWebServer): TestAsset {
|
||||
val url = server.url("pages/lorem-ipsum.html").toString().toUri()!!
|
||||
val content = "Page content: lorem ipsum"
|
||||
return TestAsset(url, content)
|
||||
|
||||
return TestAsset(url, content, "")
|
||||
}
|
||||
|
||||
fun getRefreshAsset(server: MockWebServer): TestAsset {
|
||||
val url = server.url("pages/refresh.html").toString().toUri()!!
|
||||
val content = "Page content: refresh"
|
||||
|
||||
return TestAsset(url, content)
|
||||
return TestAsset(url, content, "")
|
||||
}
|
||||
|
||||
fun getUUIDPage(server: MockWebServer): TestAsset {
|
||||
val url = server.url("pages/basic_nav_uuid.html").toString().toUri()!!
|
||||
val content = "Page content: basic_nav_uuid"
|
||||
|
||||
return TestAsset(url, content)
|
||||
return TestAsset(url, content, "")
|
||||
}
|
||||
|
||||
fun getDownloadAsset(server: MockWebServer): TestAsset {
|
||||
val url = server.url("pages/download.html").toString().toUri()!!
|
||||
val content = "Page content: Globe.svg"
|
||||
|
||||
return TestAsset(url, content)
|
||||
return TestAsset(url, content, "")
|
||||
}
|
||||
|
||||
fun getEnhancedTrackingProtectionAsset(server: MockWebServer): TestAsset {
|
||||
val url = server.url("pages/etp.html").toString().toUri()!!
|
||||
|
||||
return TestAsset(url, "")
|
||||
return TestAsset(url, "", "")
|
||||
}
|
||||
|
||||
fun getImageAsset(server: MockWebServer): TestAsset {
|
||||
val url = server.url("resources/rabbit.jpg").toString().toUri()!!
|
||||
|
||||
return TestAsset(url, "")
|
||||
return TestAsset(url, "", "")
|
||||
}
|
||||
|
||||
fun getSaveLoginAsset(server: MockWebServer): TestAsset {
|
||||
val url = server.url("pages/password.html").toString().toUri()!!
|
||||
|
||||
return TestAsset(url, "")
|
||||
return TestAsset(url, "", "")
|
||||
}
|
||||
|
||||
fun getAudioPageAsset(server: MockWebServer): TestAsset {
|
||||
val url = server.url("pages/audioMediaPage.html").toString().toUri()!!
|
||||
val title = "Audio_Test_Page"
|
||||
val content = "Page content: audio player"
|
||||
|
||||
return TestAsset(url, content, title)
|
||||
}
|
||||
|
||||
fun getVideoPageAsset(server: MockWebServer): TestAsset {
|
||||
val url = server.url("pages/videoMediaPage.html").toString().toUri()!!
|
||||
val title = "Video_Test_Page"
|
||||
val content = "Page content: video player"
|
||||
|
||||
return TestAsset(url, content, title)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/* 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.ui
|
||||
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
|
||||
import org.mozilla.fenix.helpers.HomeActivityTestRule
|
||||
import org.mozilla.fenix.helpers.TestAssetHelper
|
||||
import org.mozilla.fenix.ui.robots.browserScreen
|
||||
import org.mozilla.fenix.ui.robots.homeScreen
|
||||
import org.mozilla.fenix.ui.robots.mDevice
|
||||
import org.mozilla.fenix.ui.robots.navigationToolbar
|
||||
|
||||
/**
|
||||
* Tests for verifying basic functionality of media notifications:
|
||||
* - video and audio playback system notifications appear and can pause/play the media content
|
||||
* - a media notification icon is displayed on the homescreen for the tab playing media content
|
||||
* Note: this test only verifies media notifications, not media itself
|
||||
*/
|
||||
class MediaNotificationTest {
|
||||
/* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping.
|
||||
|
||||
private lateinit var mockWebServer: MockWebServer
|
||||
|
||||
@get:Rule
|
||||
val activityTestRule = HomeActivityTestRule()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
mockWebServer = MockWebServer().apply {
|
||||
setDispatcher(AndroidAssetDispatcher())
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
mockWebServer.shutdown()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun videoPlaybackSystemNotificationTest() {
|
||||
val videoTestPage = TestAssetHelper.getVideoPageAsset(mockWebServer)
|
||||
|
||||
navigationToolbar {
|
||||
}.enterURLAndEnterToBrowser(videoTestPage.url) {
|
||||
clickMediaPlayerPlayButton()
|
||||
waitForPlaybackToStart()
|
||||
}.openNotificationShade {
|
||||
verifySystemNotificationExists(videoTestPage.title)
|
||||
clickMediaSystemNotificationControlButton("Pause")
|
||||
verifyMediaSystemNotificationButtonState("Play")
|
||||
}
|
||||
|
||||
mDevice.pressBack()
|
||||
|
||||
browserScreen {
|
||||
verifyMediaIsPaused()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun audioPlaybackSystemNotificationTest() {
|
||||
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
|
||||
|
||||
navigationToolbar {
|
||||
}.enterURLAndEnterToBrowser(audioTestPage.url) {
|
||||
verifyPageContent(audioTestPage.content)
|
||||
clickMediaPlayerPlayButton()
|
||||
waitForPlaybackToStart()
|
||||
}.openNotificationShade {
|
||||
verifySystemNotificationExists(audioTestPage.title)
|
||||
clickMediaSystemNotificationControlButton("Pause")
|
||||
verifyMediaSystemNotificationButtonState("Play")
|
||||
}
|
||||
|
||||
mDevice.pressBack()
|
||||
|
||||
browserScreen {
|
||||
verifyMediaIsPaused()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun tabMediaControlButtonTest() {
|
||||
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
|
||||
|
||||
navigationToolbar {
|
||||
}.enterURLAndEnterToBrowser(audioTestPage.url) {
|
||||
verifyPageContent(audioTestPage.content)
|
||||
clickMediaPlayerPlayButton()
|
||||
waitForPlaybackToStart()
|
||||
}.openHomeScreen {
|
||||
verifyTabMediaControlButtonState("Pause")
|
||||
clickTabMediaControlButton()
|
||||
verifyTabMediaControlButtonState("Play")
|
||||
}.openTab(audioTestPage.title) {
|
||||
verifyMediaIsPaused()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mediaSystemNotificationInPrivateModeTest() {
|
||||
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
|
||||
|
||||
homeScreen { }.togglePrivateBrowsingMode()
|
||||
|
||||
navigationToolbar {
|
||||
}.enterURLAndEnterToBrowser(audioTestPage.url) {
|
||||
verifyPageContent(audioTestPage.content)
|
||||
clickMediaPlayerPlayButton()
|
||||
waitForPlaybackToStart()
|
||||
}.openNotificationShade {
|
||||
verifySystemNotificationExists("A site is playing media")
|
||||
clickMediaSystemNotificationControlButton("Pause")
|
||||
verifyMediaSystemNotificationButtonState("Play")
|
||||
}
|
||||
|
||||
mDevice.pressBack()
|
||||
|
||||
browserScreen {
|
||||
verifyMediaIsPaused()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ import org.mozilla.fenix.helpers.TestAssetHelper
|
|||
import org.mozilla.fenix.helpers.ext.waitNotNull
|
||||
import org.mozilla.fenix.ui.robots.homeScreen
|
||||
import org.mozilla.fenix.ui.robots.navigationToolbar
|
||||
import org.mozilla.fenix.ui.robots.notificationShade
|
||||
|
||||
/**
|
||||
* Tests for verifying basic functionality of tabbed browsing
|
||||
|
@ -259,6 +260,9 @@ class TabbedBrowsingTest {
|
|||
navigationToolbar {
|
||||
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
|
||||
mDevice.openNotification()
|
||||
}
|
||||
|
||||
notificationShade {
|
||||
verifyPrivateTabsNotification()
|
||||
}.clickClosePrivateTabsNotification {
|
||||
verifyPrivateSessionMessage()
|
||||
|
|
|
@ -26,6 +26,7 @@ import androidx.test.uiautomator.By.text
|
|||
import androidx.test.uiautomator.UiDevice
|
||||
import androidx.test.uiautomator.UiSelector
|
||||
import androidx.test.uiautomator.Until
|
||||
import androidx.test.uiautomator.Until.hasObject
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.hamcrest.CoreMatchers.containsString
|
||||
import org.junit.Assert.assertTrue
|
||||
|
@ -34,6 +35,7 @@ import org.mozilla.fenix.ext.components
|
|||
import org.mozilla.fenix.helpers.Constants.LongClickDuration
|
||||
import org.mozilla.fenix.helpers.TestAssetHelper
|
||||
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
|
||||
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
|
||||
import org.mozilla.fenix.helpers.click
|
||||
import org.mozilla.fenix.helpers.ext.waitNotNull
|
||||
|
||||
|
@ -57,7 +59,7 @@ class BrowserRobot {
|
|||
)
|
||||
TestAssetHelper.waitingTime
|
||||
onView(withId(R.id.mozac_browser_toolbar_url_view))
|
||||
.check(matches(withText(containsString(url.replace("http://", "")))))
|
||||
.check(matches(withText(containsString(url.replace("http://", "")))))
|
||||
}
|
||||
|
||||
fun verifyHelpUrl() {
|
||||
|
@ -145,11 +147,6 @@ class BrowserRobot {
|
|||
)
|
||||
}
|
||||
|
||||
fun verifyPrivateTabsNotification() {
|
||||
mDevice.wait(Until.hasObject(text("Close private tabs")), waitingTime)
|
||||
assertPrivateTabsNotification()
|
||||
}
|
||||
|
||||
fun clickContextOpenLinkInNewTab() {
|
||||
val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
mDevice.waitNotNull(
|
||||
|
@ -289,6 +286,36 @@ class BrowserRobot {
|
|||
mDevice.findObject(text(optionToSaveLogin)).click()
|
||||
}
|
||||
|
||||
fun clickMediaPlayerPlayButton() {
|
||||
mDevice.waitNotNull(
|
||||
hasObject(
|
||||
By
|
||||
.clazz("android.widget.Button")
|
||||
.textContains("Play")
|
||||
),
|
||||
waitingTime
|
||||
)
|
||||
mediaPlayerPlayButton().click()
|
||||
}
|
||||
|
||||
fun waitForPlaybackToStart() {
|
||||
mDevice.waitNotNull(
|
||||
hasObject(
|
||||
text("Media file is playing")
|
||||
), waitingTimeShort
|
||||
)
|
||||
}
|
||||
|
||||
fun verifyMediaIsPaused() {
|
||||
mDevice.waitNotNull(
|
||||
hasObject(
|
||||
text("Media file is paused")
|
||||
), waitingTimeShort
|
||||
)
|
||||
|
||||
mDevice.findObject(UiSelector().text("Media file is paused")).exists()
|
||||
}
|
||||
|
||||
class Transition {
|
||||
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
private fun threeDotButton() = onView(
|
||||
|
@ -329,12 +356,11 @@ class BrowserRobot {
|
|||
return HomeScreenRobot.Transition()
|
||||
}
|
||||
|
||||
fun clickClosePrivateTabsNotification(interact: HomeScreenRobot.() -> 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")
|
||||
)
|
||||
|
|
|
@ -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<RecyclerView.ViewHolder>(hasDescendant(withText(title)), ViewActions.longClick())
|
||||
actionOnItem<RecyclerView.ViewHolder>(
|
||||
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<RecyclerView.ViewHolder>(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))
|
||||
|
|
|
@ -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)
|
||||
)
|
Loading…
Reference in New Issue