1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.chrome.browser.payments; 6 7 import androidx.test.filters.MediumTest; 8 9 import org.junit.Assert; 10 import org.junit.ClassRule; 11 import org.junit.Rule; 12 import org.junit.Test; 13 import org.junit.runner.RunWith; 14 15 import org.chromium.base.metrics.RecordHistogram; 16 import org.chromium.base.test.util.CommandLineFlags; 17 import org.chromium.base.test.util.Feature; 18 import org.chromium.chrome.R; 19 import org.chromium.chrome.browser.autofill.AutofillTestHelper; 20 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; 21 import org.chromium.chrome.browser.flags.ChromeSwitches; 22 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.AppPresence; 23 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.FactorySpeed; 24 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback; 25 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; 26 import org.chromium.ui.test.util.DisableAnimationsTestRule; 27 28 import java.util.ArrayList; 29 import java.util.concurrent.TimeoutException; 30 31 /** 32 * A payment integration test for a merchant that requests contact details and a user that has 33 * multiple contact detail options. 34 */ 35 @RunWith(ChromeJUnit4ClassRunner.class) 36 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) 37 public class PaymentRequestMultipleContactDetailsTest implements MainActivityStartCallback { 38 // Disable animations to reduce flakiness. 39 @ClassRule 40 public static DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule(); 41 42 @Rule 43 public PaymentRequestTestRule mPaymentRequestTestRule = 44 new PaymentRequestTestRule("payment_request_contact_details_test.html", this); 45 46 private static final AutofillProfile[] AUTOFILL_PROFILES = { 47 // 0 - Incomplete (no phone) profile. 48 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 49 "" /* honorific prefix */, "Bart Simpson", "Acme Inc.", "123 Main", 50 "California", "Los Angeles", "", "90210", "", "US", "", "bart@simpson.com", ""), 51 52 // 1 - Incomplete (no email) profile. 53 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 54 "" /* honorific prefix */, "Homer Simpson", "Acme Inc.", "123 Main", 55 "California", "Los Angeles", "", "90210", "", "US", "555 123-4567", "", ""), 56 57 // 2 - Complete profile. 58 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 59 "" /* honorific prefix */, "Lisa Simpson", "Acme Inc.", "123 Main", 60 "California", "Los Angeles", "", "90210", "", "US", "555 123-4567", 61 "lisa@simpson.com", ""), 62 63 // 3 - Complete profile. 64 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 65 "" /* honorific prefix */, "Maggie Simpson", "Acme Inc.", "123 Main", 66 "California", "Los Angeles", "", "90210", "", "US", "555 123-4567", 67 "maggie@simpson.com", ""), 68 69 // 4 - Incomplete (no phone and email) profile. 70 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 71 "" /* honorific prefix */, "Marge Simpson", "Acme Inc.", "123 Main", 72 "California", "Los Angeles", "", "90210", "", "US", "", "", ""), 73 74 // 5 - Incomplete (no name) profile. 75 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 76 "" /* honorific prefix */, "", "Acme Inc.", "123 Main", "California", 77 "Los Angeles", "", "90210", "", "US", "555 123-4567", "marge@simpson.com", ""), 78 79 // These profiles are used to test the dedupe of subset suggestions. They are based on 80 // The Lisa Simpson profile. 81 82 // 6 - Same as original, but with no name. 83 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 84 "" /* honorific prefix */, "" /* name */, "Acme Inc.", "123 Main", "California", 85 "Los Angeles", "", "90210", "", "US", "555 123-4567", "lisa@simpson.com", ""), 86 87 // 7 - Same as original, but with no phone. 88 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 89 "" /* honorific prefix */, "Lisa Simpson", "Acme Inc.", "123 Main", 90 "California", "Los Angeles", "", "90210", "", "US", "" /* phoneNumber */, 91 "lisa@simpson.com", ""), 92 93 // 8 - Same as original, but with no email. 94 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 95 "" /* honorific prefix */, "Lisa Simpson", "Acme Inc.", "123 Main", 96 "California", "Los Angeles", "", "90210", "", "US", "555 123-4567", 97 "" /* emailAddress */, ""), 98 99 // 9 - Same as original, but with no phone and no email. 100 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 101 "" /* honorific prefix */, "Lisa Simpson", "Acme Inc.", "123 Main", 102 "California", "Los Angeles", "", "90210", "", "US", "" /* phoneNumber */, 103 "" /* emailAddress */, ""), 104 105 // 10 - Has an email address that is a superset of the original profile's email. 106 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 107 "" /* honorific prefix */, "Lisa Simpson", "Acme Inc.", "123 Main", 108 "California", "Los Angeles", "", "90210", "", "US", "555 123-4567", 109 "fakelisa@simpson.com", ""), 110 111 // 11 - Has the same name as the original but with no capitalization in the name. 112 new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, 113 "" /* honorific prefix */, "lisa simpson", "Acme Inc.", "123 Main", 114 "California", "Los Angeles", "", "90210", "", "US", "555 123-4567", 115 "lisa@simpson.com", ""), 116 117 }; 118 119 private AutofillProfile[] mProfilesToAdd; 120 private int[] mCountsToSet; 121 private int[] mDatesToSet; 122 123 @Override onMainActivityStarted()124 public void onMainActivityStarted() throws TimeoutException { 125 AutofillTestHelper helper = new AutofillTestHelper(); 126 127 // Add the profiles. 128 ArrayList<String> guids = new ArrayList<>(); 129 for (int i = 0; i < mProfilesToAdd.length; i++) { 130 guids.add(helper.setProfile(mProfilesToAdd[i])); 131 } 132 133 // Set up the profile use stats. 134 for (int i = 0; i < guids.size(); i++) { 135 helper.setProfileUseStatsForTesting(guids.get(i), mCountsToSet[i], mDatesToSet[i]); 136 } 137 138 mPaymentRequestTestRule.addPaymentAppFactory( 139 AppPresence.HAVE_APPS, FactorySpeed.FAST_FACTORY); 140 } 141 142 /** 143 * Make sure the contact details suggestions are in the correct order and that only the top 4 144 * are shown. They should be ordered by frecency and complete contact details should be 145 * suggested first. 146 */ 147 @Test 148 @MediumTest 149 @Feature({"Payments"}) testContactDetailsSuggestionOrdering()150 public void testContactDetailsSuggestionOrdering() throws TimeoutException { 151 // Set the use stats so that profile[0] has the highest frecency score, profile[1] the 152 // second highest, profile[2] the third lowest, profile[3] the second lowest and profile[4] 153 // the lowest. 154 mProfilesToAdd = new AutofillProfile[] {AUTOFILL_PROFILES[0], AUTOFILL_PROFILES[1], 155 AUTOFILL_PROFILES[2], AUTOFILL_PROFILES[3], AUTOFILL_PROFILES[4]}; 156 mCountsToSet = new int[] {20, 15, 10, 5, 1}; 157 mDatesToSet = new int[] {5000, 5000, 5000, 5000, 1}; 158 159 mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); 160 mPaymentRequestTestRule.clickInContactInfoAndWait( 161 R.id.payments_section, mPaymentRequestTestRule.getReadyForInput()); 162 Assert.assertEquals(4, mPaymentRequestTestRule.getNumberOfContactDetailSuggestions()); 163 Assert.assertEquals("Lisa Simpson\n555 123-4567\nlisa@simpson.com", 164 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(0)); 165 Assert.assertEquals("Maggie Simpson\n555 123-4567\nmaggie@simpson.com", 166 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(1)); 167 Assert.assertEquals("Bart Simpson\nbart@simpson.com\nPhone number required", 168 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(2)); 169 Assert.assertEquals("Homer Simpson\n555 123-4567\nEmail required", 170 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(3)); 171 172 // Verify that no record is logged since there is at least one complete suggested contact 173 // details. 174 Assert.assertEquals(0, 175 RecordHistogram.getHistogramTotalCountForTesting( 176 "PaymentRequest.MissingContactFields")); 177 } 178 179 /** 180 * Make sure the information required message has been displayed for incomplete contact details 181 * correctly. 182 */ 183 @Test 184 @MediumTest 185 @Feature({"Payments"}) testContactDetailsEditRequiredMessage()186 public void testContactDetailsEditRequiredMessage() throws TimeoutException { 187 mProfilesToAdd = new AutofillProfile[] {AUTOFILL_PROFILES[0], AUTOFILL_PROFILES[1], 188 AUTOFILL_PROFILES[4], AUTOFILL_PROFILES[5]}; 189 mCountsToSet = new int[] {15, 10, 5, 1}; 190 mDatesToSet = new int[] {5000, 5000, 5000, 5000}; 191 192 mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); 193 mPaymentRequestTestRule.clickInContactInfoAndWait( 194 R.id.payments_section, mPaymentRequestTestRule.getReadyForInput()); 195 Assert.assertEquals(4, mPaymentRequestTestRule.getNumberOfContactDetailSuggestions()); 196 Assert.assertEquals("Bart Simpson\nbart@simpson.com\nPhone number required", 197 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(0)); 198 Assert.assertEquals("Homer Simpson\n555 123-4567\nEmail required", 199 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(1)); 200 Assert.assertEquals("555 123-4567\nmarge@simpson.com\nName required", 201 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(2)); 202 Assert.assertEquals("Marge Simpson\nMore information required", 203 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(3)); 204 205 // Verify that the missing fields of the most complete suggestion has been recorded. 206 Assert.assertEquals(1, 207 RecordHistogram.getHistogramValueCountForTesting( 208 "PaymentRequest.MissingContactFields", ContactEditor.INVALID_PHONE_NUMBER)); 209 } 210 211 /** 212 * Makes sure that suggestions that are subsets of other fields (empty values) are deduped. 213 */ 214 @Test 215 @MediumTest 216 @Feature({"Payments"}) testContactDetailsDedupe_EmptyFields()217 public void testContactDetailsDedupe_EmptyFields() throws TimeoutException { 218 // Add the original profile and a bunch of similar profiles with missing fields. 219 // Make sure the original profile is suggested last, to test that the suggestions are 220 // sorted by completeness. 221 mProfilesToAdd = new AutofillProfile[] { 222 AUTOFILL_PROFILES[2], 223 AUTOFILL_PROFILES[6], 224 AUTOFILL_PROFILES[7], 225 AUTOFILL_PROFILES[8], 226 AUTOFILL_PROFILES[9], 227 }; 228 mCountsToSet = new int[] {1, 20, 15, 10, 5}; 229 mDatesToSet = new int[] {1000, 4000, 3000, 2000, 1000}; 230 231 mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); 232 mPaymentRequestTestRule.clickInContactInfoAndWait( 233 R.id.payments_section, mPaymentRequestTestRule.getReadyForInput()); 234 235 // Only the original profile with all the fields should be suggested. 236 Assert.assertEquals(1, mPaymentRequestTestRule.getNumberOfContactDetailSuggestions()); 237 Assert.assertEquals("Lisa Simpson\n555 123-4567\nlisa@simpson.com", 238 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(0)); 239 } 240 241 /** 242 * Makes sure that suggestions where some fields values are equal but with different case are 243 * deduped. 244 */ 245 @Test 246 @MediumTest 247 @Feature({"Payments"}) testContactDetailsDedupe_Capitalization()248 public void testContactDetailsDedupe_Capitalization() throws TimeoutException { 249 // Add the original profile and the one where the the name is not capitalized. 250 // Make sure the original profile is suggested first (no particular reason). 251 mProfilesToAdd = new AutofillProfile[] {AUTOFILL_PROFILES[2], AUTOFILL_PROFILES[11]}; 252 mCountsToSet = new int[] {15, 5}; 253 mDatesToSet = new int[] {5000, 2000}; 254 255 mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); 256 mPaymentRequestTestRule.clickInContactInfoAndWait( 257 R.id.payments_section, mPaymentRequestTestRule.getReadyForInput()); 258 Assert.assertEquals(1, mPaymentRequestTestRule.getNumberOfContactDetailSuggestions()); 259 Assert.assertEquals("Lisa Simpson\n555 123-4567\nlisa@simpson.com", 260 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(0)); 261 } 262 263 /** 264 * Makes sure that suggestions where some fields values are subsets of the other are not 265 * deduped. 266 */ 267 @Test 268 @MediumTest 269 @Feature({"Payments"}) testContactDetailsDontDedupe_FieldSubset()270 public void testContactDetailsDontDedupe_FieldSubset() throws TimeoutException { 271 // Add the original profile and the one where the email is a superset of the original. 272 // Make sure the one with the superset is suggested first, because to test the subset one 273 // needs to be added after. 274 mProfilesToAdd = new AutofillProfile[] {AUTOFILL_PROFILES[2], AUTOFILL_PROFILES[10]}; 275 mCountsToSet = new int[] {15, 25}; 276 mDatesToSet = new int[] {5000, 7000}; 277 278 mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); 279 mPaymentRequestTestRule.clickInContactInfoAndWait( 280 R.id.payments_section, mPaymentRequestTestRule.getReadyForInput()); 281 Assert.assertEquals(2, mPaymentRequestTestRule.getNumberOfContactDetailSuggestions()); 282 Assert.assertEquals("Lisa Simpson\n555 123-4567\nfakelisa@simpson.com", 283 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(0)); 284 Assert.assertEquals("Lisa Simpson\n555 123-4567\nlisa@simpson.com", 285 mPaymentRequestTestRule.getContactDetailsSuggestionLabel(1)); 286 } 287 288 /** 289 * Make sure all fields are recorded when no profile exists. 290 */ 291 @Test 292 @MediumTest 293 @Feature({"Payments"}) testContactDetailsAllMissingFieldsRecorded()294 public void testContactDetailsAllMissingFieldsRecorded() throws TimeoutException { 295 // Don't add any profiles. 296 mProfilesToAdd = new AutofillProfile[] {}; 297 mCountsToSet = new int[] {}; 298 mDatesToSet = new int[] {}; 299 300 mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); 301 Assert.assertEquals(0, mPaymentRequestTestRule.getNumberOfContactDetailSuggestions()); 302 303 // Verify that all contact fields are recorded as missing when no suggestion exists. 304 Assert.assertEquals(1, 305 RecordHistogram.getHistogramValueCountForTesting( 306 "PaymentRequest.MissingContactFields", 307 ContactEditor.INVALID_NAME | ContactEditor.INVALID_PHONE_NUMBER 308 | ContactEditor.INVALID_EMAIL)); 309 } 310 } 311