diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt index bdb2e31bb..a5ddedb66 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt @@ -17,6 +17,7 @@ import org.junit.Before import org.junit.Ignore import org.junit.Rule import org.junit.Test +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R import org.mozilla.fenix.ext.settings import org.mozilla.fenix.helpers.AndroidAssetDispatcher @@ -226,12 +227,21 @@ class SmokeTest { } @Test - // Verifies the Synced tabs menu opens from a tab's 3 dot menu - fun openMainMenuSyncedTabsItemTest() { - homeScreen { - }.openThreeDotMenu { - }.openSyncedTabs { - verifySyncedTabsMenuHeader() + // Verifies the Synced tabs menu or Sync Sign In menu opens from a tab's 3 dot menu. + // The test is assuming we are NOT signed in. + fun openMainMenuSyncItemTest() { + if (FeatureFlags.tabsTrayRewrite) { + homeScreen { + }.openThreeDotMenu { + }.openSyncSignIn { + verifySyncSignInMenuHeader() + } + } else { + homeScreen { + }.openThreeDotMenu { + }.openSyncedTabs { + verifySyncedTabsMenuHeader() + } } } @@ -311,7 +321,6 @@ class SmokeTest { navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { }.openThreeDotMenu { - expandMenu() }.openSaveToCollection { verifyCollectionNameTextField() } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/ThreeDotMenuMainTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/ThreeDotMenuMainTest.kt index f4814f2ee..69b2f294a 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/ThreeDotMenuMainTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/ThreeDotMenuMainTest.kt @@ -9,6 +9,7 @@ import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.HomeActivityTestRule import org.mozilla.fenix.ui.robots.homeScreen @@ -48,7 +49,11 @@ class ThreeDotMenuMainTest { verifyHistoryButton() verifyDownloadsButton() verifyAddOnsButton() - verifySyncedTabsButton() + if (FeatureFlags.tabsTrayRewrite) { + verifySyncSignInButton() + } else { + verifySyncedTabsButton() + } verifyDesktopSite() verifyWhatsNewButton() verifyHelpButton() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt index 1b692a619..96eac6ace 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt @@ -54,6 +54,7 @@ class TopSitesTest { navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { }.openThreeDotMenu { + expandMenu() verifyAddToTopSitesButton() }.addToFirefoxHome { verifySnackBarText("Added to top sites!") @@ -73,6 +74,7 @@ class TopSitesTest { navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { }.openThreeDotMenu { + expandMenu() verifyAddToTopSitesButton() }.addToFirefoxHome { verifySnackBarText("Added to top sites!") @@ -104,6 +106,7 @@ class TopSitesTest { navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { }.openThreeDotMenu { + expandMenu() verifyAddToTopSitesButton() }.addToFirefoxHome { verifySnackBarText("Added to top sites!") @@ -128,6 +131,7 @@ class TopSitesTest { navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { }.openThreeDotMenu { + expandMenu() verifyAddToTopSitesButton() }.addToFirefoxHome { verifySnackBarText("Added to top sites!") @@ -152,6 +156,7 @@ class TopSitesTest { navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { }.openThreeDotMenu { + expandMenu() verifyAddToTopSitesButton() }.addToFirefoxHome { verifySnackBarText("Added to top sites!") diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SyncSignInRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SyncSignInRobot.kt new file mode 100644 index 000000000..ac7132ea7 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SyncSignInRobot.kt @@ -0,0 +1,52 @@ +/* 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.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.withEffectiveVisibility +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.espresso.matcher.ViewMatchers.Visibility +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import org.hamcrest.CoreMatchers.allOf +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.click + +/** + * Implementation of Robot Pattern for Sync Sign In sub menu. + */ +class SyncSignInRobot { + + fun verifyAccountSettingsMenuHeader() = assertAccountSettingsMenuHeader() + fun verifySyncSignInMenuHeader() = assertSyncSignInMenuHeader() + + class Transition { + val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())!! + + fun goBack(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + goBackButton().click() + + BrowserRobot().interact() + return BrowserRobot.Transition() + } + } +} + +private fun goBackButton() = + onView(allOf(withContentDescription("Navigate up"))) + +private fun assertAccountSettingsMenuHeader() { + // Replaced with the new string here, the test is assuming we are NOT signed in + // Sync tests in SettingsSyncTest are still TO-DO, so I'm not sure that we have a test for signing into Sync + onView(withText(R.string.preferences_account_settings)) + .check((matches(withEffectiveVisibility(Visibility.VISIBLE)))) +} + +private fun assertSyncSignInMenuHeader() { + onView(withText(R.string.sign_in_with_camera)) + .check((matches(withEffectiveVisibility(Visibility.VISIBLE)))) +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt index fcfaac7e4..9db6eef94 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuMainRobot.kt @@ -51,6 +51,7 @@ class ThreeDotMenuMainRobot { fun verifyHistoryButton() = assertHistoryButton() fun verifyBookmarksButton() = assertBookmarksButton() fun verifySyncedTabsButton() = assertSyncedTabsButton() + fun verifySyncSignInButton() = assertSignInToSyncButton() fun verifyHelpButton() = assertHelpButton() fun verifyThreeDotMenuExists() = threeDotMenuRecyclerViewExists() fun verifyForwardButton() = assertForwardButton() @@ -164,6 +165,15 @@ class ThreeDotMenuMainRobot { return SyncedTabsRobot.Transition() } + fun openSyncSignIn(interact: SyncSignInRobot.() -> Unit): SyncSignInRobot.Transition { + onView(withId(R.id.mozac_browser_menu_recyclerView)).perform(swipeDown()) + mDevice.waitNotNull(Until.findObject(By.text("Sign in to sync")), waitingTime) + signInToSyncButton().click() + + SyncSignInRobot().interact() + return SyncSignInRobot.Transition() + } + fun openBookmarks(interact: BookmarksRobot.() -> Unit): BookmarksRobot.Transition { onView(withId(R.id.mozac_browser_menu_recyclerView)).perform(swipeDown()) mDevice.waitNotNull(Until.findObject(By.text("Bookmarks")), waitingTime) @@ -193,11 +203,6 @@ class ThreeDotMenuMainRobot { } fun sharePage(interact: LibrarySubMenusMultipleSelectionToolbarRobot.() -> Unit): LibrarySubMenusMultipleSelectionToolbarRobot.Transition { - var maxSwipes = 3 - while (!shareButton().exists() && maxSwipes != 0) { - threeDotMenuRecyclerView().perform(swipeUp()) - maxSwipes-- - } shareButton().click() LibrarySubMenusMultipleSelectionToolbarRobot().interact() return LibrarySubMenusMultipleSelectionToolbarRobot.Transition() @@ -212,11 +217,6 @@ class ThreeDotMenuMainRobot { } fun goForward(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { - var maxSwipes = 3 - while (!forwardButton().exists() && maxSwipes != 0) { - threeDotMenuRecyclerView().perform(swipeUp()) - maxSwipes-- - } forwardButton().click() BrowserRobot().interact() @@ -250,11 +250,6 @@ class ThreeDotMenuMainRobot { } fun refreshPage(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { - var maxSwipes = 3 - while (!refreshButton().exists() && maxSwipes != 0) { - threeDotMenuRecyclerView().perform(swipeUp()) - maxSwipes-- - } assertRefreshButton() refreshButton().click() @@ -369,6 +364,11 @@ class ThreeDotMenuMainRobot { } fun openSaveToCollection(interact: ThreeDotMenuMainRobot.() -> Unit): ThreeDotMenuMainRobot.Transition { + // Ensure the menu is expanded and fully scrolled to the bottom. + for (i in 0..3) { + threeDotMenuRecyclerView().perform(swipeUp()) + } + mDevice.waitNotNull(Until.findObject(By.text("Save to collection")), waitingTime) saveCollectionButton().click() ThreeDotMenuMainRobot().interact() diff --git a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt index eaf3489f9..205761689 100644 --- a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt +++ b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt @@ -37,7 +37,7 @@ object FeatureFlags { /** * Shows new three-dot toolbar menu design. */ - val toolbarMenuFeature = Config.channel.isNightlyOrDebug + const val toolbarMenuFeature = true /** * Enables the tabs tray re-write with Synced Tabs. diff --git a/app/src/main/java/org/mozilla/fenix/components/accounts/FenixAccountManager.kt b/app/src/main/java/org/mozilla/fenix/components/accounts/FenixAccountManager.kt new file mode 100644 index 000000000..fe5397bd1 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/components/accounts/FenixAccountManager.kt @@ -0,0 +1,33 @@ +/* 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.components.accounts + +import android.content.Context +import mozilla.components.service.fxa.manager.FxaAccountManager +import org.mozilla.fenix.ext.components + +/** + * Component which holds a reference to [FxaAccountManager]. Manages account authentication, + * profiles, and profile state observers. + */ +open class FenixAccountManager(context: Context) { + val accountManager = context.components.backgroundServices.accountManager + + val authenticatedAccount + get() = accountManager.authenticatedAccount() != null + + val accountProfileEmail + get() = accountManager.accountProfile()?.email + + /** + * Check if the current account is signed in and authenticated. + */ + fun signedInToFxa(): Boolean { + val account = accountManager.authenticatedAccount() + val needsReauth = accountManager.accountNeedsReauth() + + return account != null && !needsReauth + } +} diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt index fee10c378..8f7fdd0f0 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt @@ -226,10 +226,15 @@ class DefaultBrowserToolbarMenuController( ) } is ToolbarMenu.Item.SyncAccount -> { + val directions = if (item.signedIn) { + BrowserFragmentDirections.actionGlobalAccountSettingsFragment() + } else { + BrowserFragmentDirections.actionGlobalTurnOnSync() + } browserAnimator.captureEngineViewAndDrawStatically { navController.nav( R.id.browserFragment, - BrowserFragmentDirections.actionGlobalAccountSettingsFragment() + directions ) } } diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt index 21ab04666..985644685 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt @@ -39,6 +39,7 @@ import org.mozilla.fenix.FeatureFlags.tabsTrayRewrite import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import org.mozilla.fenix.components.accounts.FenixAccountManager import org.mozilla.fenix.experiments.ExperimentBranch import org.mozilla.fenix.experiments.Experiments import org.mozilla.fenix.ext.asActivity @@ -74,12 +75,11 @@ open class DefaultToolbarMenu( private val shouldDeleteDataOnQuit = context.settings().shouldDeleteBrowsingDataOnQuit private val shouldUseBottomToolbar = context.settings().shouldUseBottomToolbar + private val accountManager = FenixAccountManager(context) private val selectedSession: TabSessionState? get() = store.state.selectedTab - private val accountManager = context.components.backgroundServices.accountManager - override val menuBuilder by lazy { WebExtensionBrowserMenuBuilder( items = @@ -161,7 +161,7 @@ open class DefaultToolbarMenu( registerForIsBookmarkedUpdates() if (FeatureFlags.toolbarMenuFeature) { - BrowserMenuItemToolbar(listOf(back, forward, share, refresh)) + BrowserMenuItemToolbar(listOf(back, forward, share, refresh), isSticky = true) } else { val bookmark = BrowserMenuItemToolbar.TwoStateButton( primaryImageResource = R.drawable.ic_bookmark_filled, @@ -534,10 +534,10 @@ open class DefaultToolbarMenu( } private fun getSyncItemTitle(): String { - val authenticatedAccount = accountManager.authenticatedAccount() != null - val email = accountManager.accountProfile()?.email + val authenticatedAccount = accountManager.authenticatedAccount + val email = accountManager.accountProfileEmail - return if (authenticatedAccount && email != null) { + return if (authenticatedAccount && !email.isNullOrEmpty()) { email } else { context.getString(R.string.sync_menu_sign_in) @@ -549,7 +549,7 @@ open class DefaultToolbarMenu( R.drawable.ic_synced_tabs, primaryTextColor() ) { - onItemTapped.invoke(ToolbarMenu.Item.SyncAccount) + onItemTapped.invoke(ToolbarMenu.Item.SyncAccount(accountManager.signedInToFxa())) } @VisibleForTesting(otherwise = PRIVATE) diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt index 7b547e7fe..ec384c188 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt @@ -23,7 +23,7 @@ interface ToolbarMenu { object InstallPwaToHomeScreen : Item() object AddToHomeScreen : Item() object SyncedTabs : Item() - object SyncAccount : Item() + data class SyncAccount(val signedIn: Boolean) : Item() object AddonsManager : Item() object Quit : Item() object OpenInApp : Item() 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 693c14444..a43261f41 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -89,6 +89,7 @@ import org.mozilla.fenix.GleanMetrics.PerfStartup import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.browser.BrowserAnimator.Companion.getToolbarNavOptions +import org.mozilla.fenix.browser.BrowserFragmentDirections import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.PrivateShortcutCreateManager @@ -792,6 +793,18 @@ class HomeFragment : Fragment() { HomeFragmentDirections.actionGlobalSyncedTabsFragment() ) } + is HomeMenu.Item.SyncAccount -> { + hideOnboardingIfNeeded() + val directions = if (it.signedIn) { + BrowserFragmentDirections.actionGlobalAccountSettingsFragment() + } else { + BrowserFragmentDirections.actionGlobalTurnOnSync() + } + nav( + R.id.homeFragment, + directions + ) + } HomeMenu.Item.Bookmarks -> { hideOnboardingIfNeeded() nav( diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt index 6d2f6f877..4c22f21d8 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt @@ -24,7 +24,9 @@ import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.OAuthAccount import mozilla.components.support.ktx.android.content.getColorFromAttr import org.mozilla.fenix.FeatureFlags +import org.mozilla.fenix.FeatureFlags.tabsTrayRewrite import org.mozilla.fenix.R +import org.mozilla.fenix.components.accounts.FenixAccountManager import org.mozilla.fenix.experiments.ExperimentBranch import org.mozilla.fenix.experiments.Experiments import org.mozilla.fenix.ext.components @@ -47,6 +49,7 @@ class HomeMenu( object Downloads : Item() object Extensions : Item() object SyncTabs : Item() + data class SyncAccount(val signedIn: Boolean) : Item() object WhatsNew : Item() object Help : Item() object Settings : Item() @@ -55,15 +58,14 @@ class HomeMenu( data class DesktopMode(val checked: Boolean) : Item() } - private val primaryTextColor = - ThemeManager.resolveAttribute(R.attr.primaryText, context) + private val primaryTextColor = ThemeManager.resolveAttribute(R.attr.primaryText, context) private val syncDisconnectedColor = ThemeManager.resolveAttribute(R.attr.syncDisconnected, context) private val syncDisconnectedBackgroundColor = context.getColorFromAttr(R.attr.syncDisconnectedBackground) private val shouldUseBottomToolbar = context.settings().shouldUseBottomToolbar - private val accountManager = context.components.backgroundServices.accountManager + private val accountManager = FenixAccountManager(context) // 'Reconnect' and 'Quit' items aren't needed most of the time, so we'll only create the if necessary. private val reconnectToSyncItem by lazy { @@ -92,17 +94,33 @@ class HomeMenu( } } + val syncedTabsItem = BrowserMenuImageText( + context.getString(R.string.synced_tabs), + R.drawable.ic_synced_tabs, + primaryTextColor + ) { + onItemTapped.invoke(Item.SyncTabs) + } + private fun getSyncItemTitle(): String { - val authenticatedAccount = accountManager.authenticatedAccount() != null - val email = accountManager.accountProfile()?.email + val authenticatedAccount = accountManager.authenticatedAccount + val email = accountManager.accountProfileEmail - return if (authenticatedAccount && email != null) { + return if (authenticatedAccount && !email.isNullOrEmpty()) { email } else { context.getString(R.string.sync_menu_sign_in) } } + val syncSignInMenuItem = BrowserMenuImageText( + getSyncItemTitle(), + R.drawable.ic_synced_tabs, + primaryTextColor + ) { + onItemTapped.invoke(Item.SyncAccount(accountManager.signedInToFxa())) + } + private val oldCoreMenuItems by lazy { val whatsNewItem = BrowserMenuHighlightableItem( context.getString(R.string.browser_menu_whats_new), @@ -169,14 +187,6 @@ class HomeMenu( onItemTapped.invoke(Item.Settings) } - val syncedTabsItem = BrowserMenuImageText( - getSyncItemTitle(), - R.drawable.ic_synced_tabs, - primaryTextColor - ) { - onItemTapped.invoke(Item.SyncTabs) - } - val helpItem = BrowserMenuImageText( context.getString(R.string.browser_menu_help), R.drawable.ic_help, @@ -293,14 +303,6 @@ class HomeMenu( onItemTapped.invoke(Item.Extensions) } - val syncSignInItem = BrowserMenuImageText( - context.getString(R.string.library_synced_tabs), - R.drawable.ic_synced_tabs, - primaryTextColor - ) { - onItemTapped.invoke(Item.SyncTabs) - } - val whatsNewItem = BrowserMenuHighlightableItem( context.getString(R.string.browser_menu_whats_new), R.drawable.ic_whats_new, @@ -344,7 +346,7 @@ class HomeMenu( historyItem, downloadsItem, extensionsItem, - syncSignInItem, + if (tabsTrayRewrite) syncSignInMenuItem else syncedTabsItem, accountAuthItem, BrowserMenuDivider(), desktopItem, diff --git a/app/src/test/java/org/mozilla/fenix/components/accounts/FenixAccountManagerTest.kt b/app/src/test/java/org/mozilla/fenix/components/accounts/FenixAccountManagerTest.kt new file mode 100644 index 000000000..d93616bc5 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/components/accounts/FenixAccountManagerTest.kt @@ -0,0 +1,101 @@ +/* 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.components.accounts + +import android.content.Context +import io.mockk.every +import io.mockk.mockk +import mozilla.components.concept.sync.OAuthAccount +import mozilla.components.concept.sync.Profile +import mozilla.components.service.fxa.manager.FxaAccountManager +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner + +@RunWith(FenixRobolectricTestRunner::class) +class FenixAccountManagerTest { + + private lateinit var fenixFxaManager: FenixAccountManager + private lateinit var accountManagerComponent: FxaAccountManager + private lateinit var context: Context + private lateinit var account: OAuthAccount + private lateinit var profile: Profile + + @Before + fun setUp() { + context = mockk(relaxed = true) + account = mockk(relaxed = true) + profile = mockk(relaxed = true) + accountManagerComponent = mockk(relaxed = true) + } + + @Test + fun `GIVEN an account exists THEN fetch the associated email address`() { + every { accountManagerComponent.authenticatedAccount() } returns account + every { accountManagerComponent.accountProfile() } returns profile + every { context.components.backgroundServices.accountManager } returns accountManagerComponent + + fenixFxaManager = FenixAccountManager(context) + + val emailAddress = "firefoxIsFun@test.com" + every { accountManagerComponent.accountProfile()?.email } returns emailAddress + + val result = fenixFxaManager.accountProfileEmail + assertEquals(emailAddress, result) + } + + @Test + fun `GIVEN an account does not exist THEN return null when fetching the associated email address`() { + every { accountManagerComponent.authenticatedAccount() } returns null + every { accountManagerComponent.accountProfile() } returns null + every { context.components.backgroundServices.accountManager } returns accountManagerComponent + + fenixFxaManager = FenixAccountManager(context) + + val result = fenixFxaManager.accountProfileEmail + assertEquals(null, result) + } + + @Test + fun `GIVEN an account is signed in and authenticated THEN check returns true`() { + every { accountManagerComponent.authenticatedAccount() } returns account + every { accountManagerComponent.accountNeedsReauth() } returns false + every { context.components.backgroundServices.accountManager } returns accountManagerComponent + + fenixFxaManager = FenixAccountManager(context) + + val signedIn = fenixFxaManager.signedInToFxa() + assertTrue(signedIn) + } + + @Test + fun `GIVEN an account is signed in and NOT authenticated THEN check returns false`() { + every { accountManagerComponent.authenticatedAccount() } returns account + every { accountManagerComponent.accountNeedsReauth() } returns true + every { context.components.backgroundServices.accountManager } returns accountManagerComponent + + fenixFxaManager = FenixAccountManager(context) + + val signedIn = fenixFxaManager.signedInToFxa() + assertFalse(signedIn) + } + + @Test + fun `GIVEN an account is not signed in THEN check returns false`() { + every { accountManagerComponent.authenticatedAccount() } returns null + every { accountManagerComponent.accountNeedsReauth() } returns true + every { context.components.backgroundServices.accountManager } returns accountManagerComponent + + fenixFxaManager = FenixAccountManager(context) + + val signedIn = fenixFxaManager.signedInToFxa() + assertFalse(signedIn) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt b/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt index 118043de8..a60977431 100644 --- a/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt @@ -572,6 +572,28 @@ class DefaultBrowserToolbarMenuControllerTest { } } + @Test + fun `WHEN sync sign in menu item is pressed AND account is signed out THEN navigate to sync sign in`() = runBlockingTest { + val item = ToolbarMenu.Item.SyncAccount(false) + val directions = BrowserFragmentDirections.actionGlobalTurnOnSync() + + val controller = createController(scope = this, store = browserStore) + controller.handleToolbarItemInteraction(item) + + verify { navController.navigate(directions, null) } + } + + @Test + fun `WHEN sync sign in menu item is pressed AND account is signed in THEN navigate to sync sign in`() = runBlockingTest { + val item = ToolbarMenu.Item.SyncAccount(true) + val directions = BrowserFragmentDirections.actionGlobalAccountSettingsFragment() + + val controller = createController(scope = this, store = browserStore) + controller.handleToolbarItemInteraction(item) + + verify { navController.navigate(directions, null) } + } + private fun createController( scope: CoroutineScope, store: BrowserStore,