1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.fenix.ui
7 import androidx.compose.ui.test.junit4.AndroidComposeTestRule
8 import com.google.android.material.bottomsheet.BottomSheetBehavior
9 import mozilla.components.concept.engine.mediasession.MediaSession
12 import org.mozilla.fenix.customannotations.SmokeTest
13 import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
14 import org.mozilla.fenix.helpers.MatcherHelper
15 import org.mozilla.fenix.helpers.RetryTestRule
16 import org.mozilla.fenix.helpers.TestAssetHelper
17 import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton
18 import org.mozilla.fenix.helpers.TestHelper.closeApp
19 import org.mozilla.fenix.helpers.TestHelper.mDevice
20 import org.mozilla.fenix.helpers.TestHelper.restartApp
21 import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText
22 import org.mozilla.fenix.helpers.TestSetup
23 import org.mozilla.fenix.ui.robots.browserScreen
24 import org.mozilla.fenix.ui.robots.clickPageObject
25 import org.mozilla.fenix.ui.robots.homeScreen
26 import org.mozilla.fenix.ui.robots.navigationToolbar
27 import org.mozilla.fenix.ui.robots.notificationShade
30 * Tests for verifying basic functionality of tabbed browsing
34 * - Opening a private tab
35 * - Verifying tab list
38 * - Swipe to close tab (temporarily disabled)
40 * - Close private tabs persistent notification
41 * - Empty tab tray state
43 * - Shortcut context menu navigation
46 class ComposeTabbedBrowsingTest : TestSetup() {
49 AndroidComposeTestRule(
50 HomeActivityIntentTestRule.withDefaultSettingsOverrides(
51 skipOnboarding = true,
52 tabsTrayRewriteEnabled = true,
58 val retryTestRule = RetryTestRule(3)
60 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903599
62 fun closeAllTabsTest() {
63 val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
66 }.enterURLAndEnterToBrowser(defaultWebPage.url) {
67 }.openComposeTabDrawer(composeTestRule) {
68 verifyNormalTabsList()
70 verifyCloseAllTabsButton()
71 verifyShareAllTabsButton()
72 verifySelectTabsButton()
77 // Repeat for Private Tabs
79 }.togglePrivateBrowsingMode()
82 }.enterURLAndEnterToBrowser(defaultWebPage.url) {
83 }.openComposeTabDrawer(composeTestRule) {
84 verifyPrivateTabsList()
86 verifyCloseAllTabsButton()
92 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2349580
94 fun closingTabsTest() {
95 val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
98 }.enterURLAndEnterToBrowser(genericURL.url) {
99 }.openComposeTabDrawer(composeTestRule) {
100 verifyExistingOpenTabs("Test_Page_1")
102 verifySnackBarText("Tab closed")
103 clickSnackbarButton("UNDO")
106 verifyTabCounter("1")
110 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903604
112 fun swipeToCloseTabsTest() {
113 val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
116 }.enterURLAndEnterToBrowser(genericURL.url) {
118 }.openComposeTabDrawer(composeTestRule) {
119 verifyExistingOpenTabs("Test_Page_1")
120 swipeTabRight("Test_Page_1")
121 verifySnackBarText("Tab closed")
124 verifyTabCounter("0")
125 }.openNavigationToolbar {
126 }.enterURLAndEnterToBrowser(genericURL.url) {
128 }.openComposeTabDrawer(composeTestRule) {
129 verifyExistingOpenTabs("Test_Page_1")
130 swipeTabLeft("Test_Page_1")
131 verifySnackBarText("Tab closed")
134 verifyTabCounter("0")
138 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903591
140 fun closingPrivateTabsTest() {
141 val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
143 homeScreen { }.togglePrivateBrowsingMode(switchPBModeOn = true)
145 }.enterURLAndEnterToBrowser(genericURL.url) {
146 }.openComposeTabDrawer(composeTestRule) {
147 verifyExistingOpenTabs("Test_Page_1")
149 verifySnackBarText("Private tab closed")
150 clickSnackbarButton("UNDO")
153 verifyTabCounter("1")
157 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903606
160 fun tabMediaControlButtonTest() {
161 val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
164 }.enterURLAndEnterToBrowser(audioTestPage.url) {
165 mDevice.waitForIdle()
166 clickPageObject(MatcherHelper.itemWithText("Play"))
167 assertPlaybackState(browserStore, MediaSession.PlaybackState.PLAYING)
168 }.openComposeTabDrawer(composeTestRule) {
169 verifyTabMediaControlButtonState("Pause")
170 clickTabMediaControlButton("Pause")
171 verifyTabMediaControlButtonState("Play")
172 }.openTab(audioTestPage.title) {
173 assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED)
177 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903592
180 fun verifyCloseAllPrivateTabsNotificationTest() {
181 val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
184 }.togglePrivateBrowsingMode()
187 }.enterURLAndEnterToBrowser(defaultWebPage.url) {
188 mDevice.openNotification()
192 verifyPrivateTabsNotification()
193 }.clickClosePrivateTabsNotification {
198 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903602
200 fun verifyTabTrayNotShowingStateHalfExpanded() {
202 }.openComposeTabDrawer(composeTestRule) {
203 verifyNoOpenTabsInNormalBrowsing()
204 // With no tabs opened the state should be STATE_COLLAPSED.
205 verifyTabsTrayBehaviorState(BottomSheetBehavior.STATE_COLLAPSED)
206 // Need to ensure the halfExpandedRatio is very small so that when in STATE_HALF_EXPANDED
207 // the tabTray will actually have a very small height (for a very short time) akin to being hidden.
208 verifyMinusculeHalfExpandedRatio()
210 }.waitForTabTrayBehaviorToIdle {
211 // Touching the topBar would normally advance the tabTray to the next state.
212 // We don't want that.
213 verifyTabsTrayBehaviorState(BottomSheetBehavior.STATE_COLLAPSED)
214 }.advanceToHalfExpandedState {
215 }.waitForTabTrayBehaviorToIdle {
216 // TabTray should not be displayed in STATE_HALF_EXPANDED.
217 // When advancing to this state it should immediately be hidden.
218 verifyTabTrayIsClosed()
222 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903600
224 fun verifyEmptyTabTray() {
226 }.openComposeTabDrawer(composeTestRule) {
227 verifyNormalBrowsingButtonIsSelected()
228 verifyPrivateBrowsingButtonIsSelected(false)
229 verifySyncedTabsButtonIsSelected(false)
230 verifyNoOpenTabsInNormalBrowsing()
232 verifyThreeDotButton()
234 verifyTabSettingsButton()
235 verifyRecentlyClosedTabsButton()
239 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903585
241 fun verifyEmptyPrivateTabsTrayTest() {
243 }.openComposeTabDrawer(composeTestRule) {
244 }.toggleToPrivateTabs {
245 verifyNormalBrowsingButtonIsSelected(false)
246 verifyPrivateBrowsingButtonIsSelected(true)
247 verifySyncedTabsButtonIsSelected(false)
248 verifyNoOpenTabsInPrivateBrowsing()
250 verifyThreeDotButton()
252 verifyTabSettingsButton()
253 verifyRecentlyClosedTabsButton()
257 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903601
259 fun verifyTabsTrayWithOpenTabTest() {
260 val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
263 }.enterURLAndEnterToBrowser(defaultWebPage.url) {
264 }.openComposeTabDrawer(composeTestRule) {
265 verifyNormalBrowsingButtonIsSelected()
266 verifyPrivateBrowsingButtonIsSelected(isSelected = false)
267 verifySyncedTabsButtonIsSelected(isSelected = false)
268 verifyThreeDotButton()
269 verifyNormalTabCounter()
270 verifyNormalTabsList()
273 verifyExistingOpenTabs(defaultWebPage.title)
274 verifyTabCloseButton()
275 }.openTab(defaultWebPage.title) {
276 verifyUrl(defaultWebPage.url.toString())
277 verifyTabCounter("1")
281 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903587
284 fun verifyPrivateTabsTrayWithOpenTabTest() {
285 val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
288 }.openComposeTabDrawer(composeTestRule) {
289 }.toggleToPrivateTabs {
291 }.submitQuery(website.url.toString()) {
292 }.openComposeTabDrawer(composeTestRule) {
293 verifyNormalBrowsingButtonIsSelected(false)
294 verifyPrivateBrowsingButtonIsSelected(true)
295 verifySyncedTabsButtonIsSelected(false)
296 verifyThreeDotButton()
297 verifyNormalTabCounter()
298 verifyPrivateTabsList()
299 verifyExistingOpenTabs(website.title)
300 verifyTabCloseButton()
306 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/927314
308 fun tabsCounterShortcutMenuCloseTabTest() {
309 val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
310 val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
313 }.enterURLAndEnterToBrowser(firstWebPage.url) {
316 }.openNavigationToolbar {
317 }.enterURLAndEnterToBrowser(secondWebPage.url) {
321 }.openTabButtonShortcutsMenu {
322 verifyTabButtonShortcutMenuItems()
323 }.closeTabFromShortcutsMenu {
325 verifyTabCounter("1")
326 verifyPageContent(firstWebPage.content)
331 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2343663
333 fun tabsCounterShortcutMenuNewPrivateTabTest() {
334 val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
337 }.enterURLAndEnterToBrowser(defaultWebPage.url) {}
339 }.openTabButtonShortcutsMenu {
340 }.openNewPrivateTabFromShortcutsMenu {
341 verifySearchBarPlaceholder("Search or enter address")
343 verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = true)
347 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2343662
349 fun tabsCounterShortcutMenuNewTabTest() {
350 val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
353 }.enterURLAndEnterToBrowser(defaultWebPage.url) {}
355 }.openTabButtonShortcutsMenu {
356 }.openNewTabFromShortcutsMenu {
357 verifySearchBarPlaceholder("Search or enter address")
359 verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = false)
363 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/927315
365 fun privateTabsCounterShortcutMenuCloseTabTest() {
366 val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
367 val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
369 homeScreen {}.togglePrivateBrowsingMode(switchPBModeOn = true)
371 }.enterURLAndEnterToBrowser(firstWebPage.url) {
374 }.openNavigationToolbar {
375 }.enterURLAndEnterToBrowser(secondWebPage.url) {
379 }.openTabButtonShortcutsMenu {
380 verifyTabButtonShortcutMenuItems()
381 }.closeTabFromShortcutsMenu {
383 verifyTabCounter("1")
384 verifyPageContent(firstWebPage.content)
386 }.openTabButtonShortcutsMenu {
387 }.closeTabFromShortcutsMenu {
389 verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = true)
394 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2344199
396 fun privateTabsCounterShortcutMenuNewPrivateTabTest() {
397 val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
399 homeScreen {}.togglePrivateBrowsingMode(switchPBModeOn = true)
401 }.enterURLAndEnterToBrowser(defaultWebPage.url) {
405 }.openTabButtonShortcutsMenu {
406 }.openNewPrivateTabFromShortcutsMenu {
407 verifySearchBarPlaceholder("Search or enter address")
409 verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = true)
413 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2344198
415 fun privateTabsCounterShortcutMenuNewTabTest() {
416 val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
418 homeScreen {}.togglePrivateBrowsingMode(switchPBModeOn = true)
420 }.enterURLAndEnterToBrowser(defaultWebPage.url) {
421 verifyPageContent(defaultWebPage.content)
424 }.openTabButtonShortcutsMenu {
425 }.openNewTabFromShortcutsMenu {
426 verifySearchToolbar(isDisplayed = true)
428 verifyIfInPrivateOrNormalMode(privateBrowsingEnabled = false)
432 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1046683
434 fun verifySyncedTabsWhenUserIsNotSignedInTest() {
436 }.openComposeTabDrawer(composeTestRule) {
437 verifySyncedTabsButtonIsSelected(isSelected = false)
438 }.toggleToSyncedTabs {
439 verifySyncedTabsButtonIsSelected(isSelected = true)
440 verifySyncedTabsListWhenUserIsNotSignedIn()
441 }.clickSignInToSyncButton {
442 verifyTurnOnSyncMenu()
446 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/903598
449 fun shareTabsFromTabsTrayTest() {
450 val firstWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 1)
451 val secondWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 2)
452 val firstWebsiteTitle = firstWebsite.title
453 val secondWebsiteTitle = secondWebsite.title
454 val sharingApp = "Gmail"
455 val sharedUrlsString = "${firstWebsite.url}\n\n${secondWebsite.url}"
458 }.openNavigationToolbar {
459 }.enterURLAndEnterToBrowser(firstWebsite.url) {
460 verifyPageContent(firstWebsite.content)
461 }.openComposeTabDrawer(composeTestRule) {
463 }.submitQuery(secondWebsite.url.toString()) {
464 verifyPageContent(secondWebsite.content)
465 }.openComposeTabDrawer(composeTestRule) {
466 verifyExistingOpenTabs("Test_Page_1")
467 verifyExistingOpenTabs("Test_Page_2")
469 verifyShareAllTabsButton()
470 }.clickShareAllTabsButton {
471 verifyShareTabsOverlay(firstWebsiteTitle, secondWebsiteTitle)
472 verifySharingWithSelectedApp(
475 "$firstWebsiteTitle, $secondWebsiteTitle",
480 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/526244
482 fun privateModeStaysAsDefaultAfterRestartTest() {
483 val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
486 }.enterURLAndEnterToBrowser(defaultWebPage.url) {
488 }.togglePrivateBrowsingMode()
490 closeApp(composeTestRule.activityRule)
491 restartApp(composeTestRule.activityRule)
494 verifyPrivateBrowsingHomeScreenItems()
495 }.openComposeTabDrawer(composeTestRule) {
496 }.toggleToNormalTabs {
497 verifyExistingOpenTabs(defaultWebPage.title)
501 // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2228470
504 fun privateTabsDoNotPersistAfterClosingAppTest() {
505 val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
506 val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
509 }.togglePrivateBrowsingMode()
512 }.enterURLAndEnterToBrowser(firstWebPage.url) {
513 }.openComposeTabDrawer(composeTestRule) {
515 }.submitQuery(secondWebPage.url.toString()) {
517 closeApp(composeTestRule.activityRule)
518 restartApp(composeTestRule.activityRule)
520 verifyPrivateBrowsingHomeScreenItems()
521 }.openComposeTabDrawer(composeTestRule) {
522 verifyNoOpenTabsInPrivateBrowsing()