// Copyright 2016 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.payments;
import androidx.test.filters.MediumTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.autofill.AutofillTestHelper;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.payments.PaymentRequestTestRule.AppPresence;
import org.chromium.chrome.browser.payments.PaymentRequestTestRule.FactorySpeed;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.R;
import org.chromium.components.autofill.AutofillProfile;
import java.util.ArrayList;
import java.util.concurrent.TimeoutException;
/**
* A payment integration test for a merchant that requests contact details and a user that has
* multiple contact detail options.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class PaymentRequestMultipleContactDetailsTest {
@Rule
public PaymentRequestTestRule mPaymentRequestTestRule =
new PaymentRequestTestRule("payment_request_contact_details_test.html");
private static final AutofillProfile INCOMPLETE_PROFILE_NO_PHONE =
AutofillProfile.builder()
.setFullName("Bart Simpson")
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.setEmailAddress("[email protected]")
.build();
private static final AutofillProfile INCOMPLETE_PROFILE_NO_EMAIL =
AutofillProfile.builder()
.setFullName("Homer Simpson")
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.setPhoneNumber("555 123-4567")
.build();
private static final AutofillProfile COMPLETE_PROFILE_1 =
AutofillProfile.builder()
.setFullName("Lisa Simpson")
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.setPhoneNumber("555 123-4567")
.setEmailAddress("[email protected]")
.build();
private static final AutofillProfile COMPLETE_PROFILE_2 =
AutofillProfile.builder()
.setFullName("Maggie Simpson")
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.setPhoneNumber("555 123-4567")
.setEmailAddress("[email protected]")
.build();
private static final AutofillProfile INCOMPLETE_PROFILE_NO_PHONE_OR_EMAIL =
AutofillProfile.builder()
.setFullName("Marge Simpson")
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.build();
private static final AutofillProfile INCOMPLETE_PROFILE_NO_NAME =
AutofillProfile.builder()
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.setPhoneNumber("555 123-4567")
.setEmailAddress("[email protected]")
.build();
// These profiles are used to test the dedupe of subset suggestions. They are based on
// The Lisa Simpson profile.
private static final AutofillProfile DUPLICATE_PROFILE_WITH_NO_NAME =
AutofillProfile.builder()
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.setPhoneNumber("555 123-4567")
.setEmailAddress("[email protected]")
.build();
private static final AutofillProfile DUPLICATE_PROFILE_WITH_NO_PHONE =
AutofillProfile.builder()
.setFullName("Lisa Simpson")
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.setEmailAddress("[email protected]")
.build();
private static final AutofillProfile DUPLICATE_PROFILE_WITH_NO_EMAIL =
AutofillProfile.builder()
.setFullName("Lisa Simpson")
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.setPhoneNumber("555 123-4567")
.build();
private static final AutofillProfile DUPLICATE_PROFILE_WITH_NO_PHONE_OR_EMAIL =
AutofillProfile.builder()
.setFullName("Lisa Simpson")
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.build();
// This profile is a duplicate except that its email address is a superset of the original
// profile (that is, the original profile's email is a suffix of this one).
private static final AutofillProfile DUPLICATE_PROFILE_WITH_SUPERSET_EMAIL =
AutofillProfile.builder()
.setFullName("Lisa Simpson")
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.setPhoneNumber("555 123-4567")
.setEmailAddress("[email protected]")
.build();
private static final AutofillProfile DUPLICATE_PROFILE_WITH_MISMATCHED_CAPITALIZATION =
AutofillProfile.builder()
.setFullName("lisa simpson")
.setCompanyName("Acme Inc.")
.setStreetAddress("123 Main")
.setRegion("California")
.setLocality("Los Angeles")
.setPostalCode("90210")
.setCountryCode("US")
.setPhoneNumber("555 123-4567")
.setEmailAddress("[email protected]")
.build();
@Before
public void setUp() {
mPaymentRequestTestRule.addPaymentAppFactory(
"https://bobpay.test", AppPresence.HAVE_APPS, FactorySpeed.FAST_FACTORY);
}
private void setUpAutofillProfiles(
AutofillProfile[] profiles, int[] counts, int[] daysSinceLastUsed)
throws TimeoutException {
AutofillTestHelper helper = new AutofillTestHelper();
// Add the profiles.
ArrayList<String> guids = new ArrayList<>();
for (int i = 0; i < profiles.length; i++) {
guids.add(helper.setProfile(profiles[i]));
}
// Set up the profile use stats.
for (int i = 0; i < guids.size(); i++) {
helper.setProfileUseStatsForTesting(guids.get(i), counts[i], daysSinceLastUsed[i]);
}
}
/**
* Make sure the contact details suggestions are in the correct order and that only the top 4
* are shown. They should be ordered by frecency and complete contact details should be
* suggested first.
*/
@Test
@MediumTest
@Feature({"Payments"})
public void testContactDetailsSuggestionOrdering() throws TimeoutException {
// Set the use stats such that the profiles are in descending frecency score.
AutofillProfile[] profiles =
new AutofillProfile[] {
INCOMPLETE_PROFILE_NO_PHONE,
INCOMPLETE_PROFILE_NO_EMAIL,
COMPLETE_PROFILE_1,
COMPLETE_PROFILE_2,
INCOMPLETE_PROFILE_NO_PHONE_OR_EMAIL
};
int[] counts = new int[] {20, 15, 10, 5, 1};
int[] daysSinceLastUsed = new int[] {5, 5, 5, 5, 5};
setUpAutofillProfiles(profiles, counts, daysSinceLastUsed);
// The complete profiles should still come first, despite having a lower frecency score. The
// profile without either a phone or email should have been sorted to last, and is then not
// shown because we have more than PaymentUiService.SUGGESTIONS_LIMIT profiles.
mPaymentRequestTestRule.runJavaScriptAndWaitForUIEvent(
"buyWithMethods([{supportedMethods:'https://bobpay.test'}]);",
mPaymentRequestTestRule.getReadyForInput());
mPaymentRequestTestRule.clickInContactInfoAndWait(
R.id.payments_section, mPaymentRequestTestRule.getReadyForInput());
Assert.assertEquals(4, mPaymentRequestTestRule.getNumberOfContactDetailSuggestions());
Assert.assertEquals(
"Lisa Simpson\n555 123-4567\[email protected]",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(0));
Assert.assertEquals(
"Maggie Simpson\n555 123-4567\[email protected]",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(1));
Assert.assertEquals(
"Bart Simpson\[email protected]\nPhone number required",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(2));
Assert.assertEquals(
"Homer Simpson\n555 123-4567\nEmail required",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(3));
}
/**
* Make sure the information required message has been displayed for incomplete contact details
* correctly.
*/
@Test
@MediumTest
@Feature({"Payments"})
public void testContactDetailsEditRequiredMessage() throws TimeoutException {
AutofillProfile[] profiles =
new AutofillProfile[] {
INCOMPLETE_PROFILE_NO_PHONE,
INCOMPLETE_PROFILE_NO_EMAIL,
INCOMPLETE_PROFILE_NO_PHONE_OR_EMAIL,
INCOMPLETE_PROFILE_NO_NAME
};
int[] counts = new int[] {15, 10, 5, 1};
int[] daysSinceLastUsed = new int[] {5, 5, 5, 5};
setUpAutofillProfiles(profiles, counts, daysSinceLastUsed);
mPaymentRequestTestRule.runJavaScriptAndWaitForUIEvent(
"buyWithMethods([{supportedMethods:'https://bobpay.test'}]);",
mPaymentRequestTestRule.getReadyForInput());
mPaymentRequestTestRule.clickInContactInfoAndWait(
R.id.payments_section, mPaymentRequestTestRule.getReadyForInput());
Assert.assertEquals(4, mPaymentRequestTestRule.getNumberOfContactDetailSuggestions());
Assert.assertEquals(
"Bart Simpson\[email protected]\nPhone number required",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(0));
Assert.assertEquals(
"Homer Simpson\n555 123-4567\nEmail required",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(1));
Assert.assertEquals(
"555 123-4567\[email protected]\nName required",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(2));
Assert.assertEquals(
"Marge Simpson\nMore information required",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(3));
}
/** Makes sure that suggestions that are subsets of other fields (empty values) are deduped. */
@Test
@MediumTest
@Feature({"Payments"})
public void testContactDetailsDedupe_EmptyFields() throws TimeoutException {
// Add the original profile and a bunch of similar profiles with missing fields.
// Make sure the original profile is suggested last, to test that the suggestions are
// sorted by completeness.
AutofillProfile[] profiles =
new AutofillProfile[] {
COMPLETE_PROFILE_1,
DUPLICATE_PROFILE_WITH_NO_NAME,
DUPLICATE_PROFILE_WITH_NO_PHONE,
DUPLICATE_PROFILE_WITH_NO_EMAIL,
DUPLICATE_PROFILE_WITH_NO_PHONE_OR_EMAIL,
};
int[] counts = new int[] {1, 20, 15, 10, 5};
int[] daysSinceLastUsed = new int[] {4, 1, 2, 3, 4};
setUpAutofillProfiles(profiles, counts, daysSinceLastUsed);
mPaymentRequestTestRule.runJavaScriptAndWaitForUIEvent(
"buyWithMethods([{supportedMethods:'https://bobpay.test'}]);",
mPaymentRequestTestRule.getReadyForInput());
mPaymentRequestTestRule.clickInContactInfoAndWait(
R.id.payments_section, mPaymentRequestTestRule.getReadyForInput());
// Only the original profile with all the fields should be suggested.
Assert.assertEquals(1, mPaymentRequestTestRule.getNumberOfContactDetailSuggestions());
Assert.assertEquals(
"Lisa Simpson\n555 123-4567\[email protected]",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(0));
}
/**
* Makes sure that suggestions where some fields values are equal but with different case are
* deduped.
*/
@Test
@MediumTest
@Feature({"Payments"})
public void testContactDetailsDedupe_Capitalization() throws TimeoutException {
// Add the original profile and the one where the the name is not capitalized.
// Make sure the original profile is suggested first (no particular reason).
AutofillProfile[] profiles =
new AutofillProfile[] {
COMPLETE_PROFILE_1, DUPLICATE_PROFILE_WITH_MISMATCHED_CAPITALIZATION,
};
int[] counts = new int[] {15, 5};
int[] daysSinceLastUsed = new int[] {2, 5};
setUpAutofillProfiles(profiles, counts, daysSinceLastUsed);
mPaymentRequestTestRule.runJavaScriptAndWaitForUIEvent(
"buyWithMethods([{supportedMethods:'https://bobpay.test'}]);",
mPaymentRequestTestRule.getReadyForInput());
mPaymentRequestTestRule.clickInContactInfoAndWait(
R.id.payments_section, mPaymentRequestTestRule.getReadyForInput());
Assert.assertEquals(1, mPaymentRequestTestRule.getNumberOfContactDetailSuggestions());
Assert.assertEquals(
"Lisa Simpson\n555 123-4567\[email protected]",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(0));
}
/**
* Makes sure that suggestions where some fields values are subsets of the other are not
* deduped.
*/
@Test
@MediumTest
@Feature({"Payments"})
public void testContactDetailsDontDedupe_FieldSubset() throws TimeoutException {
// Add the original profile and the one where the email is a superset of the original.
// Make sure the one with the superset is suggested first, because to test the subset one
// needs to be added after.
AutofillProfile[] profiles =
new AutofillProfile[] {
COMPLETE_PROFILE_1, DUPLICATE_PROFILE_WITH_SUPERSET_EMAIL,
};
int[] counts = new int[] {15, 25};
int[] daysSinceLastUsed = new int[] {7, 5};
setUpAutofillProfiles(profiles, counts, daysSinceLastUsed);
mPaymentRequestTestRule.runJavaScriptAndWaitForUIEvent(
"buyWithMethods([{supportedMethods:'https://bobpay.test'}]);",
mPaymentRequestTestRule.getReadyForInput());
mPaymentRequestTestRule.clickInContactInfoAndWait(
R.id.payments_section, mPaymentRequestTestRule.getReadyForInput());
Assert.assertEquals(2, mPaymentRequestTestRule.getNumberOfContactDetailSuggestions());
Assert.assertEquals(
"Lisa Simpson\n555 123-4567\[email protected]",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(0));
Assert.assertEquals(
"Lisa Simpson\n555 123-4567\[email protected]",
mPaymentRequestTestRule.getContactDetailsSuggestionLabel(1));
}
}