| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.chrome.browser.signin; |
| |
| import static androidx.test.espresso.Espresso.onView; |
| import static androidx.test.espresso.action.ViewActions.click; |
| import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; |
| import static androidx.test.espresso.assertion.ViewAssertions.matches; |
| import static androidx.test.espresso.matcher.RootMatchers.isDialog; |
| import static androidx.test.espresso.matcher.ViewMatchers.isChecked; |
| import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; |
| import static androidx.test.espresso.matcher.ViewMatchers.withId; |
| import static androidx.test.espresso.matcher.ViewMatchers.withText; |
| |
| import static org.hamcrest.Matchers.not; |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.ArgumentMatchers.anyInt; |
| import static org.mockito.ArgumentMatchers.eq; |
| import static org.mockito.ArgumentMatchers.notNull; |
| import static org.mockito.Mockito.atLeastOnce; |
| import static org.mockito.Mockito.doAnswer; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.never; |
| import static org.mockito.Mockito.timeout; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| import android.app.Activity; |
| import android.content.res.Configuration; |
| import android.graphics.drawable.ColorDrawable; |
| import android.graphics.drawable.Drawable; |
| import android.widget.ProgressBar; |
| |
| import androidx.appcompat.app.AppCompatDelegate; |
| import androidx.test.espresso.ViewAction; |
| import androidx.test.filters.MediumTest; |
| |
| import org.junit.After; |
| import org.junit.Assert; |
| import org.junit.Before; |
| import org.junit.BeforeClass; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.AdditionalAnswers; |
| import org.mockito.ArgumentCaptor; |
| import org.mockito.Captor; |
| import org.mockito.Mock; |
| import org.mockito.junit.MockitoJUnit; |
| import org.mockito.junit.MockitoRule; |
| |
| import org.chromium.base.Callback; |
| import org.chromium.base.Promise; |
| import org.chromium.base.supplier.OneshotSupplierImpl; |
| import org.chromium.base.test.BaseActivityTestRule; |
| import org.chromium.base.test.metrics.HistogramTestRule; |
| import org.chromium.base.test.params.ParameterAnnotations; |
| import org.chromium.base.test.params.ParameterizedRunner; |
| import org.chromium.base.test.util.CallbackHelper; |
| import org.chromium.base.test.util.CommandLineFlags; |
| import org.chromium.base.test.util.CriteriaHelper; |
| import org.chromium.base.test.util.DoNotBatch; |
| import org.chromium.chrome.R; |
| import org.chromium.chrome.browser.enterprise.util.EnterpriseInfo; |
| import org.chromium.chrome.browser.enterprise.util.EnterpriseInfo.OwnedState; |
| import org.chromium.chrome.browser.enterprise.util.FakeEnterpriseInfo; |
| import org.chromium.chrome.browser.firstrun.FirstRunPageDelegate; |
| import org.chromium.chrome.browser.firstrun.FirstRunUtils; |
| import org.chromium.chrome.browser.firstrun.FirstRunUtilsJni; |
| import org.chromium.chrome.browser.firstrun.MobileFreProgress; |
| import org.chromium.chrome.browser.firstrun.PolicyLoadListener; |
| import org.chromium.chrome.browser.flags.ChromeSwitches; |
| import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManagerImpl; |
| import org.chromium.chrome.browser.profiles.Profile; |
| import org.chromium.chrome.browser.signin.services.DisplayableProfileData; |
| import org.chromium.chrome.browser.signin.services.FREMobileIdentityConsistencyFieldTrial; |
| import org.chromium.chrome.browser.signin.services.FREMobileIdentityConsistencyFieldTrial.VariationsGroup; |
| import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; |
| import org.chromium.chrome.browser.signin.services.SigninChecker; |
| import org.chromium.chrome.browser.signin.services.SigninManager; |
| import org.chromium.chrome.browser.ui.signin.fre.SigninFirstRunMediator.LoadPoint; |
| import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; |
| import org.chromium.chrome.test.util.ActivityTestUtils; |
| import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; |
| import org.chromium.chrome.test.util.browser.signin.SigninTestRule; |
| import org.chromium.components.browser_ui.styles.SemanticColorUtils; |
| import org.chromium.components.externalauth.ExternalAuthUtils; |
| import org.chromium.components.policy.PolicyService; |
| import org.chromium.components.signin.AccountUtils; |
| import org.chromium.components.signin.base.CoreAccountInfo; |
| import org.chromium.components.signin.identitymanager.ConsentLevel; |
| import org.chromium.components.signin.identitymanager.IdentityManager; |
| import org.chromium.content_public.browser.test.NativeLibraryTestUtils; |
| import org.chromium.content_public.browser.test.util.TestThreadUtils; |
| import org.chromium.ui.test.util.BlankUiTestActivity; |
| import org.chromium.ui.test.util.NightModeTestUtils; |
| import org.chromium.ui.test.util.ViewUtils; |
| |
| /** Tests for the class {@link SigninFirstRunFragment}. */ |
| @RunWith(ParameterizedRunner.class) |
| @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) |
| @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) |
| @DoNotBatch(reason = "Relies on global state") |
| public class SigninFirstRunFragmentTest { |
| private static final String TEST_EMAIL1 = "test.account1@gmail.com"; |
| private static final String FULL_NAME1 = "Test Account1"; |
| private static final String GIVEN_NAME1 = "Account1"; |
| private static final String TEST_EMAIL2 = "test.account2@gmail.com"; |
| private static final String CHILD_ACCOUNT_EMAIL = |
| AccountManagerTestRule.generateChildEmail("account@gmail.com"); |
| private static final String CHILD_FULL_NAME = "Test Child"; |
| |
| /** |
| * This class is used to test {@link SigninFirstRunFragment}. |
| */ |
| public static class CustomSigninFirstRunFragment extends SigninFirstRunFragment { |
| private FirstRunPageDelegate mFirstRunPageDelegate; |
| |
| @Override |
| public FirstRunPageDelegate getPageDelegate() { |
| return mFirstRunPageDelegate; |
| } |
| |
| void setPageDelegate(FirstRunPageDelegate delegate) { |
| mFirstRunPageDelegate = delegate; |
| } |
| } |
| |
| @Rule |
| public final MockitoRule mMockitoRule = MockitoJUnit.rule(); |
| |
| @Rule |
| public HistogramTestRule mHistogramTestRule = new HistogramTestRule(); |
| |
| @Rule |
| public final SigninTestRule mSigninTestRule = new SigninTestRule(); |
| |
| @Rule |
| public final BaseActivityTestRule<BlankUiTestActivity> mActivityTestRule = |
| new BaseActivityTestRule(BlankUiTestActivity.class); |
| |
| @Mock |
| private ExternalAuthUtils mExternalAuthUtilsMock; |
| @Mock |
| private FirstRunPageDelegate mFirstRunPageDelegateMock; |
| @Mock |
| public FirstRunUtils.Natives mFirstRunUtils; |
| @Mock |
| public PolicyService mPolicyService; |
| @Mock |
| private PolicyLoadListener mPolicyLoadListenerMock; |
| @Mock |
| private OneshotSupplierImpl<Boolean> mChildAccountStatusListenerMock; |
| @Mock |
| private SigninManager mSigninManagerMock; |
| @Mock |
| private IdentityManager mIdentityManagerMock; |
| @Mock |
| private SigninChecker mSigninCheckerMock; |
| @Mock |
| private IdentityServicesProvider mIdentityServicesProviderMock; |
| @Captor |
| private ArgumentCaptor<Callback<Boolean>> mCallbackCaptor; |
| @Mock |
| private PrivacyPreferencesManagerImpl mPrivacyPreferencesManagerMock; |
| |
| private Promise<Void> mNativeInitializationPromise; |
| private FakeEnterpriseInfo mFakeEnterpriseInfo = new FakeEnterpriseInfo(); |
| private CustomSigninFirstRunFragment mFragment; |
| |
| @ParameterAnnotations.UseMethodParameterBefore(NightModeTestUtils.NightModeParams.class) |
| public void setupNightMode(boolean nightModeEnabled) { |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| AppCompatDelegate.setDefaultNightMode(nightModeEnabled |
| ? AppCompatDelegate.MODE_NIGHT_YES |
| : AppCompatDelegate.MODE_NIGHT_NO); |
| }); |
| } |
| |
| @BeforeClass |
| public static void setUpBeforeActivityLaunched() { |
| // Only needs to be loaded once and needs to be loaded before HistogramTestRule. |
| // TODO(https://crbug.com/1211884): Revise after HistogramTestRule is revised to not require |
| // native loading. |
| NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); |
| } |
| |
| @Before |
| public void setUp() { |
| // SigninTestRule requires access to Profile which in turn requires browser process to be |
| // initialized. Calling this method in #setUpBeforeActivityLaunched() method causes a |
| // crash. |
| NativeLibraryTestUtils.loadNativeLibraryAndInitBrowserProcess(); |
| mSigninTestRule.waitForSeeding(); |
| |
| when(mExternalAuthUtilsMock.canUseGooglePlayServices()).thenReturn(true); |
| ExternalAuthUtils.setInstanceForTesting(mExternalAuthUtilsMock); |
| EnterpriseInfo.setInstanceForTest(mFakeEnterpriseInfo); |
| mFakeEnterpriseInfo.initialize(new OwnedState( |
| /*isDeviceOwned=*/false, /*isProfileOwned=*/false)); |
| FirstRunUtils.setDisableDelayOnExitFreForTest(true); |
| FirstRunUtilsJni.TEST_HOOKS.setInstanceForTesting(mFirstRunUtils); |
| SigninCheckerProvider.setForTests(mSigninCheckerMock); |
| FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting( |
| VariationsGroup.DEFAULT); |
| |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| mNativeInitializationPromise = new Promise<>(); |
| mNativeInitializationPromise.fulfill(null); |
| // Use thenAnswer in case mNativeSideIsInitialized is changed in some tests. |
| when(mFirstRunPageDelegateMock.getNativeInitializationPromise()) |
| .thenAnswer(ignored -> mNativeInitializationPromise); |
| }); |
| |
| when(mPolicyLoadListenerMock.get()).thenReturn(false); |
| when(mFirstRunPageDelegateMock.getPolicyLoadListener()).thenReturn(mPolicyLoadListenerMock); |
| when(mChildAccountStatusListenerMock.get()).thenReturn(false); |
| when(mFirstRunPageDelegateMock.getChildAccountStatusSupplier()) |
| .thenReturn(mChildAccountStatusListenerMock); |
| when(mFirstRunPageDelegateMock.isLaunchedFromCct()).thenReturn(false); |
| mActivityTestRule.launchActivity(null); |
| mFragment = new CustomSigninFirstRunFragment(); |
| mFragment.setPageDelegate(mFirstRunPageDelegateMock); |
| } |
| |
| @After |
| public void tearDown() { |
| FirstRunUtils.setDisableDelayOnExitFreForTest(false); |
| EnterpriseInfo.setInstanceForTest(null); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenAddingAccountDynamically() { |
| launchActivityWithFragment(); |
| Assert.assertFalse( |
| mFragment.getView().findViewById(R.id.signin_fre_selected_account).isShown()); |
| onView(withText(R.string.signin_add_account_to_device)).check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_dismiss_button)).check(matches(isDisplayed())); |
| |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| |
| checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenAddingChildAccountDynamically() { |
| launchActivityWithFragment(); |
| onView(withText(R.string.signin_add_account_to_device)).check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_dismiss_button)).check(matches(isDisplayed())); |
| |
| mSigninTestRule.addAccount( |
| CHILD_ACCOUNT_EMAIL, CHILD_FULL_NAME, /* givenName= */ null, /* avatar= */ null); |
| |
| checkFragmentWithChildAccount(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenRemovingChildAccountDynamically() { |
| mSigninTestRule.addAccount( |
| CHILD_ACCOUNT_EMAIL, CHILD_FULL_NAME, /* givenName= */ null, /* avatar= */ null); |
| launchActivityWithFragment(); |
| |
| mSigninTestRule.removeAccount(CHILD_ACCOUNT_EMAIL); |
| |
| CriteriaHelper.pollUiThread(() -> { |
| return !mFragment.getView().findViewById(R.id.signin_fre_selected_account).isShown(); |
| }); |
| onView(withText(R.string.signin_add_account_to_device)).check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_dismiss_button)).check(matches(isDisplayed())); |
| onView(withId(R.id.signin_fre_footer)).check(matches(isDisplayed())); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenDefaultAccountIsRemoved() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, /*avatar=*/null); |
| mSigninTestRule.addAccount( |
| TEST_EMAIL2, /*fullName=*/null, /*givenName=*/null, /*avatar=*/null); |
| launchActivityWithFragment(); |
| |
| mSigninTestRule.removeAccount(TEST_EMAIL1); |
| |
| checkFragmentWithSelectedAccount(TEST_EMAIL2, /*fullName=*/null, /*givenName=*/null); |
| } |
| |
| @Test |
| @MediumTest |
| public void testRemovingAllAccountsDismissesAccountPickerDialog() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, /*avatar=*/null); |
| launchActivityWithFragment(); |
| onView(withText(TEST_EMAIL1)).perform(click()); |
| onView(withText(R.string.signin_account_picker_dialog_title)) |
| .inRoot(isDialog()) |
| .check(matches(isDisplayed())); |
| |
| mSigninTestRule.removeAccount(TEST_EMAIL1); |
| |
| onView(withText(R.string.signin_account_picker_dialog_title)).check(doesNotExist()); |
| onView(withText(R.string.signin_add_account_to_device)).check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_dismiss_button)).check(matches(isDisplayed())); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWithDefaultAccount() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| |
| launchActivityWithFragment(); |
| |
| checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1); |
| onView(withId(R.id.fre_browser_managed_by_organization)).check(matches(not(isDisplayed()))); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenCannotUseGooglePlayService() { |
| when(mExternalAuthUtilsMock.canUseGooglePlayServices()).thenReturn(false); |
| |
| launchActivityWithFragment(); |
| |
| CriteriaHelper.pollUiThread(() -> { |
| return !mFragment.getView().findViewById(R.id.signin_fre_selected_account).isShown(); |
| }); |
| ViewUtils.waitForView(withText(R.string.continue_button)); |
| onView(withId(R.id.signin_fre_dismiss_button)).check(matches(not(isDisplayed()))); |
| ViewUtils.waitForView(withId(R.id.signin_fre_footer)); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenSigninIsDisabledByPolicy() { |
| IdentityServicesProvider.setInstanceForTests(mIdentityServicesProviderMock); |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| when(IdentityServicesProvider.get().getSigninManager( |
| Profile.getLastUsedRegularProfile())) |
| .thenReturn(mSigninManagerMock); |
| }); |
| when(mSigninManagerMock.isSigninDisabledByPolicy()).thenReturn(true); |
| when(mPolicyLoadListenerMock.get()).thenReturn(true); |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| |
| launchActivityWithFragment(); |
| |
| checkFragmentWhenSigninIsDisabledByPolicy(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenSigninErrorOccurs() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| IdentityServicesProvider.setInstanceForTests(mIdentityServicesProviderMock); |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| when(IdentityServicesProvider.get().getSigninManager( |
| Profile.getLastUsedRegularProfile())) |
| .thenReturn(mSigninManagerMock); |
| // IdentityManager#getPrimaryAccountInfo() is called during this test flow by |
| // SigninFirstRunMediator. |
| when(IdentityServicesProvider.get().getIdentityManager( |
| Profile.getLastUsedRegularProfile())) |
| .thenReturn(mIdentityManagerMock); |
| }); |
| doAnswer(invocation -> { |
| SigninManager.SignInCallback callback = invocation.getArgument(1); |
| callback.onSignInAborted(); |
| return null; |
| }) |
| .when(mSigninManagerMock) |
| .signin(eq(AccountUtils.createAccountFromName(TEST_EMAIL1)), any()); |
| launchActivityWithFragment(); |
| checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1); |
| |
| final String continueAsText = mActivityTestRule.getActivity().getString( |
| R.string.sync_promo_continue_as, GIVEN_NAME1); |
| onView(withText(continueAsText)).perform(click()); |
| |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(true); |
| verify(mFirstRunPageDelegateMock, never()).advanceToNextPage(); |
| // TODO(crbug/1248090): For now we enable the buttons again to not block the users from |
| // continuing to the next page. Should show a dialog with the signin error. |
| checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenAddingAccountDynamicallyAndSigninIsDisabledByPolicy() { |
| IdentityServicesProvider.setInstanceForTests(mIdentityServicesProviderMock); |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| when(IdentityServicesProvider.get().getSigninManager( |
| Profile.getLastUsedRegularProfile())) |
| .thenReturn(mSigninManagerMock); |
| }); |
| when(mSigninManagerMock.isSigninDisabledByPolicy()).thenReturn(true); |
| when(mPolicyLoadListenerMock.get()).thenReturn(true); |
| launchActivityWithFragment(); |
| checkFragmentWhenSigninIsDisabledByPolicy(); |
| |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| |
| checkFragmentWhenSigninIsDisabledByPolicy(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testContinueButtonWhenCannotUseGooglePlayService() { |
| when(mExternalAuthUtilsMock.canUseGooglePlayServices()).thenReturn(false); |
| launchActivityWithFragment(); |
| CriteriaHelper.pollUiThread(() -> { |
| return !mFragment.getView().findViewById(R.id.signin_fre_selected_account).isShown(); |
| }); |
| |
| onView(withText(R.string.continue_button)).perform(click()); |
| |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(true); |
| verify(mFirstRunPageDelegateMock).advanceToNextPage(); |
| verify(mFirstRunPageDelegateMock, never()).recordFreProgressHistogram(anyInt()); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenChoosingAnotherAccount() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| mSigninTestRule.addAccount( |
| TEST_EMAIL2, /* fullName= */ null, /* givenName= */ null, /* avatar= */ null); |
| launchActivityWithFragment(); |
| onView(withText(TEST_EMAIL1)).perform(click()); |
| |
| onView(withText(TEST_EMAIL2)).inRoot(isDialog()).perform(click()); |
| |
| checkFragmentWithSelectedAccount(TEST_EMAIL2, /* fullName= */ null, /* givenName= */ null); |
| onView(withId(R.id.fre_browser_managed_by_organization)).check(matches(not(isDisplayed()))); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWithDefaultAccountWhenPolicyAvailableOnDevice() { |
| when(mPolicyLoadListenerMock.get()).thenReturn(true); |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| |
| launchActivityWithFragment(); |
| |
| checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1); |
| onView(withId(R.id.fre_browser_managed_by_organization)).check(matches(isDisplayed())); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWithChildAccount() { |
| mSigninTestRule.addAccount( |
| CHILD_ACCOUNT_EMAIL, CHILD_FULL_NAME, /* givenName= */ null, /* avatar= */ null); |
| |
| launchActivityWithFragment(); |
| |
| checkFragmentWithChildAccount(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testSigninWithDefaultAccount() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| launchActivityWithFragment(); |
| final String continueAsText = mActivityTestRule.getActivity().getString( |
| R.string.sync_promo_continue_as, GIVEN_NAME1); |
| |
| onView(withText(continueAsText)).perform(click()); |
| // ToS should be accepted right away, without waiting for the sign-in to complete. |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(true); |
| |
| CriteriaHelper.pollUiThread(() -> { |
| return IdentityServicesProvider.get() |
| .getIdentityManager(Profile.getLastUsedRegularProfile()) |
| .hasPrimaryAccount(ConsentLevel.SIGNIN); |
| }); |
| final CoreAccountInfo primaryAccount = |
| mSigninTestRule.getPrimaryAccount(ConsentLevel.SIGNIN); |
| Assert.assertEquals(TEST_EMAIL1, primaryAccount.getEmail()); |
| // Sign-in has completed, so the FRE should advance to the next page. |
| verify(mFirstRunPageDelegateMock).advanceToNextPage(); |
| verify(mFirstRunPageDelegateMock) |
| .recordFreProgressHistogram(MobileFreProgress.WELCOME_SIGNIN_WITH_DEFAULT_ACCOUNT); |
| } |
| |
| @Test |
| @MediumTest |
| public void testSigninWithNonDefaultAccount() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, /*avatar=*/null); |
| mSigninTestRule.addAccount( |
| TEST_EMAIL2, /*fullName=*/null, /*givenName=*/null, /*avatar=*/null); |
| launchActivityWithFragment(); |
| onView(withText(TEST_EMAIL1)).perform(click()); |
| onView(withText(TEST_EMAIL2)).inRoot(isDialog()).perform(click()); |
| final String continueAsText = mActivityTestRule.getActivity().getString( |
| R.string.sync_promo_continue_as, TEST_EMAIL2); |
| |
| ViewUtils.onViewWaiting(withText(continueAsText)).perform(click()); |
| |
| CriteriaHelper.pollUiThread(() -> { |
| return IdentityServicesProvider.get() |
| .getIdentityManager(Profile.getLastUsedRegularProfile()) |
| .hasPrimaryAccount(ConsentLevel.SIGNIN); |
| }); |
| final CoreAccountInfo primaryAccount = |
| mSigninTestRule.getPrimaryAccount(ConsentLevel.SIGNIN); |
| Assert.assertEquals(TEST_EMAIL2, primaryAccount.getEmail()); |
| verify(mFirstRunPageDelegateMock) |
| .recordFreProgressHistogram( |
| MobileFreProgress.WELCOME_SIGNIN_WITH_NON_DEFAULT_ACCOUNT); |
| } |
| |
| @Test |
| @MediumTest |
| public void testContinueButtonWithAnAccountOtherThanTheSignedInAccount() { |
| final CoreAccountInfo targetPrimaryAccount = |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| final CoreAccountInfo primaryAccount = mSigninTestRule.addTestAccountThenSignin(); |
| Assert.assertNotEquals("The primary account should be a different account!", |
| targetPrimaryAccount.getEmail(), primaryAccount.getEmail()); |
| launchActivityWithFragment(); |
| |
| final String continueAsText = mActivityTestRule.getActivity().getString( |
| R.string.sync_promo_continue_as, GIVEN_NAME1); |
| onView(withText(continueAsText)).perform(click()); |
| |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(true); |
| CriteriaHelper.pollUiThread(() -> { |
| return targetPrimaryAccount.equals( |
| IdentityServicesProvider.get() |
| .getIdentityManager(Profile.getLastUsedRegularProfile()) |
| .getPrimaryAccountInfo(ConsentLevel.SIGNIN)); |
| }); |
| verify(mFirstRunPageDelegateMock).advanceToNextPage(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testContinueButtonWithTheSignedInAccount() { |
| final CoreAccountInfo signedInAccount = |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| when(mIdentityManagerMock.getPrimaryAccountInfo(ConsentLevel.SIGNIN)) |
| .thenReturn(signedInAccount); |
| IdentityServicesProvider.setInstanceForTests(mIdentityServicesProviderMock); |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| when(IdentityServicesProvider.get().getSigninManager( |
| Profile.getLastUsedRegularProfile())) |
| .thenReturn(mSigninManagerMock); |
| // IdentityManager#getPrimaryAccountInfo() is called during this test flow by |
| // SigninFirstRunMediator. |
| when(IdentityServicesProvider.get().getIdentityManager( |
| Profile.getLastUsedRegularProfile())) |
| .thenReturn(mIdentityManagerMock); |
| }); |
| launchActivityWithFragment(); |
| |
| final String continueAsText = mActivityTestRule.getActivity().getString( |
| R.string.sync_promo_continue_as, GIVEN_NAME1); |
| onView(withText(continueAsText)).perform(click()); |
| |
| verify(mSigninManagerMock, never()).signin(any(), any()); |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(true); |
| verify(mFirstRunPageDelegateMock).advanceToNextPage(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testDismissButtonWhenUserIsSignedIn() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| final CoreAccountInfo primaryAccount = mSigninTestRule.addTestAccountThenSignin(); |
| Assert.assertNotEquals("The primary account should be a different account!", TEST_EMAIL1, |
| primaryAccount.getEmail()); |
| launchActivityWithFragment(); |
| |
| onView(withText(R.string.signin_fre_dismiss_button)).perform(click()); |
| |
| CriteriaHelper.pollUiThread(() -> { |
| return !IdentityServicesProvider.get() |
| .getIdentityManager(Profile.getLastUsedRegularProfile()) |
| .hasPrimaryAccount(ConsentLevel.SIGNIN); |
| }); |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(true); |
| verify(mFirstRunPageDelegateMock).advanceToNextPage(); |
| verify(mFirstRunPageDelegateMock) |
| .recordFreProgressHistogram(MobileFreProgress.WELCOME_DISMISS); |
| } |
| |
| @Test |
| @MediumTest |
| public void testDismissButtonWithDefaultAccount() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| launchActivityWithFragment(); |
| |
| onView(withText(R.string.signin_fre_dismiss_button)).perform(click()); |
| Assert.assertNull(mSigninTestRule.getPrimaryAccount(ConsentLevel.SIGNIN)); |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(true); |
| verify(mFirstRunPageDelegateMock).advanceToNextPage(); |
| verify(mFirstRunPageDelegateMock) |
| .recordFreProgressHistogram(MobileFreProgress.WELCOME_DISMISS); |
| } |
| |
| @Test |
| @MediumTest |
| public void testContinueButtonWithChildAccount() { |
| IdentityServicesProvider.setInstanceForTests(mIdentityServicesProviderMock); |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| when(IdentityServicesProvider.get().getSigninManager( |
| Profile.getLastUsedRegularProfile())) |
| .thenReturn(mSigninManagerMock); |
| }); |
| |
| mSigninTestRule.addAccount( |
| CHILD_ACCOUNT_EMAIL, CHILD_FULL_NAME, /* givenName= */ null, /* avatar= */ null); |
| launchActivityWithFragment(); |
| final String continueAsText = mActivityTestRule.getActivity().getString( |
| R.string.sync_promo_continue_as, CHILD_FULL_NAME); |
| |
| onView(withText(continueAsText)).perform(click()); |
| |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(true); |
| verify(mFirstRunPageDelegateMock).advanceToNextPage(); |
| |
| // Sign-in isn't processed by SigninFirstRunFragment for child accounts. |
| verify(mSigninManagerMock, never()).signin(any(), any()); |
| verify(mSigninManagerMock, never()).signinAndEnableSync(anyInt(), any(), any()); |
| } |
| |
| @Test |
| @MediumTest |
| public void testProgressSpinnerOnContinueButtonPress() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| IdentityServicesProvider.setInstanceForTests(mIdentityServicesProviderMock); |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| when(IdentityServicesProvider.get().getSigninManager( |
| Profile.getLastUsedRegularProfile())) |
| .thenReturn(mSigninManagerMock); |
| // IdentityManager#getPrimaryAccountInfo() is called during this test flow by |
| // SigninFirstRunMediator. |
| when(IdentityServicesProvider.get().getIdentityManager( |
| Profile.getLastUsedRegularProfile())) |
| .thenReturn(mIdentityManagerMock); |
| }); |
| launchActivityWithFragment(); |
| |
| final String continueAsText = mActivityTestRule.getActivity().getString( |
| R.string.sync_promo_continue_as, GIVEN_NAME1); |
| onView(withText(continueAsText)).perform(click()); |
| |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(true); |
| onView(withId(R.id.fre_signin_progress_spinner)).check(matches(isDisplayed())); |
| onView(withText(R.string.fre_signing_in)).check(matches(isDisplayed())); |
| onView(withText(R.string.fre_welcome)).check(matches(isDisplayed())); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| onView(withText(TEST_EMAIL1)).check(matches(not(isDisplayed()))); |
| onView(withText(FULL_NAME1)).check(matches(not(isDisplayed()))); |
| onView(withId(R.id.signin_fre_selected_account_expand_icon)) |
| .check(matches(not(isDisplayed()))); |
| onView(withText(continueAsText)).check(matches(not(isDisplayed()))); |
| onView(withText(R.string.signin_fre_dismiss_button)).check(matches(not(isDisplayed()))); |
| onView(withId(R.id.signin_fre_footer)).check(matches(not(isDisplayed()))); |
| |
| IdentityServicesProvider.setInstanceForTests(null); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenClickingOnTosLink() { |
| launchActivityWithFragment(); |
| |
| onView(withId(R.id.signin_fre_footer)).perform(clickOnTosLink()); |
| |
| verify(mFirstRunPageDelegateMock).showInfoPage(R.string.google_terms_of_service_url); |
| } |
| |
| @Test |
| @MediumTest |
| @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class) |
| public void testFragmentWhenClickingOnTosLinkInDarkMode(boolean nightModeEnabled) { |
| launchActivityWithFragment(); |
| |
| onView(withId(R.id.signin_fre_footer)).perform(clickOnTosLink()); |
| |
| verify(mFirstRunPageDelegateMock) |
| .showInfoPage(nightModeEnabled ? R.string.google_terms_of_service_dark_mode_url |
| : R.string.google_terms_of_service_url); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenClickingOnUmaDialogLink() { |
| launchActivityWithFragment(); |
| |
| clickOnUmaDialogLinkAndWait(); |
| |
| onView(withText(R.string.signin_fre_uma_dialog_title)) |
| .inRoot(isDialog()) |
| .check(matches(isDisplayed())); |
| onView(withId(R.id.fre_uma_dialog_switch)).inRoot(isDialog()).check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_uma_dialog_first_section_header)) |
| .inRoot(isDialog()) |
| .check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_uma_dialog_first_section_body)) |
| .inRoot(isDialog()) |
| .check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_uma_dialog_second_section_header)) |
| .inRoot(isDialog()) |
| .check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_uma_dialog_second_section_body)) |
| .inRoot(isDialog()) |
| .check(matches(isDisplayed())); |
| onView(withText(R.string.done)).check(matches(isDisplayed())); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenDismissingUmaDialog() { |
| launchActivityWithFragment(); |
| clickOnUmaDialogLinkAndWait(); |
| |
| onView(withText(R.string.done)).perform(click()); |
| |
| onView(withText(R.string.signin_fre_uma_dialog_title)).check(doesNotExist()); |
| } |
| |
| @Test |
| @MediumTest |
| public void testDismissButtonWhenAllowCrashUploadTurnedOff() { |
| launchActivityWithFragment(); |
| clickOnUmaDialogLinkAndWait(); |
| onView(withId(R.id.fre_uma_dialog_switch)).perform(click()); |
| onView(withText(R.string.done)).perform(click()); |
| |
| onView(withText(R.string.signin_fre_dismiss_button)).perform(click()); |
| |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(false); |
| verify(mFirstRunPageDelegateMock).advanceToNextPage(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testUmaDialogSwitchIsOffWhenAllowCrashUploadWasTurnedOffBefore() { |
| launchActivityWithFragment(); |
| clickOnUmaDialogLinkAndWait(); |
| onView(withId(R.id.fre_uma_dialog_switch)).check(matches(isChecked())).perform(click()); |
| onView(withText(R.string.done)).perform(click()); |
| |
| clickOnUmaDialogLinkAndWait(); |
| |
| onView(withId(R.id.fre_uma_dialog_switch)) |
| .check(matches(not(isChecked()))) |
| .perform(click()); |
| onView(withText(R.string.done)).perform(click()); |
| onView(withText(R.string.signin_fre_dismiss_button)).perform(click()); |
| |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(true); |
| verify(mFirstRunPageDelegateMock).advanceToNextPage(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testContinueButtonWhenAllowCrashUploadTurnedOff() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| launchActivityWithFragment(); |
| clickOnUmaDialogLinkAndWait(); |
| onView(withId(R.id.fre_uma_dialog_switch)).perform(click()); |
| onView(withText(R.string.done)).perform(click()); |
| |
| final String continueAsText = mActivityTestRule.getActivity().getString( |
| R.string.sync_promo_continue_as, GIVEN_NAME1); |
| onView(withText(continueAsText)).perform(click()); |
| |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(false); |
| verify(mFirstRunPageDelegateMock).advanceToNextPage(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenAddingAnotherAccount() { |
| mSigninTestRule.setResultForNextAddAccountFlow(Activity.RESULT_OK, TEST_EMAIL2); |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| launchActivityWithFragment(); |
| |
| onView(withText(TEST_EMAIL1)).perform(click()); |
| onView(withText(R.string.signin_add_account_to_device)).perform(click()); |
| |
| checkFragmentWithSelectedAccount(TEST_EMAIL2, /* fullName= */ null, /* givenName= */ null); |
| verify(mFirstRunPageDelegateMock) |
| .recordFreProgressHistogram(MobileFreProgress.WELCOME_ADD_ACCOUNT); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenAddingDefaultAccount() { |
| mSigninTestRule.setResultForNextAddAccountFlow(Activity.RESULT_OK, TEST_EMAIL1); |
| launchActivityWithFragment(); |
| |
| onView(withText(R.string.signin_add_account_to_device)).perform(click()); |
| |
| checkFragmentWithSelectedAccount(TEST_EMAIL1, /* fullName= */ null, /* givenName= */ null); |
| verify(mFirstRunPageDelegateMock) |
| .recordFreProgressHistogram(MobileFreProgress.WELCOME_ADD_ACCOUNT); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenPolicyIsLoadedAfterNativeAndChildStatus() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| when(mPolicyLoadListenerMock.get()).thenReturn(null); |
| launchActivityWithFragment(); |
| checkFragmentWhenLoadingNativeAndPolicy(); |
| |
| // TODO(https://crbug.com/1346258): Use OneshotSupplierImpl instead. |
| when(mPolicyLoadListenerMock.get()).thenReturn(false); |
| verify(mPolicyLoadListenerMock, atLeastOnce()).onAvailable(mCallbackCaptor.capture()); |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| for (Callback<Boolean> callback : mCallbackCaptor.getAllValues()) { |
| callback.onResult(false); |
| } |
| }); |
| |
| checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1); |
| Assert.assertEquals("Policy loading should be the slowest", 1, |
| mHistogramTestRule.getHistogramValueCount( |
| "MobileFre.SlowestLoadPoint", LoadPoint.POLICY_LOAD)); |
| Assert.assertEquals("SlowestLoadpoint histogram should be counted only once", 1, |
| mHistogramTestRule.getHistogramTotalCount("MobileFre.SlowestLoadPoint")); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenNativeIsLoadedAfterPolicyAndChildStatus() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| TestThreadUtils.runOnUiThreadBlocking( |
| () -> { mNativeInitializationPromise = new Promise<>(); }); |
| launchActivityWithFragment(); |
| checkFragmentWhenLoadingNativeAndPolicy(); |
| |
| TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null)); |
| |
| checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1); |
| Assert.assertEquals("Native initialization should be the slowest", 1, |
| mHistogramTestRule.getHistogramValueCount( |
| "MobileFre.SlowestLoadPoint", LoadPoint.NATIVE_INITIALIZATION)); |
| Assert.assertEquals("SlowestLoadpoint histogram should be counted only once", 1, |
| mHistogramTestRule.getHistogramTotalCount("MobileFre.SlowestLoadPoint")); |
| verify(mFirstRunPageDelegateMock).recordNativeInitializedHistogram(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWhenChildStatusIsLoadedAfterNativeAndPolicy() { |
| mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null); |
| when(mChildAccountStatusListenerMock.get()).thenReturn(null); |
| launchActivityWithFragment(); |
| checkFragmentWhenLoadingNativeAndPolicy(); |
| |
| // TODO(https://crbug.com/1346258): Use OneshotSupplierImpl instead. |
| when(mChildAccountStatusListenerMock.get()).thenReturn(false); |
| verify(mChildAccountStatusListenerMock, atLeastOnce()) |
| .onAvailable(mCallbackCaptor.capture()); |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| for (Callback<Boolean> callback : mCallbackCaptor.getAllValues()) { |
| callback.onResult(false); |
| } |
| }); |
| |
| checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1); |
| Assert.assertEquals("Child status loading should be the slowest", 1, |
| mHistogramTestRule.getHistogramValueCount( |
| "MobileFre.SlowestLoadPoint", LoadPoint.CHILD_STATUS_LOAD)); |
| Assert.assertEquals("SlowestLoadpoint histogram should be counted only once", 1, |
| mHistogramTestRule.getHistogramTotalCount("MobileFre.SlowestLoadPoint")); |
| } |
| |
| @Test |
| @MediumTest |
| public void testNativePolicyAndChildStatusLoadMetricRecordedOnlyOnce() { |
| launchActivityWithFragment(); |
| verify(mFirstRunPageDelegateMock, timeout(CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL)) |
| .recordNativePolicyAndChildStatusLoadedHistogram(); |
| verify(mFirstRunPageDelegateMock).recordNativeInitializedHistogram(); |
| Assert.assertEquals("Native initialization should be the slowest", 1, |
| mHistogramTestRule.getHistogramValueCount( |
| "MobileFre.SlowestLoadPoint", LoadPoint.NATIVE_INITIALIZATION)); |
| |
| // Changing the activity orientation will create SigninFirstRunCoordinator again and call |
| // SigninFirstRunFragment.notifyCoordinatorWhenNativePolicyAndChildStatusAreLoaded() |
| ActivityTestUtils.rotateActivityToOrientation( |
| mActivityTestRule.getActivity(), Configuration.ORIENTATION_LANDSCAPE); |
| |
| // These histograms should not be recorded again. The call count should be the same as |
| // before as mockito does not reset invocation counts between consecutive verify calls. |
| verify(mFirstRunPageDelegateMock).recordNativePolicyAndChildStatusLoadedHistogram(); |
| verify(mFirstRunPageDelegateMock).recordNativeInitializedHistogram(); |
| Assert.assertEquals("Native initialization should be the slowest", 1, |
| mHistogramTestRule.getHistogramValueCount( |
| "MobileFre.SlowestLoadPoint", LoadPoint.NATIVE_INITIALIZATION)); |
| Assert.assertEquals("SlowestLoadpoint histogram should be counted only once", 1, |
| mHistogramTestRule.getHistogramTotalCount("MobileFre.SlowestLoadPoint")); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWithTosDialogBehaviorPolicy() throws Exception { |
| CallbackHelper callbackHelper = new CallbackHelper(); |
| doAnswer(invocation -> { |
| callbackHelper.notifyCalled(); |
| return null; |
| }) |
| .when(mFirstRunPageDelegateMock) |
| .exitFirstRun(); |
| when(mFirstRunPageDelegateMock.isLaunchedFromCct()).thenReturn(true); |
| mFakeEnterpriseInfo.initialize(new OwnedState( |
| /*isDeviceOwned=*/true, /*isProfileOwned=*/false)); |
| doAnswer(AdditionalAnswers.answerVoid( |
| (Callback<Boolean> callback) -> callback.onResult(true))) |
| .when(mPolicyLoadListenerMock) |
| .onAvailable(any()); |
| when(mPolicyLoadListenerMock.get()).thenReturn(true); |
| when(mFirstRunUtils.getCctTosDialogEnabled()).thenReturn(false); |
| launchActivityWithFragment(); |
| |
| callbackHelper.waitForFirst(); |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(false); |
| verify(mFirstRunPageDelegateMock).exitFirstRun(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragmentWithMetricsReportingDisabled() throws Exception { |
| when(mPolicyLoadListenerMock.get()).thenReturn(true); |
| when(mPrivacyPreferencesManagerMock.isUsageAndCrashReportingPermittedByPolicy()) |
| .thenReturn(false); |
| PrivacyPreferencesManagerImpl.setInstanceForTesting(mPrivacyPreferencesManagerMock); |
| launchActivityWithFragment(); |
| |
| onView(withText(R.string.signin_fre_dismiss_button)).perform(click()); |
| |
| verify(mFirstRunPageDelegateMock).acceptTermsOfService(false); |
| verify(mFirstRunPageDelegateMock).advanceToNextPage(); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragment_WelcomeToChrome() { |
| FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting( |
| VariationsGroup.WELCOME_TO_CHROME); |
| TestThreadUtils.runOnUiThreadBlocking( |
| () -> { mNativeInitializationPromise = new Promise<>(); }); |
| launchActivityWithFragment(); |
| onView(withId(R.id.fre_native_and_policy_load_progress_spinner)) |
| .check(matches(isDisplayed())); |
| onView(withText(R.string.fre_welcome)).check(matches(isDisplayed())); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| |
| TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null)); |
| |
| onView(withText(R.string.fre_welcome)).check(matches(isDisplayed())); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragment_WelcomeToChrome_MostOutOfChrome() { |
| FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting( |
| VariationsGroup.WELCOME_TO_CHROME_MOST_OUT_OF_CHROME); |
| TestThreadUtils.runOnUiThreadBlocking( |
| () -> { mNativeInitializationPromise = new Promise<>(); }); |
| launchActivityWithFragment(); |
| onView(withId(R.id.fre_native_and_policy_load_progress_spinner)) |
| .check(matches(isDisplayed())); |
| onView(withId(R.id.title)).check(matches(not(isDisplayed()))); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| |
| TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null)); |
| |
| onView(withText(R.string.fre_welcome)).check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_subtitle_variation_1)).check(matches(isDisplayed())); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragment_WelcomeToChrome_StrongestSecurity() { |
| FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting( |
| VariationsGroup.WELCOME_TO_CHROME_STRONGEST_SECURITY); |
| TestThreadUtils.runOnUiThreadBlocking( |
| () -> { mNativeInitializationPromise = new Promise<>(); }); |
| launchActivityWithFragment(); |
| onView(withId(R.id.title)).check(matches(not(isDisplayed()))); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| |
| TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null)); |
| |
| onView(withText(R.string.fre_welcome)).check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_subtitle_variation_2)).check(matches(isDisplayed())); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragment_WelcomeToChrome_EasierAcrossDevices() { |
| FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting( |
| VariationsGroup.WELCOME_TO_CHROME_EASIER_ACROSS_DEVICES); |
| TestThreadUtils.runOnUiThreadBlocking( |
| () -> { mNativeInitializationPromise = new Promise<>(); }); |
| launchActivityWithFragment(); |
| onView(withId(R.id.fre_native_and_policy_load_progress_spinner)) |
| .check(matches(isDisplayed())); |
| onView(withId(R.id.title)).check(matches(not(isDisplayed()))); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| |
| TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null)); |
| |
| onView(withText(R.string.fre_welcome)).check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_subtitle_variation_3)).check(matches(isDisplayed())); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragment_MostOutOfChrome() { |
| FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting( |
| VariationsGroup.MOST_OUT_OF_CHROME); |
| TestThreadUtils.runOnUiThreadBlocking( |
| () -> { mNativeInitializationPromise = new Promise<>(); }); |
| launchActivityWithFragment(); |
| onView(withId(R.id.fre_native_and_policy_load_progress_spinner)) |
| .check(matches(isDisplayed())); |
| onView(withId(R.id.title)).check(matches(not(isDisplayed()))); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| |
| TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null)); |
| |
| onView(withText(R.string.signin_fre_title_variation_1)).check(matches(isDisplayed())); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| } |
| |
| @Test |
| @MediumTest |
| public void testFragment_MakeChromeYourOwn() { |
| FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting( |
| VariationsGroup.MAKE_CHROME_YOUR_OWN); |
| TestThreadUtils.runOnUiThreadBlocking( |
| () -> { mNativeInitializationPromise = new Promise<>(); }); |
| launchActivityWithFragment(); |
| onView(withId(R.id.fre_native_and_policy_load_progress_spinner)) |
| .check(matches(isDisplayed())); |
| onView(withId(R.id.title)).check(matches(not(isDisplayed()))); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| |
| TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null)); |
| |
| onView(withText(R.string.signin_fre_title_variation_2)).check(matches(isDisplayed())); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| } |
| |
| private void checkFragmentWithSelectedAccount(String email, String fullName, String givenName) { |
| CriteriaHelper.pollUiThread( |
| mFragment.getView().findViewById(R.id.signin_fre_selected_account)::isShown); |
| verify(mFirstRunPageDelegateMock).recordNativePolicyAndChildStatusLoadedHistogram(); |
| final DisplayableProfileData profileData = |
| new DisplayableProfileData(email, mock(Drawable.class), fullName, givenName, true); |
| onView(withText(R.string.fre_welcome)).check(matches(isDisplayed())); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| onView(withText(email)).check(matches(isDisplayed())); |
| if (fullName != null) { |
| onView(withText(fullName)).check(matches(isDisplayed())); |
| } |
| onView(withId(R.id.signin_fre_selected_account_expand_icon)).check(matches(isDisplayed())); |
| final String continueAsText = mFragment.getString( |
| R.string.sync_promo_continue_as, profileData.getGivenNameOrFullNameOrEmail()); |
| onView(withText(continueAsText)).check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_dismiss_button)).check(matches(isDisplayed())); |
| onView(withId(R.id.signin_fre_footer)).check(matches(isDisplayed())); |
| } |
| |
| private void checkFragmentWhenLoadingNativeAndPolicy() { |
| onView(withId(R.id.fre_native_and_policy_load_progress_spinner)) |
| .check(matches(isDisplayed())); |
| onView(withText(R.string.fre_welcome)).check(matches(isDisplayed())); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| onView(withText(TEST_EMAIL1)).check(matches(not(isDisplayed()))); |
| onView(withText(FULL_NAME1)).check(matches(not(isDisplayed()))); |
| onView(withId(R.id.signin_fre_selected_account_expand_icon)) |
| .check(matches(not(isDisplayed()))); |
| final String continueAsText = mActivityTestRule.getActivity().getString( |
| R.string.sync_promo_continue_as, GIVEN_NAME1); |
| onView(withText(continueAsText)).check(matches(not(isDisplayed()))); |
| onView(withText(R.string.signin_fre_dismiss_button)).check(matches(not(isDisplayed()))); |
| onView(withId(R.id.signin_fre_footer)).check(matches(not(isDisplayed()))); |
| verify(mPolicyLoadListenerMock, atLeastOnce()).onAvailable(notNull()); |
| } |
| |
| private void checkFragmentWithChildAccount() { |
| CriteriaHelper.pollUiThread( |
| mFragment.getView().findViewById(R.id.signin_fre_selected_account)::isShown); |
| verify(mFirstRunPageDelegateMock).recordNativePolicyAndChildStatusLoadedHistogram(); |
| onView(withText(R.string.fre_welcome)).check(matches(isDisplayed())); |
| onView(withId(R.id.subtitle)).check(matches(not(isDisplayed()))); |
| Assert.assertFalse( |
| mFragment.getView().findViewById(R.id.signin_fre_selected_account).isEnabled()); |
| onView(withText(CHILD_ACCOUNT_EMAIL)).check(matches(isDisplayed())); |
| onView(withText(CHILD_FULL_NAME)).check(matches(isDisplayed())); |
| onView(withId(R.id.signin_fre_selected_account_expand_icon)) |
| .check(matches(not(isDisplayed()))); |
| final String continueAsText = |
| mFragment.getString(R.string.sync_promo_continue_as, CHILD_FULL_NAME); |
| onView(withText(continueAsText)).check(matches(isDisplayed())); |
| onView(withId(R.id.signin_fre_footer)).check(matches(isDisplayed())); |
| onView(withText(R.string.signin_fre_dismiss_button)).check(matches(not(isDisplayed()))); |
| onView(withId(R.id.fre_browser_managed_by_organization)).check(matches(not(isDisplayed()))); |
| } |
| |
| private void checkFragmentWhenSigninIsDisabledByPolicy() { |
| CriteriaHelper.pollUiThread(() -> { |
| return !mFragment.getView().findViewById(R.id.signin_fre_selected_account).isShown(); |
| }); |
| verify(mFirstRunPageDelegateMock).recordNativePolicyAndChildStatusLoadedHistogram(); |
| ViewUtils.waitForView(withId(R.id.fre_browser_managed_by_organization)); |
| ViewUtils.waitForView(withText(R.string.continue_button)); |
| ViewUtils.waitForView(withId(R.id.signin_fre_footer)); |
| onView(withId(R.id.signin_fre_dismiss_button)).check(matches(not(isDisplayed()))); |
| } |
| |
| private void launchActivityWithFragment() { |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| ((BlankUiTestActivity) mActivityTestRule.getActivity()) |
| .getSupportFragmentManager() |
| .beginTransaction() |
| .add(android.R.id.content, mFragment) |
| .commit(); |
| }); |
| // Wait for fragment to be added to the activity. |
| CriteriaHelper.pollUiThread(() -> mFragment.isResumed()); |
| |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| // Replace all the progress bars with dummies. Currently the progress bar cannot be |
| // stopped otherwise due to some espresso issues (crbug/1115067). |
| ProgressBar nativeAndPolicyProgressBar = mFragment.getView().findViewById( |
| R.id.fre_native_and_policy_load_progress_spinner); |
| nativeAndPolicyProgressBar.setIndeterminateDrawable(new ColorDrawable( |
| SemanticColorUtils.getDefaultBgColor(mFragment.getContext()))); |
| ProgressBar signinProgressSpinner = |
| mFragment.getView().findViewById(R.id.fre_signin_progress_spinner); |
| signinProgressSpinner.setIndeterminateDrawable(new ColorDrawable( |
| SemanticColorUtils.getDefaultBgColor(mFragment.getContext()))); |
| }); |
| } |
| |
| /** |
| * The dialog does not open instantly, and if we do not wait we get a small percentage of |
| * flakes. See https://crbug.com/1343519. |
| */ |
| private void clickOnUmaDialogLinkAndWait() { |
| onView(withId(R.id.signin_fre_footer)).perform(clickOnUmaDialogLink()); |
| ViewUtils.onViewWaiting(withText(R.string.done)).check(matches(isDisplayed())); |
| } |
| |
| private ViewAction clickOnUmaDialogLink() { |
| return ViewUtils.clickOnClickableSpan(1); |
| } |
| |
| private ViewAction clickOnTosLink() { |
| return ViewUtils.clickOnClickableSpan(0); |
| } |
| } |