blob: d0c17047cc967a2c88f9dc71a38c9dc8abbac3a9 [file] [log] [blame]
// 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.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
import static org.chromium.content_public.browser.test.util.TestThreadUtils.runOnUiThreadBlocking;
import static org.chromium.ui.test.util.UiRestriction.RESTRICTION_TYPE_PHONE;
import android.view.View;
import androidx.test.filters.MediumTest;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
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.JniMocker;
import org.chromium.base.test.util.Restriction;
import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
import org.chromium.chrome.browser.autofill.prefeditor.EditorDialog;
import org.chromium.chrome.browser.autofill.settings.AddressEditor;
import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge;
import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge.AddressField;
import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge.AddressUiComponent;
import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridgeJni;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.payments.AutofillAddress;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
import org.chromium.chrome.browser.sync.SyncService;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
import org.chromium.components.signin.base.CoreAccountInfo;
import org.chromium.components.signin.identitymanager.IdentityManager;
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.HashSet;
import java.util.List;
/**
* These tests render screenshots of the {@link AddressEditor} 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_ENABLE_SUPPORT_FOR_HONORIFIC_PREFIXES,
ChromeFeatureList.AUTOFILL_ADDRESS_PROFILE_SAVE_PROMPT_NICKNAME_SUPPORT})
@Restriction({RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
public class AddressEditorRenderTest extends BlankUiTestActivityTestCase {
private static final String USER_EMAIL = "example@gmail.com";
private static final List<AddressUiComponent> SUPPORTED_ADDRESS_FIELDS = List.of(
new AddressUiComponent(AddressField.RECIPIENT, "Name", true, true),
new AddressUiComponent(AddressField.ORGANIZATION, "Company", false, true),
new AddressUiComponent(AddressField.STREET_ADDRESS, "Street address", true, true),
new AddressUiComponent(AddressField.LOCALITY, "City", true, true),
new AddressUiComponent(AddressField.ADMIN_AREA, "State", true, false),
new AddressUiComponent(AddressField.POSTAL_CODE, "ZIP", true, false));
private static final AutofillProfile sLocalProfile = new AutofillProfile("", true,
Source.LOCAL_OR_SYNCABLE, /*honorific prefix=*/"", "Seb Doe", "Google", "111 First St",
"CA", "Los Angeles", "", "90291", "", "US", "650-253-0000", "first@gmail.com", "en-US");
private static final AutofillProfile sAccountProfile = new AutofillProfile("", true,
Source.ACCOUNT, /*honorific prefix=*/"", "Seb Doe", "Google", "111 First St", "CA",
"Los Angeles", "", "90291", "", "US", "650-253-0000", "first@gmail.com", "en-US");
@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 TestRule mProcessor = new Features.JUnitProcessor();
@Rule
public JniMocker mJniMocker = new JniMocker();
@Mock
private AutofillProfileBridge.Natives mAutofillProfileBridgeJni;
@Mock
private PhoneNumberUtil.Natives mPhoneNumberUtilJni;
@Mock
private IdentityServicesProvider mIdentityServicesProvider;
@Mock
private IdentityManager mIdentityManager;
@Mock
private SyncService mSyncService;
@Mock
private PersonalDataManager mPersonalDataManager;
@Mock
private Profile mProfile;
@Mock
private AddressEditor.Delegate mDelegate;
private final CoreAccountInfo mAccountInfo =
CoreAccountInfo.createFromEmailAndGaiaId(USER_EMAIL, "gaia_id");
public AddressEditorRenderTest(boolean nightModeEnabled) {
NightModeTestUtils.setUpNightModeForBlankUiTestActivity(nightModeEnabled);
mRenderTestRule.setNightModeEnabled(nightModeEnabled);
}
@Before
@Override
public void setUpTest() throws Exception {
MockitoAnnotations.initMocks(this);
mJniMocker.mock(AutofillProfileBridgeJni.TEST_HOOKS, mAutofillProfileBridgeJni);
mJniMocker.mock(PhoneNumberUtilJni.TEST_HOOKS, mPhoneNumberUtilJni);
doAnswer(invocation -> {
List<Integer> requiredFields = (List<Integer>) invocation.getArguments()[1];
requiredFields.addAll(List.of(AddressField.RECIPIENT, AddressField.LOCALITY,
AddressField.DEPENDENT_LOCALITY, AddressField.POSTAL_CODE));
return null;
})
.when(mAutofillProfileBridgeJni)
.getRequiredFields(anyString(), anyList());
runOnUiThreadBlocking(() -> {
when(mSyncService.isSyncFeatureEnabled()).thenReturn(false);
when(mSyncService.getSelectedTypes()).thenReturn(new HashSet());
SyncService.overrideForTests(mSyncService);
when(mPersonalDataManager.isCountryEligibleForAccountStorage(anyString()))
.thenReturn(true);
PersonalDataManager.setInstanceForTesting(mPersonalDataManager);
Profile.setLastUsedProfileForTesting(mProfile);
IdentityServicesProvider.setInstanceForTests(mIdentityServicesProvider);
when(mIdentityServicesProvider.getIdentityManager(mProfile))
.thenReturn(mIdentityManager);
when(mIdentityManager.getPrimaryAccountInfo(anyInt())).thenReturn(mAccountInfo);
});
doAnswer(invocation -> { return (String) invocation.getArguments()[0]; })
.when(mPhoneNumberUtilJni)
.formatForDisplay(anyString(), anyString());
doAnswer(invocation -> { return (String) invocation.getArguments()[0]; })
.when(mPhoneNumberUtilJni)
.formatForResponse(anyString());
when(mPhoneNumberUtilJni.isPossibleNumber(anyString(), anyString())).thenReturn(true);
setUpAddressUiComponents(SUPPORTED_ADDRESS_FIELDS);
super.setUpTest();
}
@AfterClass
public static void tearDownClass() throws Exception {
runOnUiThreadBlocking(NightModeTestUtils::tearDownNightModeForBlankUiTestActivity);
}
private void setUpAddressUiComponents(List<AddressUiComponent> addressUiComponents) {
doAnswer(invocation -> {
List<Integer> componentIds = (List<Integer>) invocation.getArguments()[3];
List<String> componentNames = (List<String>) invocation.getArguments()[4];
List<Integer> componentRequired = (List<Integer>) invocation.getArguments()[5];
List<Integer> componentLength = (List<Integer>) invocation.getArguments()[6];
for (AddressUiComponent component : addressUiComponents) {
componentIds.add(component.id);
componentNames.add(component.label);
componentRequired.add(component.isRequired ? 1 : 0);
componentLength.add(component.isFullLine ? 1 : 0);
}
return "EN";
})
.when(mAutofillProfileBridgeJni)
.getAddressUiComponents(anyString(), anyString(), anyInt(), anyList(), anyList(),
anyList(), anyList());
}
@Test
@MediumTest
@Feature({"RenderTest"})
public void editNewAddressProfile() throws Exception {
View editor = runOnUiThreadBlocking(() -> {
EditorDialog dialog =
new EditorDialog(getActivity(), /*deleteRunnable=*/null, mProfile);
AddressEditor addressEditor = new AddressEditor(dialog, mDelegate, /*saveToDisk=*/false,
/*isUpdate=*/false, /*isMigrationToAccount=*/false);
addressEditor.showEditorDialog();
return dialog.getDataViewForTest();
});
mRenderTestRule.render(editor, "edit_new_address_profile");
}
@Test
@MediumTest
@Feature({"RenderTest"})
public void editNewAccountAddressProfile() throws Exception {
View editor = runOnUiThreadBlocking(() -> {
when(mPersonalDataManager.isEligibleForAddressAccountStorage()).thenReturn(true);
EditorDialog dialog =
new EditorDialog(getActivity(), /*deleteRunnable=*/null, mProfile);
AddressEditor addressEditor = new AddressEditor(dialog, mDelegate, /*saveToDisk=*/false,
/*isUpdate=*/false, /*isMigrationToAccount=*/false);
addressEditor.showEditorDialog();
return dialog.getDataViewForTest();
});
mRenderTestRule.render(editor, "edit_new_account_address_profile");
}
@Test
@MediumTest
@Feature({"RenderTest"})
public void editLocalOrSyncableAddressProfile() throws Exception {
View editor = runOnUiThreadBlocking(() -> {
when(mPersonalDataManager.isEligibleForAddressAccountStorage()).thenReturn(true);
EditorDialog dialog =
new EditorDialog(getActivity(), /*deleteRunnable=*/null, mProfile);
AddressEditor addressEditor = new AddressEditor(dialog, mDelegate,
new AutofillAddress(getActivity(), sLocalProfile), /*saveToDisk=*/false,
/*isUpdate=*/false, /*isMigrationToAccount=*/false);
addressEditor.showEditorDialog();
return dialog.getDataViewForTest();
});
mRenderTestRule.render(editor, "edit_local_or_syncable_address_profile");
}
@Test
@MediumTest
@Feature({"RenderTest"})
public void editAccountAddressProfile() throws Exception {
View editor = runOnUiThreadBlocking(() -> {
when(mPersonalDataManager.isEligibleForAddressAccountStorage()).thenReturn(true);
EditorDialog dialog =
new EditorDialog(getActivity(), /*deleteRunnable=*/null, mProfile);
AddressEditor addressEditor = new AddressEditor(dialog, mDelegate,
new AutofillAddress(getActivity(), sAccountProfile), /*saveToDisk=*/false,
/*isUpdate=*/false, /*isMigrationToAccount=*/false);
addressEditor.showEditorDialog();
return dialog.getDataViewForTest();
});
mRenderTestRule.render(editor, "edit_account_address_profile");
}
@Test
@MediumTest
@Feature({"RenderTest"})
public void migrateLocalOrSyncableAddressProfile() throws Exception {
View editor = runOnUiThreadBlocking(() -> {
when(mPersonalDataManager.isEligibleForAddressAccountStorage()).thenReturn(true);
EditorDialog dialog =
new EditorDialog(getActivity(), /*deleteRunnable=*/null, mProfile);
AddressEditor addressEditor = new AddressEditor(dialog, mDelegate,
new AutofillAddress(getActivity(), sLocalProfile), /*saveToDisk=*/false,
/*isUpdate=*/false, /*isMigrationToAccount=*/true);
addressEditor.showEditorDialog();
return dialog.getDataViewForTest();
});
mRenderTestRule.render(editor, "migrate_local_or_syncable_address_profile");
}
}