// Copyright 2023 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.autofill;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.chromium.base.ThreadUtils.runOnUiThreadBlocking;
import android.view.View;
import androidx.test.filters.MediumTest;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.chromium.base.test.params.ParameterAnnotations;
import org.chromium.base.test.params.ParameterSet;
import org.chromium.base.test.params.ParameterizedRunner;
import org.chromium.base.test.util.DoNotBatch;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.Features.EnableFeatures;
import org.chromium.base.test.util.JniMocker;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
import org.chromium.chrome.browser.sync.SyncServiceFactory;
import org.chromium.components.autofill.AutofillProfile;
import org.chromium.components.signin.identitymanager.IdentityManager;
import org.chromium.components.sync.SyncService;
import org.chromium.ui.test.util.BlankUiTestActivityTestCase;
import org.chromium.ui.test.util.NightModeTestUtils;
import org.chromium.ui.test.util.RenderTestRule;
import org.chromium.ui.test.util.RenderTestRule.Component;
import java.util.List;
/**
* These tests render screenshots of the {@link SaveUpdateAddressProfilePrompt} and compare them to
* a gold standard.
*/
@DoNotBatch(reason = "The tests can't be batched because they run for different set-ups.")
@RunWith(ParameterizedRunner.class)
@EnableFeatures({ChromeFeatureList.AUTOFILL_ADDRESS_PROFILE_SAVE_PROMPT_NICKNAME_SUPPORT})
public class SaveUpdateAddressProfilePromptRenderTest extends BlankUiTestActivityTestCase {
private static final long NATIVE_SAVE_UPDATE_ADDRESS_PROFILE_PROMPT_CONTROLLER = 100L;
@ParameterAnnotations.ClassParameter
private static List<ParameterSet> sClassParams =
new NightModeTestUtils.NightModeParams().getParameters();
@Rule
public final RenderTestRule mRenderTestRule =
RenderTestRule.Builder.withPublicCorpus()
.setRevision(0)
.setBugComponent(Component.UI_BROWSER_AUTOFILL)
.build();
@Rule public JniMocker mJniMocker = new JniMocker();
@Mock private SaveUpdateAddressProfilePromptController.Natives mPromptControllerJni;
@Mock private AutofillProfileBridge.Natives mAutofillProfileBridgeJni;
@Mock private PersonalDataManager mPersonalDataManager;
@Mock private Profile mProfile;
@Mock private IdentityServicesProvider mIdentityServicesProvider;
@Mock private IdentityManager mIdentityManager;
@Mock private SyncService mSyncService;
private SaveUpdateAddressProfilePromptController mPromptController;
private SaveUpdateAddressProfilePrompt mPrompt;
public SaveUpdateAddressProfilePromptRenderTest(boolean nightModeEnabled) {
NightModeTestUtils.setUpNightModeForBlankUiTestActivity(nightModeEnabled);
mRenderTestRule.setNightModeEnabled(nightModeEnabled);
}
@Before
@Override
public void setUpTest() throws Exception {
MockitoAnnotations.initMocks(this);
runOnUiThreadBlocking(
() -> {
PersonalDataManagerFactory.setInstanceForTesting(mPersonalDataManager);
when(mPersonalDataManager.getDefaultCountryCodeForNewAddress())
.thenReturn("US");
SyncServiceFactory.setInstanceForTesting(mSyncService);
IdentityServicesProvider.setInstanceForTests(mIdentityServicesProvider);
when(mIdentityServicesProvider.getIdentityManager(any()))
.thenReturn(mIdentityManager);
});
mPromptController =
SaveUpdateAddressProfilePromptController.create(
NATIVE_SAVE_UPDATE_ADDRESS_PROFILE_PROMPT_CONTROLLER);
mJniMocker.mock(
SaveUpdateAddressProfilePromptControllerJni.TEST_HOOKS, mPromptControllerJni);
mJniMocker.mock(AutofillProfileBridgeJni.TEST_HOOKS, mAutofillProfileBridgeJni);
super.setUpTest();
}
@After
@Override
public void tearDownTest() throws Exception {
runOnUiThreadBlocking(mPrompt::dismiss);
super.tearDownTest();
}
@AfterClass
public static void tearDownClass() throws Exception {
runOnUiThreadBlocking(NightModeTestUtils::tearDownNightModeForBlankUiTestActivity);
}
@Test
@MediumTest
@Feature({"RenderTest"})
public void saveLocalOrSyncAddress() throws Exception {
View dialogView =
runOnUiThreadBlocking(
() -> {
mPrompt =
new SaveUpdateAddressProfilePrompt(
mPromptController,
getActivity().getModalDialogManager(),
getActivity(),
mProfile,
AutofillProfile.builder().build(),
/* isUpdate= */ false,
/* isMigrationToAccount= */ false);
mPrompt.setDialogDetails(
/* title= */ "Dialog title",
/* positiveButtonText= */ "Accept",
/* negativeButtonText= */ "Cancel");
mPrompt.setSaveOrMigrateDetails(
/* address= */ "321 Spear Street",
/* email= */ "[email protected]",
/* phone= */ "+0000000000000");
mPrompt.show();
return mPrompt.getDialogViewForTesting();
});
mRenderTestRule.render(dialogView, "save_local_or_sync_address");
}
@Test
@MediumTest
@Feature({"RenderTest"})
public void saveAccountAddress() throws Exception {
View dialogView =
runOnUiThreadBlocking(
() -> {
mPrompt =
new SaveUpdateAddressProfilePrompt(
mPromptController,
getActivity().getModalDialogManager(),
getActivity(),
mProfile,
AutofillProfile.builder().build(),
/* isUpdate= */ false,
/* isMigrationToAccount= */ false);
mPrompt.setDialogDetails(
/* title= */ "Dialog title",
/* positiveButtonText= */ "Accept",
/* negativeButtonText= */ "Cancel");
mPrompt.setSaveOrMigrateDetails(
/* address= */ "321 Spear Street",
/* email= */ "[email protected]",
/* phone= */ "+0000000000000");
mPrompt.setSourceNotice(
getActivity()
.getString(
R.string
.autofill_address_will_be_saved_in_account_source_notice)
.replace("$1", "[email protected]"));
mPrompt.show();
return mPrompt.getDialogViewForTesting();
});
mRenderTestRule.render(dialogView, "save_account_address");
}
@Test
@MediumTest
@Feature({"RenderTest"})
public void migrateAddress() throws Exception {
View dialogView =
runOnUiThreadBlocking(
() -> {
mPrompt =
new SaveUpdateAddressProfilePrompt(
mPromptController,
getActivity().getModalDialogManager(),
getActivity(),
mProfile,
AutofillProfile.builder().build(),
/* isUpdate= */ false,
/* isMigrationToAccount= */ true);
mPrompt.setDialogDetails(
/* title= */ "Dialog title",
/* positiveButtonText= */ "Accept",
/* negativeButtonText= */ "Cancel");
mPrompt.setSaveOrMigrateDetails(
/* address= */ "321 Spear Street",
/* email= */ "[email protected]",
/* phone= */ "+0000000000000");
mPrompt.setSourceNotice(
getActivity()
.getString(
R.string
.autofill_address_will_be_saved_in_account_source_notice)
.replace("$1", "[email protected]"));
mPrompt.show();
return mPrompt.getDialogViewForTesting();
});
mRenderTestRule.render(dialogView, "migrate_address");
}
@Test
@MediumTest
@Feature({"RenderTest"})
public void updateLocalOrSyncAddress() throws Exception {
View dialogView =
runOnUiThreadBlocking(
() -> {
mPrompt =
new SaveUpdateAddressProfilePrompt(
mPromptController,
getActivity().getModalDialogManager(),
getActivity(),
mProfile,
AutofillProfile.builder().build(),
/* isUpdate= */ true,
/* isMigrationToAccount= */ false);
mPrompt.setDialogDetails(
/* title= */ "Dialog title",
/* positiveButtonText= */ "Accept",
/* negativeButtonText= */ "Cancel");
mPrompt.setUpdateDetails(
/* subtitle= */ "Update your address",
/* oldDetails= */ "321 Spear Street",
/* newDetails= */ "123 Lake Street");
mPrompt.show();
return mPrompt.getDialogViewForTesting();
});
mRenderTestRule.render(dialogView, "update_local_or_sync_address");
}
@Test
@MediumTest
@Feature({"RenderTest"})
public void updateAccountAddress() throws Exception {
View dialogView =
runOnUiThreadBlocking(
() -> {
mPrompt =
new SaveUpdateAddressProfilePrompt(
mPromptController,
getActivity().getModalDialogManager(),
getActivity(),
mProfile,
AutofillProfile.builder().build(),
/* isUpdate= */ true,
/* isMigrationToAccount= */ false);
mPrompt.setDialogDetails(
/* title= */ "Dialog title",
/* positiveButtonText= */ "Accept",
/* negativeButtonText= */ "Cancel");
mPrompt.setUpdateDetails(
/* subtitle= */ "Update your address",
/* oldDetails= */ "321 Spear Street",
/* newDetails= */ "123 Lake Street");
mPrompt.setSourceNotice(
getActivity()
.getString(
R.string
.autofill_address_already_saved_in_account_source_notice)
.replace("$1", "[email protected]"));
mPrompt.show();
return mPrompt.getDialogViewForTesting();
});
mRenderTestRule.render(dialogView, "update_local_or_sync_address");
}
}