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 android.support.test.InstrumentationRegistry; 8 import android.view.View; 9 10 import androidx.test.filters.MediumTest; 11 12 import org.junit.After; 13 import org.junit.Assert; 14 import org.junit.Before; 15 import org.junit.ClassRule; 16 import org.junit.Rule; 17 import org.junit.Test; 18 import org.junit.runner.RunWith; 19 20 import org.chromium.base.test.util.CallbackHelper; 21 import org.chromium.base.test.util.CommandLineFlags; 22 import org.chromium.base.test.util.DisabledTest; 23 import org.chromium.base.test.util.Feature; 24 import org.chromium.chrome.R; 25 import org.chromium.chrome.browser.flags.ChromeSwitches; 26 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; 27 import org.chromium.content_public.browser.test.util.JavaScriptUtils; 28 import org.chromium.net.test.EmbeddedTestServer; 29 import org.chromium.net.test.ServerCertificate; 30 import org.chromium.ui.test.util.DisableAnimationsTestRule; 31 32 /** An integration test for shipping address and payer's contact information delegation. */ 33 @RunWith(ChromeJUnit4ClassRunner.class) 34 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) 35 @MediumTest 36 public class PaymentHandlerEnableDelegationsTest { 37 // Disable animations to reduce flakiness. 38 @ClassRule 39 public static DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule(); 40 41 // Open a tab on the blank page first to initiate the native bindings required by the test 42 // server. 43 @Rule 44 public PaymentRequestTestRule mRule = new PaymentRequestTestRule("about:blank", null, true); 45 46 // Host the tests on https://127.0.0.1, because file:// URLs cannot have service workers. 47 private EmbeddedTestServer mServer; 48 49 @Before setUp()50 public void setUp() throws Throwable { 51 mServer = EmbeddedTestServer.createAndStartHTTPSServer( 52 InstrumentationRegistry.getContext(), ServerCertificate.CERT_OK); 53 mRule.startMainActivityWithURL( 54 mServer.getURL("/components/test/data/payments/payment_handler.html")); 55 56 // Find the web contents where JavaScript will be executed and instrument the browser 57 // payment sheet. 58 mRule.openPage(); 59 } 60 installPaymentHandlerWithDelegations(String delegations)61 private void installPaymentHandlerWithDelegations(String delegations) throws Throwable { 62 Assert.assertEquals("\"success\"", 63 JavaScriptUtils.runJavascriptWithAsyncResult( 64 mRule.getActivity().getCurrentWebContents(), 65 "install().then(result => {domAutomationController.send(result);});")); 66 Assert.assertEquals("\"success\"", 67 JavaScriptUtils.runJavascriptWithAsyncResult( 68 mRule.getActivity().getCurrentWebContents(), 69 "enableDelegations(" + delegations 70 + ").then(result => {domAutomationController.send(result);});")); 71 } 72 73 @After tearDown()74 public void tearDown() { 75 mServer.stopAndDestroyServer(); 76 } 77 createPaymentRequestAndWaitFor(String paymentOptions, CallbackHelper helper)78 private void createPaymentRequestAndWaitFor(String paymentOptions, CallbackHelper helper) 79 throws Throwable { 80 int callCount = helper.getCallCount(); 81 Assert.assertEquals("\"success\"", 82 mRule.runJavaScriptCodeInCurrentTab( 83 "paymentRequestWithOptions(" + paymentOptions + ");")); 84 helper.waitForCallback(callCount); 85 } 86 87 @Test 88 @Feature({"Payments"}) 89 @MediumTest testShippingDelegation()90 public void testShippingDelegation() throws Throwable { 91 installPaymentHandlerWithDelegations("['shippingAddress']"); 92 // The pay button should be enabled when shipping address is requested and the selected 93 // payment instrument can provide it. 94 createPaymentRequestAndWaitFor("{requestShipping: true}", mRule.getReadyToPay()); 95 96 // Click the pay button and wait for success. 97 mRule.clickAndWait(R.id.button_primary, mRule.getDismissed()); 98 } 99 100 @Test 101 @Feature({"Payments"}) 102 @MediumTest testContactDelegation()103 public void testContactDelegation() throws Throwable { 104 installPaymentHandlerWithDelegations("['payerName', 'payerEmail', 'payerPhone']"); 105 // The pay button should be enabled when payer's contact information is requested and the 106 // selected payment instrument can provide it. 107 createPaymentRequestAndWaitFor( 108 "{requestPayerName: true, requestPayerEmail: true, requestPayerPhone: true}", 109 mRule.getReadyToPay()); 110 111 // Click the pay button and wait for success. 112 mRule.clickAndWait(R.id.button_primary, mRule.getDismissed()); 113 } 114 115 @Test 116 @Feature({"Payments"}) 117 @MediumTest 118 @DisabledTest(message = "crbug.com/1131674") testShippingAndContactInfoDelegation()119 public void testShippingAndContactInfoDelegation() throws Throwable { 120 installPaymentHandlerWithDelegations( 121 "['shippingAddress', 'payerName', 'payerEmail', 'payerPhone']"); 122 // The pay button should be enabled when shipping address and payer's contact information 123 // are requested and the selected payment instrument can provide them. 124 createPaymentRequestAndWaitFor( 125 "{requestShipping: true, requestPayerName: true, requestPayerEmail: true," 126 + " requestPayerPhone: true}", 127 mRule.getReadyToPay()); 128 129 // Click the pay button and wait for success. 130 mRule.clickAndWait(R.id.button_primary, mRule.getDismissed()); 131 } 132 133 @Test 134 @Feature({"Payments"}) 135 @MediumTest testPartialDelegationShippingNotSupported()136 public void testPartialDelegationShippingNotSupported() throws Throwable { 137 installPaymentHandlerWithDelegations("['payerName', 'payerEmail', 'payerPhone']"); 138 createPaymentRequestAndWaitFor( 139 "{requestShipping: true, requestPayerName: true, requestPayerEmail: true}", 140 mRule.getReadyForInput()); 141 // Shipping section must exist in payment sheet since shipping address is requested and 142 // won't be provided by the selected payment handler. 143 Assert.assertEquals(View.VISIBLE, 144 mRule.getPaymentRequestUI().getShippingAddressSectionForTest().getVisibility()); 145 } 146 147 @Test 148 @Feature({"Payments"}) 149 @MediumTest testPartialDelegationContactInfoNotSupported()150 public void testPartialDelegationContactInfoNotSupported() throws Throwable { 151 installPaymentHandlerWithDelegations("['shippingAddress']"); 152 createPaymentRequestAndWaitFor( 153 "{requestShipping: true, requestPayerName: true, requestPayerEmail: true}", 154 mRule.getReadyForInput()); 155 // Contact section must exist in payment sheet since payer's name and email are requested 156 // and won't be provided by the selected payment handler. 157 Assert.assertEquals(View.VISIBLE, 158 mRule.getPaymentRequestUI().getContactDetailsSectionForTest().getVisibility()); 159 } 160 } 161