Commit b4d0bb74 authored by Liquan (Max) Gu's avatar Liquan (Max) Gu Committed by Commit Bot

[PlayBilling] Test WebPaymentIntentHelper

Change:
Add more test coverage for:
 * WebPaymentIntentHelper#parsePaymentResponse
 * WebPaymentIntentHelper#createIsReadyToPayIntent

Bug: 1063430

Change-Id: Ie9347e287fbdfb702850d09d8b54d3140f68e10e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2112933
Commit-Queue: Liquan (Max) Gu <maxlg@chromium.org>
Reviewed-by: default avatarMike West <mkwst@chromium.org>
Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#752532}
parent 18e8c2b1
...@@ -21,6 +21,7 @@ import org.junit.Assert; ...@@ -21,6 +21,7 @@ import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mockito; import org.mockito.Mockito;
...@@ -46,6 +47,9 @@ public class IsReadyToPayServiceHelperTest { ...@@ -46,6 +47,9 @@ public class IsReadyToPayServiceHelperTest {
public ChromeActivityTestRule<ChromeActivity> mRule = public ChromeActivityTestRule<ChromeActivity> mRule =
new ChromeActivityTestRule<>(ChromeActivity.class); new ChromeActivityTestRule<>(ChromeActivity.class);
@Rule
public ExpectedException thrown = ExpectedException.none();
private boolean mErrorReceived; private boolean mErrorReceived;
private boolean mResponseReceived; private boolean mResponseReceived;
...@@ -135,6 +139,35 @@ public class IsReadyToPayServiceHelperTest { ...@@ -135,6 +139,35 @@ public class IsReadyToPayServiceHelperTest {
return context; return context;
} }
/**
* Create a mock context that never connects to a service.
*/
private Context createContextThatNeverConnectToService() {
Context context = Mockito.mock(Context.class);
// Mock {@link Context#bindService}.
try {
Mockito.doAnswer((invocation) -> {
ServiceConnection serviceConnection = invocation.getArgument(1);
new Handler().post(() -> {
ComponentName mockComponentName = null;
try {
mockComponentName = Mockito.any(ComponentName.class);
} catch (Throwable e) {
Assert.fail(e.toString());
}
});
return true;
})
.when(context)
.bindService(Mockito.any(Intent.class), Mockito.any(ServiceConnection.class),
Mockito.anyInt());
} catch (Throwable e) {
Assert.fail(e.toString());
}
return context;
}
@Test @Test
@MediumTest @MediumTest
@Feature({"Payments"}) @Feature({"Payments"})
...@@ -248,4 +281,35 @@ public class IsReadyToPayServiceHelperTest { ...@@ -248,4 +281,35 @@ public class IsReadyToPayServiceHelperTest {
} }
}); });
} }
@Test
@MediumTest
@Feature({"Payments"})
public void serviceConnectionTimeoutTest() throws Throwable {
mErrorReceived = false;
mRule.runOnUiThread(() -> {
Intent intent = new Intent();
intent.setClassName("mock.package.name", "mock.service.name");
Context context = createContextThatNeverConnectToService();
IsReadyToPayServiceHelper helper = new IsReadyToPayServiceHelper(
context, intent, new IsReadyToPayServiceHelper.ResultHandler() {
@Override
public void onIsReadyToPayServiceResponse(boolean isReadyToPay) {
Assert.fail();
}
@Override
public void onIsReadyToPayServiceError() {
mErrorReceived = true;
}
});
});
// Assuming CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL >
// IsReadyToPayServiceHelper.SERVICE_CONNECTION_TIMEOUT_MS.
CriteriaHelper.pollInstrumentationThread(new Criteria() {
@Override
public boolean isSatisfied() {
return mErrorReceived;
}
});
}
} }
...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.payments; ...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.payments;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcelable; import android.os.Parcelable;
...@@ -19,6 +20,7 @@ import org.junit.runner.RunWith; ...@@ -19,6 +20,7 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Feature;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.components.payments.ErrorStrings;
import org.chromium.components.payments.intent.WebPaymentIntentHelper; import org.chromium.components.payments.intent.WebPaymentIntentHelper;
import org.chromium.components.payments.intent.WebPaymentIntentHelperType.PaymentCurrencyAmount; import org.chromium.components.payments.intent.WebPaymentIntentHelperType.PaymentCurrencyAmount;
import org.chromium.components.payments.intent.WebPaymentIntentHelperType.PaymentDetailsModifier; import org.chromium.components.payments.intent.WebPaymentIntentHelperType.PaymentDetailsModifier;
...@@ -30,6 +32,7 @@ import java.util.Arrays; ...@@ -30,6 +32,7 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
/** /**
...@@ -40,6 +43,11 @@ public class WebPaymentIntentHelperTest { ...@@ -40,6 +43,11 @@ public class WebPaymentIntentHelperTest {
@Rule @Rule
public ExpectedException thrown = ExpectedException.none(); public ExpectedException thrown = ExpectedException.none();
// Used to receive the result of {@link #parsePaymentResponse}.
private String mErrorString;
private String mDetails;
private String mMethodName;
// Test the happy path of createPayIntent and verify the non-deprecated extras. // Test the happy path of createPayIntent and verify the non-deprecated extras.
@Test @Test
@SmallTest @SmallTest
...@@ -69,6 +77,9 @@ public class WebPaymentIntentHelperTest { ...@@ -69,6 +77,9 @@ public class WebPaymentIntentHelperTest {
"payment.request.id", "merchant.name", "schemeless.origin", "payment.request.id", "merchant.name", "schemeless.origin",
"schemeless.iframe.origin", certificateChain, methodDataMap, total, displayItems, "schemeless.iframe.origin", certificateChain, methodDataMap, total, displayItems,
modifiers); modifiers);
Assert.assertEquals(WebPaymentIntentHelper.ACTION_PAY, intent.getAction());
Assert.assertEquals("package.name", intent.getComponent().getPackageName());
Assert.assertEquals("activity.name", intent.getComponent().getClassName());
Bundle bundle = intent.getExtras(); Bundle bundle = intent.getExtras();
Assert.assertNotNull(bundle); Assert.assertNotNull(bundle);
Assert.assertEquals( Assert.assertEquals(
...@@ -487,4 +498,158 @@ public class WebPaymentIntentHelperTest { ...@@ -487,4 +498,158 @@ public class WebPaymentIntentHelperTest {
"schemeless.iframe.origin", /*certificateChain=*/null, methodDataMap, total, "schemeless.iframe.origin", /*certificateChain=*/null, methodDataMap, total,
/*displayItems=*/null, modifiers); /*displayItems=*/null, modifiers);
} }
@Test
@SmallTest
@Feature({"Payments"})
public void parsePaymentResponseMissingIntentDataTest() throws Throwable {
mErrorString = null;
WebPaymentIntentHelper.parsePaymentResponse(Activity.RESULT_OK, /*intent=*/null,
(errorString)
-> mErrorString = errorString,
(methodName, details) -> Assert.fail("Parsing should fail."));
Assert.assertEquals(ErrorStrings.MISSING_INTENT_DATA, mErrorString);
}
@Test
@SmallTest
@Feature({"Payments"})
public void parsePaymentResponseMissingIntentExtrasTest() throws Throwable {
Intent intent = new Intent();
mErrorString = null;
WebPaymentIntentHelper.parsePaymentResponse(Activity.RESULT_OK, intent,
(errorString)
-> mErrorString = errorString,
(methodName, details) -> Assert.fail("Parsing should fail."));
Assert.assertEquals(ErrorStrings.MISSING_INTENT_EXTRAS, mErrorString);
}
@Test
@SmallTest
@Feature({"Payments"})
public void parsePaymentResponseResultCanceledTest() throws Throwable {
Intent intent = new Intent();
intent.putExtras(new Bundle());
mErrorString = null;
WebPaymentIntentHelper.parsePaymentResponse(Activity.RESULT_CANCELED, intent,
(errorString)
-> mErrorString = errorString,
(methodName, details) -> Assert.fail("Parsing should fail."));
Assert.assertEquals(ErrorStrings.RESULT_CANCELED, mErrorString);
}
@Test
@SmallTest
@Feature({"Payments"})
public void parsePaymentResponseUnrecognizedActivityResultTest() throws Throwable {
Intent intent = new Intent();
intent.putExtras(new Bundle());
mErrorString = null;
WebPaymentIntentHelper.parsePaymentResponse(/*resultCode=*/123, intent,
(errorString)
-> mErrorString = errorString,
(methodName, details) -> Assert.fail("Parsing should fail."));
Assert.assertEquals(
String.format(Locale.US, ErrorStrings.UNRECOGNIZED_ACTIVITY_RESULT, 123),
mErrorString);
}
@Test
@SmallTest
@Feature({"Payments"})
public void parsePaymentResponseOKTest() throws Throwable {
Intent intent = new Intent();
Bundle extras = new Bundle();
extras.putString(WebPaymentIntentHelper.EXTRA_RESPONSE_DETAILS, "\"key\":\"value\"}");
extras.putString(WebPaymentIntentHelper.EXTRA_RESPONSE_METHOD_NAME, "maxPay");
intent.putExtras(extras);
mErrorString = null;
WebPaymentIntentHelper.parsePaymentResponse(Activity.RESULT_OK, intent,
(errorString) -> Assert.fail("Parsing should succeed."), (methodName, details) -> {
mMethodName = methodName;
mDetails = details;
});
Assert.assertEquals("maxPay", mMethodName);
Assert.assertEquals("\"key\":\"value\"}", mDetails);
}
@Test
@SmallTest
@Feature({"Payments"})
public void parsePaymentResponseDeprecatedDetailTest() throws Throwable {
Intent intent = new Intent();
Bundle extras = new Bundle();
extras.putString(WebPaymentIntentHelper.EXTRA_DEPRECATED_RESPONSE_INSTRUMENT_DETAILS,
"\"key\":\"value\"}");
extras.putString(WebPaymentIntentHelper.EXTRA_RESPONSE_METHOD_NAME, "maxPay");
intent.putExtras(extras);
mErrorString = null;
WebPaymentIntentHelper.parsePaymentResponse(Activity.RESULT_OK, intent,
(errorString) -> Assert.fail("Parsing should succeed."), (methodName, details) -> {
mMethodName = methodName;
mDetails = details;
});
Assert.assertEquals("maxPay", mMethodName);
Assert.assertEquals("\"key\":\"value\"}", mDetails);
}
@Test
@SmallTest
@Feature({"Payments"})
public void createIsReadyToPayIntent() throws Throwable {
Map<String, PaymentMethodData> methodDataMap = new HashMap<String, PaymentMethodData>();
PaymentMethodData bobPayMethodData =
new PaymentMethodData("bobPayMethod", "{\"key\":\"value\"}");
PaymentMethodData maxPayMethodData = new PaymentMethodData("maxPayMethod", "{}");
methodDataMap.put("bobPay", bobPayMethodData);
methodDataMap.put("maxPay", maxPayMethodData);
byte[][] certificateChain = new byte[][] {{0}};
Intent intent = WebPaymentIntentHelper.createIsReadyToPayIntent("package.name",
"service.name", "schemeless.origin", "schemeless.iframe.origin", certificateChain,
methodDataMap);
Assert.assertEquals("package.name", intent.getComponent().getPackageName());
Assert.assertEquals("service.name", intent.getComponent().getClassName());
Bundle bundle = intent.getExtras();
Assert.assertNotNull(bundle);
Assert.assertEquals(
"schemeless.origin", bundle.get(WebPaymentIntentHelper.EXTRA_TOP_ORIGIN));
Assert.assertEquals("schemeless.iframe.origin",
bundle.get(WebPaymentIntentHelper.EXTRA_PAYMENT_REQUEST_ORIGIN));
Parcelable[] certificateChainParcels =
bundle.getParcelableArray(WebPaymentIntentHelper.EXTRA_TOP_CERTIFICATE_CHAIN);
Assert.assertEquals(1, certificateChainParcels.length);
assertThat(((Bundle) certificateChainParcels[0])
.getByteArray(WebPaymentIntentHelper.EXTRA_CERTIFICATE))
.isEqualTo(new byte[] {0});
Assert.assertEquals(new HashSet(Arrays.asList("bobPay", "maxPay")),
new HashSet(bundle.getStringArrayList(WebPaymentIntentHelper.EXTRA_METHOD_NAMES)));
Bundle expectedMethodDataBundle =
bundle.getParcelable(WebPaymentIntentHelper.EXTRA_METHOD_DATA);
Assert.assertEquals(2, expectedMethodDataBundle.keySet().size());
Assert.assertEquals("{\"key\":\"value\"}", expectedMethodDataBundle.getString("bobPay"));
Assert.assertEquals("{}", expectedMethodDataBundle.getString("maxPay"));
}
@Test
@SmallTest
@Feature({"Payments"})
public void createIsReadyToPayIntentNullPackageNameExceptionTest() throws Throwable {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("packageName should not be null or empty.");
Map<String, PaymentMethodData> methodDataMap = new HashMap<String, PaymentMethodData>();
PaymentMethodData bobPayMethodData = new PaymentMethodData("method", "null");
methodDataMap.put("bobPay", bobPayMethodData);
PaymentItem total = new PaymentItem(new PaymentCurrencyAmount("CAD", "200"));
WebPaymentIntentHelper.createIsReadyToPayIntent(/*packageName=*/null, "service.name",
"schemeless.origin", "schemeless.iframe.origin", /*certificateChain=*/null,
methodDataMap);
}
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment