1 // Copyright 2019 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.autofill.PersonalDataManager.CreditCard; 22 import org.chromium.chrome.browser.flags.ChromeSwitches; 23 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback; 24 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; 25 import org.chromium.ui.test.util.DisableAnimationsTestRule; 26 27 import java.util.ArrayList; 28 import java.util.concurrent.TimeoutException; 29 30 /** 31 * A payment integration test for a merchant that requires shipping address to calculate shipping 32 * and user that has 5 addresses stored in autofill settings. 33 */ 34 @RunWith(ChromeJUnit4ClassRunner.class) 35 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) 36 public class PaymentRequestMultiplePaymentInstrumentsTest implements MainActivityStartCallback { 37 // Disable animations to reduce flakiness. 38 @ClassRule 39 public static DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule(); 40 41 @Rule 42 public PaymentRequestTestRule mPaymentRequestTestRule = 43 new PaymentRequestTestRule("payment_request_no_shipping_test.html", this); 44 45 private static final AutofillProfile AUTOFILL_PROFILE = new AutofillProfile("" /* guid */, 46 "https://www.example.com" /* origin */, "" /* honorific prefix */, "Lisa Simpson", 47 "Acme Inc.", "123 Main", "California", "Los Angeles", "", "90210", "", "US", 48 "555 123-4567", "lisa@simpson.com", "" /* languageCode */); 49 50 private static final CreditCard[] CREDIT_CARDS = { 51 // CARD_0 missing billing address. 52 new CreditCard("", "https://example.com", true /* isLocal */, true /* isCached */, 53 "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa", 54 R.drawable.visa_card, "" /* billingAddressId */, "" /* serverId */), 55 56 // For the rest of the cards billing address id will be added in 57 // onMainActivityStarted(). 58 // CARD_1 complete card. 59 new CreditCard("", "https://example.com", true /* isLocal */, true /* isCached */, 60 "John Smith", "4111111111113333", "3333", "10", "2050", "visa", 61 R.drawable.amex_card, "" /* billingAddressId */, "" /* serverId */), 62 63 // CARD_2 complete card, different from CARD_1. 64 new CreditCard("", "https://example.com", true /* isLocal */, true /* isCached */, 65 "Jane Doe", "4111111111112222", "2222", "07", "2077", "visa", 66 R.drawable.visa_card, "" /* billingAddressId */, "" /* serverId */), 67 68 // CARD_3 expired card. 69 new CreditCard("", "https://example.com", true /* isLocal */, true /* isCached */, 70 "Lisa Simpson", "4111111111111111", "1111", "12", "2010", "visa", 71 R.drawable.visa_card, "" /* billingAddressId */, "" /* serverId */), 72 73 // CARD_4 missing name. 74 new CreditCard("", "https://example.com", true /* isLocal */, true /* isCached */, 75 "" /* name */, "4012888888881881", "1881", "06", "2049", "visa", 76 R.drawable.visa_card, "" /* billingAddressId */, "" /* serverId */), 77 }; 78 79 private CreditCard[] mCreditCardsToAdd; 80 private int[] mCountsToSet; 81 private int[] mDatesToSet; 82 83 @Override onMainActivityStarted()84 public void onMainActivityStarted() throws TimeoutException { 85 AutofillTestHelper helper = new AutofillTestHelper(); 86 87 // The user has a complete autofill profile. 88 String billingAddressId = helper.setProfile(AUTOFILL_PROFILE); 89 // Add the autofill card. 90 ArrayList<String> guids = new ArrayList<>(); 91 for (int i = 0; i < mCreditCardsToAdd.length; i++) { 92 // CREDIT_CARDS[0] has no billing address. 93 if (mCreditCardsToAdd[i] != CREDIT_CARDS[0]) { 94 mCreditCardsToAdd[i].setBillingAddressId(billingAddressId); 95 } 96 String creditCardId = helper.setCreditCard(mCreditCardsToAdd[i]); 97 guids.add(creditCardId); 98 } 99 100 // Set up the autofill card use stats. 101 for (int i = 0; i < guids.size(); i++) { 102 PaymentPreferencesUtil.setPaymentAppUseCountForTest(guids.get(i), mCountsToSet[i]); 103 PaymentPreferencesUtil.setPaymentAppLastUseDate(guids.get(i), mDatesToSet[i]); 104 } 105 } 106 107 /** 108 * Make sure the address suggestions are in the correct order and that only the top 4 109 * suggestions are shown. They should be ordered by frecency and complete addresses should be 110 * suggested first. 111 */ 112 @Test 113 @MediumTest 114 @Feature({"Payments"}) testCreditCardSuggestionOrdering()115 public void testCreditCardSuggestionOrdering() throws TimeoutException { 116 mCreditCardsToAdd = new CreditCard[] {CREDIT_CARDS[0], CREDIT_CARDS[3], CREDIT_CARDS[2], 117 CREDIT_CARDS[1], CREDIT_CARDS[4]}; 118 mCountsToSet = new int[] {20, 15, 10, 25, 30}; 119 mDatesToSet = new int[] {5000, 5000, 5000, 5000, 5000}; 120 121 mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); 122 mPaymentRequestTestRule.clickInPaymentMethodAndWait( 123 R.id.payments_section, mPaymentRequestTestRule.getReadyForInput()); 124 Assert.assertEquals(5, mPaymentRequestTestRule.getNumberOfPaymentApps()); 125 int i = 0; 126 // The two complete cards are sorted by frecency. 127 Assert.assertTrue(mPaymentRequestTestRule.getPaymentMethodSuggestionLabel(i++).contains( 128 "John Smith")); 129 Assert.assertTrue( 130 mPaymentRequestTestRule.getPaymentMethodSuggestionLabel(i++).contains("Jane Doe")); 131 // Incomplete cards have this order: 1-expired 2-missing name 3-missing address 4-missing 132 // card number. 133 Assert.assertTrue(mPaymentRequestTestRule.getPaymentMethodSuggestionLabel(i++).contains( 134 "Lisa Simpson")); 135 Assert.assertTrue(mPaymentRequestTestRule.getPaymentMethodSuggestionLabel(i++).contains( 136 "Cardholder name required")); 137 Assert.assertTrue( 138 mPaymentRequestTestRule.getPaymentMethodSuggestionLabel(i++).contains("Jon Doe")); 139 140 // Verify that no shipping fields is recorded since there is at least one complete 141 // suggestion. 142 Assert.assertEquals(0, 143 RecordHistogram.getHistogramTotalCountForTesting( 144 "PaymentRequest.MissingPaymentFields")); 145 } 146 147 /** 148 * Make sure the name bit is recorded in missing fields when an incomplete card with missing 149 * name is the most complete one. 150 */ 151 @Test 152 @MediumTest 153 @Feature({"Payments"}) testMissingNameFieldRecorded()154 public void testMissingNameFieldRecorded() throws TimeoutException { 155 // Add a card with invalid billing address and another one with missing name. 156 mCreditCardsToAdd = new CreditCard[] {CREDIT_CARDS[4], CREDIT_CARDS[0]}; 157 mCountsToSet = new int[] {5, 5}; 158 mDatesToSet = new int[] {5000, 5000}; 159 160 mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); 161 mPaymentRequestTestRule.clickInPaymentMethodAndWait( 162 R.id.payments_section, mPaymentRequestTestRule.getReadyForInput()); 163 Assert.assertEquals(2, mPaymentRequestTestRule.getNumberOfPaymentApps()); 164 165 // Verify that the missing fields of the most complete payment method has been recorded. 166 Assert.assertEquals(1, 167 RecordHistogram.getHistogramValueCountForTesting( 168 "PaymentRequest.MissingPaymentFields", 169 AutofillPaymentInstrument.CompletionStatus.CREDIT_CARD_NO_CARDHOLDER)); 170 } 171 172 /** 173 * Make sure the billing address bit is recorded in missing fields when an incomplete card 174 * with missing address is the most complete one. 175 */ 176 @Test 177 @MediumTest 178 @Feature({"Payments"}) testMissingBillingAddressFieldRecorded()179 public void testMissingBillingAddressFieldRecorded() throws TimeoutException { 180 // Add a card with invalid billing address. 181 mCreditCardsToAdd = new CreditCard[] {CREDIT_CARDS[0]}; 182 mCountsToSet = new int[] {5}; 183 mDatesToSet = new int[] {5000}; 184 185 mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); 186 mPaymentRequestTestRule.clickInPaymentMethodAndWait( 187 R.id.payments_section, mPaymentRequestTestRule.getReadyForInput()); 188 Assert.assertEquals(1, mPaymentRequestTestRule.getNumberOfPaymentApps()); 189 190 // Verify that the missing fields of the most complete payment method has been recorded. 191 Assert.assertEquals(1, 192 RecordHistogram.getHistogramValueCountForTesting( 193 "PaymentRequest.MissingPaymentFields", 194 AutofillPaymentInstrument.CompletionStatus.CREDIT_CARD_NO_BILLING_ADDRESS)); 195 } 196 197 /** 198 * Make sure all fields are recorded when no card exists. 199 */ 200 @Test 201 @MediumTest 202 @Feature({"Payments"}) 203 @CommandLineFlags.Add("disable-features=StrictHasEnrolledAutofillInstrument") testAllMissingFieldsRecorded()204 public void testAllMissingFieldsRecorded() throws TimeoutException { 205 // Don't add any cards 206 mCreditCardsToAdd = new CreditCard[] {}; 207 mCountsToSet = new int[] {}; 208 mDatesToSet = new int[] {}; 209 210 mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); 211 Assert.assertEquals(0, mPaymentRequestTestRule.getNumberOfPaymentApps()); 212 213 // Verify that the missing fields of the most complete payment method has been recorded. 214 Assert.assertEquals(1, 215 RecordHistogram.getHistogramValueCountForTesting( 216 "PaymentRequest.MissingPaymentFields", 217 AutofillPaymentInstrument.CompletionStatus.CREDIT_CARD_EXPIRED 218 | AutofillPaymentInstrument.CompletionStatus 219 .CREDIT_CARD_NO_CARDHOLDER 220 | AutofillPaymentInstrument.CompletionStatus 221 .CREDIT_CARD_NO_BILLING_ADDRESS 222 | AutofillPaymentInstrument.CompletionStatus 223 .CREDIT_CARD_NO_NUMBER)); 224 } 225 } 226