From 6f899c7fb5f917ef6591d4ce8be7706817293299 Mon Sep 17 00:00:00 2001 From: Yeon Taek Jeong Date: Tue, 20 Aug 2019 13:10:08 -0700 Subject: [PATCH] For #2834: Delete all Private Tabs redesign (#4787) --- .../org/mozilla/fenix/ui/HomeScreenTest.kt | 45 +++++++++++++++++++ .../mozilla/fenix/ui/robots/BrowserRobot.kt | 12 +++++ .../fenix/ui/robots/HomeScreenRobot.kt | 42 +++++++++++++++++ .../mozilla/fenix/ui/robots/SearchRobot.kt | 8 ++++ .../org/mozilla/fenix/home/HomeFragment.kt | 15 +++++-- .../viewholders/TabHeaderViewHolder.kt | 17 ++++++- .../layout/private_browsing_description.xml | 7 --- app/src/main/res/layout/tab_header.xml | 14 ++++++ app/src/main/res/values/strings.xml | 2 + 9 files changed, 150 insertions(+), 12 deletions(-) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt index 2ee660052..283112ffc 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/HomeScreenTest.kt @@ -10,6 +10,10 @@ import org.junit.Test import org.mozilla.fenix.helpers.HomeActivityTestRule import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.By +import androidx.test.uiautomator.Until +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.ui.robots.PRIVATE_SESSION_MESSAGE import org.mozilla.fenix.ui.robots.homeScreen /** @@ -88,4 +92,45 @@ class HomeScreenTest { verifyStartBrowsingButton() } } + + @Test + fun privateModeScreenItemsTest() { + homeScreen { }.dismissOnboarding() + homeScreen { }.turnOnPrivateMode() + + homeScreen { + verifyHomeScreen() + verifyNavigationToolbar() + verifyHomePrivateBrowsingButton() + verifyHomeMenu() + verifyHomeWordmark() + verifyAddTabButton() + verifyShareTabsButton(visible = false) + verifyCloseTabsButton(visible = false) + verifyPrivateSessionHeader() + verifyPrivateSessionMessage(visible = true) + verifyHomeToolbar() + verifyHomeComponent() + } + + homeScreen { }.addNewTab() + + homeScreen { + // To deal with the race condition where multiple "add tab" buttons are present, + // we need to wait until previous HomeFragment View objects are gone. + mDevice.wait(Until.gone(By.text(PRIVATE_SESSION_MESSAGE)), waitingTime) + verifyHomeScreen() + verifyNavigationToolbar() + verifyHomePrivateBrowsingButton() + verifyHomeMenu() + verifyHomeWordmark() + verifyAddTabButton() + verifyShareTabsButton(visible = true) + verifyCloseTabsButton(visible = true) + verifyPrivateSessionHeader() + verifyPrivateSessionMessage(visible = false) + verifyHomeToolbar() + verifyHomeComponent() + } + } } 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 cddcc8ec1..64f93adc9 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 @@ -8,6 +8,7 @@ package org.mozilla.fenix.ui.robots import androidx.test.espresso.Espresso.onView import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.platform.app.InstrumentationRegistry @@ -48,6 +49,15 @@ class BrowserRobot { NavigationToolbarRobot().interact() return NavigationToolbarRobot.Transition() } + + fun openHomeScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { + mDevice.waitForIdle() + + tabsCounter().click() + + HomeScreenRobot().interact() + return HomeScreenRobot.Transition() + } } } @@ -57,3 +67,5 @@ fun browserScreen(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { } fun navURLBar() = onView(withId(R.id.mozac_browser_toolbar_url_view)) + +private fun tabsCounter() = onView(withContentDescription("Tabs")) 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 5a3fe3b7b..38a194c62 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 @@ -8,6 +8,7 @@ package org.mozilla.fenix.ui.robots import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.doesNotExist import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.Visibility @@ -65,6 +66,12 @@ class HomeScreenRobot { fun verifyPrivacyNoticeButton() = assertPrivacyNoticeButton() fun verifyStartBrowsingButton() = assertStartBrowsingButton() + // Private mode elements + fun verifyPrivateSessionHeader() = assertPrivateSessionHeader() + fun verifyPrivateSessionMessage(visible: Boolean = true) = assertPrivateSessionMessage(visible) + fun verifyShareTabsButton(visible: Boolean = true) = assertShareTabsButton(visible) + fun verifyCloseTabsButton(visible: Boolean = true) = assertCloseTabsButton(visible) + private fun scrollToElementByText(text: String): UiScrollable { val appView = UiScrollable(UiSelector().scrollable(true)) appView.scrollTextIntoView(text) @@ -97,6 +104,15 @@ class HomeScreenRobot { fun dismissOnboarding() { openThreeDotMenu { }.openSettings { }.goBack { } } + + fun addNewTab() { + openSearch { }.openBrowser { }.openHomeScreen { } + } + + fun turnOnPrivateMode() { + onView(ViewMatchers.withResourceName("privateBrowsingButton")) + .perform(click()) + } } } @@ -262,3 +278,29 @@ private fun assertPrivacyNoticeButton() = private fun assertStartBrowsingButton() = onView(CoreMatchers.allOf(ViewMatchers.withText("Start browsing"))) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + +// Private mode elements +private fun assertPrivateSessionHeader() = + onView(CoreMatchers.allOf(ViewMatchers.withText("Private session"))) + .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 " + + "your internet service provider, it makes it easier to keep what you do online private from anyone else " + + "who uses this device.\n\nCommon myths about private browsing" + +private fun assertPrivateSessionMessage(visible: Boolean) = + onView(CoreMatchers.allOf(ViewMatchers.withText(PRIVATE_SESSION_MESSAGE))) + .check( + if (visible) matches(withEffectiveVisibility(Visibility.VISIBLE)) else doesNotExist() + ) + +private fun assertShareTabsButton(visible: Boolean) = + onView(CoreMatchers.allOf(ViewMatchers.withResourceName("share_tabs_button"))) + .check(matches(withEffectiveVisibility(visibleOrGone(visible)))) + +private fun assertCloseTabsButton(visible: Boolean) = + onView(CoreMatchers.allOf(ViewMatchers.withResourceName("close_tabs_button"))) + .check(matches(withEffectiveVisibility(visibleOrGone(visible)))) + +private fun visibleOrGone(visibility: Boolean) = if (visibility) Visibility.VISIBLE else Visibility.GONE diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt index 8ee6ce800..f0842fec4 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt @@ -84,6 +84,14 @@ class SearchRobot { class Transition { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + fun openBrowser(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + mDevice.waitForIdle() + browserToolbarEditView().perform(typeText("Mozilla\n")) + + BrowserRobot().interact() + return BrowserRobot.Transition() + } } } diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 3be4291a1..2242cb750 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -347,14 +347,15 @@ class HomeFragment : Fragment(), AccountObserver { } is TabAction.CloseAll -> { if (pendingSessionDeletion?.deletionJob == null) removeAllTabsWithUndo( - sessionManager.filteredSessions(action.private) + sessionManager.filteredSessions(action.private), + action.private ) else { pendingSessionDeletion?.deletionJob?.let { viewLifecycleOwner.lifecycleScope.launch { it.invoke() }.invokeOnCompletion { pendingSessionDeletion = null - removeAllTabsWithUndo(sessionManager.filteredSessions(action.private)) + removeAllTabsWithUndo(sessionManager.filteredSessions(action.private), action.private) } } } @@ -581,7 +582,7 @@ class HomeFragment : Fragment(), AccountObserver { } } - private fun removeAllTabsWithUndo(listOfSessionsToDelete: List) { + private fun removeAllTabsWithUndo(listOfSessionsToDelete: List, private: Boolean) { val sessionManager = requireComponents.core.sessionManager getManagedEmitter().onNext(SessionControlChange.TabsChange(listOf())) @@ -593,9 +594,15 @@ class HomeFragment : Fragment(), AccountObserver { } deleteAllSessionsJob = deleteOperation + val snackbarMessage = if (private) { + getString(R.string.snackbar_private_tabs_deleted) + } else { + getString(R.string.snackbar_tab_deleted) + } + viewLifecycleOwner.lifecycleScope.allowUndo( view!!, - getString(R.string.snackbar_tabs_deleted), + snackbarMessage, getString(R.string.snackbar_deleted_undo), { deleteAllSessionsJob = null emitSessionChanges() diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabHeaderViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabHeaderViewHolder.kt index 027f969d2..d68daa14b 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabHeaderViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabHeaderViewHolder.kt @@ -6,6 +6,7 @@ package org.mozilla.fenix.home.sessioncontrol.viewholders import android.content.Context import android.view.View +import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import io.reactivex.Observer import kotlinx.android.synthetic.main.tab_header.view.* @@ -46,6 +47,18 @@ class TabHeaderViewHolder( } } + share_tabs_button.run { + setOnClickListener { + actionEmitter.onNext(TabAction.ShareTabs) + } + } + + close_tabs_button.run { + setOnClickListener { + actionEmitter.onNext(TabAction.CloseAll(true)) + } + } + tabs_overflow_button.run { setOnClickListener { tabsMenu.menuBuilder @@ -63,7 +76,9 @@ class TabHeaderViewHolder( val headerTextResourceId = if (isPrivate) R.string.tabs_header_private_title else R.string.tab_header_label view.header_text.text = view.context.getString(headerTextResourceId) - view.tabs_overflow_button.visibility = if (hasTabs) View.VISIBLE else View.GONE + view.share_tabs_button.isVisible = isPrivate && hasTabs + view.close_tabs_button.isVisible = isPrivate && hasTabs + view.tabs_overflow_button.isVisible = !isPrivate && hasTabs } class TabHeaderMenu( diff --git a/app/src/main/res/layout/private_browsing_description.xml b/app/src/main/res/layout/private_browsing_description.xml index bab1c1db6..8eab61edb 100644 --- a/app/src/main/res/layout/private_browsing_description.xml +++ b/app/src/main/res/layout/private_browsing_description.xml @@ -9,13 +9,6 @@ android:layout_height="wrap_content" android:layout_margin="16dp" android:orientation="vertical"> - + + + + Tab deleted Tabs deleted + + Private tabs deleted UNDO