From 70ecdec3c400f120a721e24e1ffc4a585646ad22 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Mon, 18 Dec 2023 14:46:36 -0600 Subject: [PATCH 1/3] Remove activity from VenmoClient --- .../braintreepayments/demo/VenmoFragment.java | 5 +- .../braintreepayments/api/VenmoClient.java | 38 ++---- .../braintreepayments/api/VenmoLauncher.java | 20 ++- .../api/VenmoClientUnitTest.java | 124 ++++++++---------- .../api/VenmoLauncherUnitTest.java | 21 +++ 5 files changed, 110 insertions(+), 98 deletions(-) diff --git a/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java b/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java index a96136581b..45ccac90b4 100644 --- a/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java +++ b/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java @@ -36,7 +36,7 @@ public class VenmoFragment extends BaseFragment { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_venmo, container, false); venmoButton = view.findViewById(R.id.venmo_button); - venmoButton.setOnClickListener(this::launchVenmo); + venmoButton.setOnClickListener(this::showVenmo); venmoLauncher = new VenmoLauncher(this, venmoAuthChallengeResult -> venmoClient.tokenize(venmoAuthChallengeResult, this::handleVenmoResult)); @@ -60,6 +60,9 @@ private void handleVenmoAccountNonce(VenmoAccountNonce venmoAccountNonce) { VenmoFragmentDirections.actionVenmoFragmentToDisplayNonceFragment(venmoAccountNonce); NavHostFragment.findNavController(this).navigate(action); } + public void showVenmo(View v) { + venmoLauncher.showVenmoInGooglePlayStore(requireActivity()); + } public void launchVenmo(View v) { getActivity().setProgressBarIndeterminateVisibility(true); diff --git a/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java b/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java index 1996a44359..966ec45f0c 100644 --- a/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java +++ b/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java @@ -1,15 +1,11 @@ package com.braintreepayments.api; import android.content.Context; -import android.content.Intent; -import android.net.Uri; import android.text.TextUtils; -import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import androidx.fragment.app.FragmentActivity; /** * Used to create and tokenize Venmo accounts. For more information see the { if (exception == null) { - createPaymentAuthRequest(activity, request, configuration, + createPaymentAuthRequest(context, request, configuration, braintreeClient.getAuthorization(), finalVenmoProfileId, paymentContextId, callback); } else { @@ -130,7 +112,7 @@ public void createPaymentAuthRequest(@NonNull final FragmentActivity activity, } private void createPaymentAuthRequest( - final FragmentActivity activity, + final Context context, final VenmoRequest request, final Configuration configuration, Authorization authorization, @@ -140,7 +122,7 @@ private void createPaymentAuthRequest( ) { boolean isClientTokenAuth = (authorization instanceof ClientToken); boolean shouldVault = request.getShouldVault() && isClientTokenAuth; - sharedPrefsWriter.persistVenmoVaultOption(activity, shouldVault); + sharedPrefsWriter.persistVenmoVaultOption(context, shouldVault); VenmoPaymentAuthRequestParams params = new VenmoPaymentAuthRequestParams(configuration, venmoProfileId, paymentContextId, braintreeClient.getSessionId(), braintreeClient.getIntegrationType()); @@ -149,7 +131,7 @@ private void createPaymentAuthRequest( /** * After successfully authenticating a Venmo user account via {@link - * VenmoClient#createPaymentAuthRequest(FragmentActivity, VenmoRequest, VenmoPaymentAuthRequestCallback)}, + * VenmoClient#createPaymentAuthRequest(Context, VenmoRequest, VenmoPaymentAuthRequestCallback)}, * this method should be invoked to tokenize the account to retrieve a * {@link VenmoAccountNonce}. * diff --git a/Venmo/src/main/java/com/braintreepayments/api/VenmoLauncher.java b/Venmo/src/main/java/com/braintreepayments/api/VenmoLauncher.java index 422379135e..bd3b5b602a 100644 --- a/Venmo/src/main/java/com/braintreepayments/api/VenmoLauncher.java +++ b/Venmo/src/main/java/com/braintreepayments/api/VenmoLauncher.java @@ -1,6 +1,10 @@ package com.braintreepayments.api; +import android.content.Intent; +import android.net.Uri; + +import androidx.activity.ComponentActivity; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultRegistry; import androidx.annotation.NonNull; @@ -17,6 +21,7 @@ public class VenmoLauncher { @VisibleForTesting ActivityResultLauncher activityLauncher; private static final String VENMO_SECURE_RESULT = "com.braintreepayments.api.Venmo.RESULT"; + static final String VENMO_PACKAGE_NAME = "com.venmo"; /** * Used to launch the Venmo authentication flow to tokenize a Venmo account. This class must be @@ -56,10 +61,21 @@ public VenmoLauncher(@NonNull FragmentActivity activity, * Launches the Venmo authentication flow by switching to the Venmo app. * * @param venmoPaymentAuthRequest the result of - * {@link VenmoClient#createPaymentAuthRequest(FragmentActivity, - * VenmoRequest, VenmoPaymentAuthRequestCallback)} + * {@link VenmoClient#createPaymentAuthRequest(android.content.Context, VenmoRequest, VenmoPaymentAuthRequestCallback)} */ public void launch(VenmoPaymentAuthRequest.ReadyToLaunch venmoPaymentAuthRequest) { activityLauncher.launch(venmoPaymentAuthRequest.getRequestParams()); } + + /** + * Launches an Android Intent pointing to the Venmo app on the Google Play Store + * + * @param activity used to open the Venmo's Google Play Store + */ + public void showVenmoInGooglePlayStore(@NonNull ComponentActivity activity) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse( + "https://play.google.com/store/apps/details?id=" + VENMO_PACKAGE_NAME)); + activity.startActivity(intent); + } } \ No newline at end of file diff --git a/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java b/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java index 38e5f2e3ae..3c63ec4fa5 100644 --- a/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java +++ b/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java @@ -12,9 +12,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.Context; import android.content.Intent; import androidx.fragment.app.FragmentActivity; +import androidx.test.core.app.ApplicationProvider; import org.json.JSONException; import org.json.JSONObject; @@ -29,7 +31,7 @@ @RunWith(RobolectricTestRunner.class) public class VenmoClientUnitTest { - private FragmentActivity activity; + private Context context; private BraintreeClient braintreeClient; private Configuration venmoEnabledConfiguration; @@ -45,7 +47,7 @@ public class VenmoClientUnitTest { @Before public void beforeEach() throws JSONException { - activity = mock(FragmentActivity.class); + context = ApplicationProvider.getApplicationContext(); braintreeClient = mock(BraintreeClient.class); venmoApi = mock(VenmoApi.class); deviceInspector = mock(DeviceInspector.class); @@ -62,19 +64,7 @@ public void beforeEach() throws JSONException { tokenizationKey = Authorization.fromString(Fixtures.TOKENIZATION_KEY); } - @Test - public void showVenmoInGooglePlayStore_opensVenmoAppStoreURL() { - VenmoClient sut = - new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.showVenmoInGooglePlayStore(activity); - - ArgumentCaptor captor = ArgumentCaptor.forClass(Intent.class); - - verify(activity).startActivity(captor.capture()); - assertEquals(captor.getValue().getData().toString(), - "https://play.google.com/store/apps/details?id=com.venmo"); - } @Test public void createPaymentAuthRequest_whenCreatePaymentContextFails_collectAddressWithEcdDisabled() { @@ -89,7 +79,7 @@ public void createPaymentAuthRequest_whenCreatePaymentContextFails_collectAddres .createPaymentContextSuccess("venmo-payment-context-id") .build(); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); ArgumentCaptor captor = ArgumentCaptor.forClass(VenmoPaymentAuthRequest.class); @@ -100,7 +90,7 @@ public void createPaymentAuthRequest_whenCreatePaymentContextFails_collectAddres VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); verify(venmoPaymentAuthRequestCallback).onVenmoPaymentAuthRequest(captor.capture()); verify(braintreeClient).sendAnalyticsEvent(VenmoAnalytics.TOKENIZE_FAILED); @@ -124,7 +114,7 @@ public void createPaymentAuthRequest_whenCreatePaymentContextSucceeds_createsVen .createPaymentContextSuccess("venmo-payment-context-id") .build(); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); VenmoRequest request = new VenmoRequest(VenmoPaymentMethodUsage.SINGLE_USE); request.setProfileId("sample-venmo-merchant"); @@ -132,7 +122,7 @@ public void createPaymentAuthRequest_whenCreatePaymentContextSucceeds_createsVen VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); InOrder inOrder = Mockito.inOrder(venmoPaymentAuthRequestCallback, braintreeClient); inOrder.verify(braintreeClient).sendAnalyticsEvent(VenmoAnalytics.TOKENIZE_STARTED); @@ -164,7 +154,7 @@ public void createPaymentAuthRequest_whenConfigurationException_forwardsExceptio VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(VenmoPaymentAuthRequest.class); @@ -187,7 +177,7 @@ public void createPaymentAuthRequest_whenVenmoNotEnabled_forwardsExceptionToList VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(VenmoPaymentAuthRequest.class); @@ -208,13 +198,13 @@ public void createPaymentAuthRequest_whenVenmoNotInstalled_forwardsExceptionToLi request.setProfileId(null); request.setShouldVault(false); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(false); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(false); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); - verify(deviceInspector).isVenmoAppSwitchAvailable(same(activity)); + verify(deviceInspector).isVenmoAppSwitchAvailable(same(context)); verify(braintreeClient).sendAnalyticsEvent(VenmoAnalytics.APP_SWITCH_FAILED); ArgumentCaptor captor = @@ -243,11 +233,11 @@ public void createPaymentAuthRequest_whenProfileIdIsNull_appSwitchesWithMerchant request.setProfileId(null); request.setShouldVault(false); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(VenmoPaymentAuthRequest.class); @@ -278,11 +268,11 @@ public void createPaymentAuthRequest_whenProfileIdIsSpecified_appSwitchesWithPro request.setProfileId("second-pwv-profile-id"); request.setShouldVault(false); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(VenmoPaymentAuthRequest.class); @@ -308,7 +298,7 @@ public void createPaymentAuthRequest_sendsAnalyticsEvent() { VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); verify(braintreeClient).sendAnalyticsEvent(VenmoAnalytics.TOKENIZE_STARTED); } @@ -328,13 +318,13 @@ public void createPaymentAuthRequest_whenShouldVaultIsTrue_persistsVenmoVaultTru request.setProfileId(null); request.setShouldVault(true); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); - verify(sharedPrefsWriter).persistVenmoVaultOption(activity, true); + verify(sharedPrefsWriter).persistVenmoVaultOption(context, true); } @Test @@ -352,13 +342,13 @@ public void createPaymentAuthRequest_whenShouldVaultIsFalse_persistsVenmoVaultFa request.setProfileId(null); request.setShouldVault(false); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); - verify(sharedPrefsWriter).persistVenmoVaultOption(activity, false); + verify(sharedPrefsWriter).persistVenmoVaultOption(context, false); } @Test @@ -377,13 +367,13 @@ public void createPaymentAuthRequest_withTokenizationKey_persistsVenmoVaultFalse request.setProfileId(null); request.setShouldVault(false); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); - verify(sharedPrefsWriter).persistVenmoVaultOption(activity, false); + verify(sharedPrefsWriter).persistVenmoVaultOption(context, false); } @Test @@ -400,11 +390,11 @@ public void createPaymentAuthRequest_sendsAnalyticsEventWhenUnavailableAndPostEx request.setProfileId(null); request.setShouldVault(false); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(false); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(false); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(VenmoPaymentAuthRequest.class); @@ -432,11 +422,11 @@ public void createPaymentAuthRequest_whenVenmoApiError_forwardsErrorToListener_a .build(); VenmoRequest request = new VenmoRequest(VenmoPaymentMethodUsage.SINGLE_USE); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - sut.createPaymentAuthRequest(activity, request, venmoPaymentAuthRequestCallback); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(VenmoPaymentAuthRequest.class); @@ -458,7 +448,7 @@ public void isReadyToPay_whenConfigurationFails_callbackFalseAndPropagatesError( new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); VenmoIsReadyToPayCallback callback = mock(VenmoIsReadyToPayCallback.class); - sut.isReadyToPay(activity, callback); + sut.isReadyToPay(context, callback); verify(callback).onVenmoReadinessResult(any(VenmoReadinessResult.Failure.class)); } @@ -473,7 +463,7 @@ public void isReadyToPay_whenVenmoDisabled_callbackFalse() throws JSONException new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); VenmoIsReadyToPayCallback callback = mock(VenmoIsReadyToPayCallback.class); - sut.isReadyToPay(activity, callback); + sut.isReadyToPay(context, callback); verify(callback).onVenmoReadinessResult(VenmoReadinessResult.NotReadyToPay.INSTANCE); } @@ -487,10 +477,10 @@ public void isReadyToPay_whenVenmoEnabledAndAppSwitchUnavailable_callbackFalse() VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(false); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(false); VenmoIsReadyToPayCallback callback = mock(VenmoIsReadyToPayCallback.class); - sut.isReadyToPay(activity, callback); + sut.isReadyToPay(context, callback); verify(callback).onVenmoReadinessResult(VenmoReadinessResult.NotReadyToPay.INSTANCE); } @@ -504,10 +494,10 @@ public void isReadyToPay_whenVenmoEnabledAndAppSwitchAvailable_callbackTrue() VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); VenmoIsReadyToPayCallback callback = mock(VenmoIsReadyToPayCallback.class); - sut.isReadyToPay(activity, callback); + sut.isReadyToPay(context, callback); verify(callback).onVenmoReadinessResult(VenmoReadinessResult.ReadyToPay.INSTANCE); } @@ -650,7 +640,7 @@ public void tokenize_withPaymentContext_performsVaultRequestIfRequestPersisted() .sessionId("session-id") .authorizationSuccess(clientToken) .build(); - when(braintreeClient.getApplicationContext()).thenReturn(activity); + when(braintreeClient.getApplicationContext()).thenReturn(context); VenmoAccountNonce nonce = mock(VenmoAccountNonce.class); when(nonce.getString()).thenReturn("some-nonce"); @@ -663,8 +653,8 @@ public void tokenize_withPaymentContext_performsVaultRequestIfRequestPersisted() request.setProfileId(null); request.setShouldVault(true); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); - when(sharedPrefsWriter.getVenmoVaultOption(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); + when(sharedPrefsWriter.getVenmoVaultOption(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); @@ -746,7 +736,7 @@ public void tokenize_performsVaultRequestIfRequestPersisted() throws JSONExcepti .sessionId("session-id") .authorizationSuccess(clientToken) .build(); - when(braintreeClient.getApplicationContext()).thenReturn(activity); + when(braintreeClient.getApplicationContext()).thenReturn(context); VenmoApi venmoApi = new MockVenmoApiBuilder() .createNonceFromPaymentContextSuccess(VenmoAccountNonce.fromJSON( @@ -757,8 +747,8 @@ public void tokenize_performsVaultRequestIfRequestPersisted() throws JSONExcepti request.setProfileId(null); request.setShouldVault(true); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); - when(sharedPrefsWriter.getVenmoVaultOption(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); + when(sharedPrefsWriter.getVenmoVaultOption(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); @@ -779,8 +769,8 @@ public void tokenize_doesNotPerformRequestIfTokenizationKeyUsed() { .authorizationSuccess(tokenizationKey) .build(); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); - when(sharedPrefsWriter.getVenmoVaultOption(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); + when(sharedPrefsWriter.getVenmoVaultOption(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); @@ -800,7 +790,7 @@ public void tokenize_withSuccessfulVaultCall_forwardsResultToActivityResultListe .sessionId("session-id") .authorizationSuccess(clientToken) .build(); - when(braintreeClient.getApplicationContext()).thenReturn(activity); + when(braintreeClient.getApplicationContext()).thenReturn(context); VenmoAccountNonce venmoAccountNonce = mock(VenmoAccountNonce.class); @@ -808,8 +798,8 @@ public void tokenize_withSuccessfulVaultCall_forwardsResultToActivityResultListe .vaultVenmoAccountNonceSuccess(venmoAccountNonce) .build(); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); - when(sharedPrefsWriter.getVenmoVaultOption(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); + when(sharedPrefsWriter.getVenmoVaultOption(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); @@ -837,7 +827,7 @@ public void tokenize_withPaymentContext_withSuccessfulVaultCall_forwardsNonceToC .sendGraphQLPOSTSuccessfulResponse( Fixtures.VENMO_GRAPHQL_GET_PAYMENT_CONTEXT_RESPONSE) .build(); - when(braintreeClient.getApplicationContext()).thenReturn(activity); + when(braintreeClient.getApplicationContext()).thenReturn(context); VenmoAccountNonce venmoAccountNonce = VenmoAccountNonce.fromJSON( new JSONObject(Fixtures.PAYMENT_METHODS_VENMO_ACCOUNT_RESPONSE)); @@ -847,8 +837,8 @@ public void tokenize_withPaymentContext_withSuccessfulVaultCall_forwardsNonceToC .vaultVenmoAccountNonceSuccess(venmoAccountNonce) .build(); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); - when(sharedPrefsWriter.getVenmoVaultOption(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); + when(sharedPrefsWriter.getVenmoVaultOption(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); @@ -874,7 +864,7 @@ public void tokenize_withFailedVaultCall_forwardsErrorToActivityResultListener_a .sessionId("session-id") .authorizationSuccess(clientToken) .build(); - when(braintreeClient.getApplicationContext()).thenReturn(activity); + when(braintreeClient.getApplicationContext()).thenReturn(context); Exception error = new Exception("error"); @@ -882,8 +872,8 @@ public void tokenize_withFailedVaultCall_forwardsErrorToActivityResultListener_a .vaultVenmoAccountNonceError(error) .build(); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); - when(sharedPrefsWriter.getVenmoVaultOption(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); + when(sharedPrefsWriter.getVenmoVaultOption(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); @@ -910,7 +900,7 @@ public void tokenize_withPaymentContext_withFailedVaultCall_forwardsErrorToCallb .sendGraphQLPOSTSuccessfulResponse( Fixtures.VENMO_GRAPHQL_GET_PAYMENT_CONTEXT_RESPONSE) .build(); - when(braintreeClient.getApplicationContext()).thenReturn(activity); + when(braintreeClient.getApplicationContext()).thenReturn(context); VenmoAccountNonce venmoAccountNonce = VenmoAccountNonce.fromJSON( new JSONObject(Fixtures.PAYMENT_METHODS_VENMO_ACCOUNT_RESPONSE)); @@ -921,8 +911,8 @@ public void tokenize_withPaymentContext_withFailedVaultCall_forwardsErrorToCallb .vaultVenmoAccountNonceError(error) .build(); - when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); - when(sharedPrefsWriter.getVenmoVaultOption(activity)).thenReturn(true); + when(deviceInspector.isVenmoAppSwitchAvailable(context)).thenReturn(true); + when(sharedPrefsWriter.getVenmoVaultOption(context)).thenReturn(true); VenmoClient sut = new VenmoClient(braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); diff --git a/Venmo/src/test/java/com/braintreepayments/api/VenmoLauncherUnitTest.java b/Venmo/src/test/java/com/braintreepayments/api/VenmoLauncherUnitTest.java index 1071d27ad0..78e03335bc 100644 --- a/Venmo/src/test/java/com/braintreepayments/api/VenmoLauncherUnitTest.java +++ b/Venmo/src/test/java/com/braintreepayments/api/VenmoLauncherUnitTest.java @@ -1,10 +1,15 @@ package com.braintreepayments.api; +import static junit.framework.Assert.assertEquals; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import android.content.Context; +import android.content.Intent; + +import androidx.activity.ComponentActivity; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultRegistry; import androidx.activity.result.contract.ActivityResultContract; @@ -14,6 +19,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; @@ -60,4 +66,19 @@ public void launch_launchesAuthChallenge() throws JSONException { verify(activityResultLauncher).launch(params); } + + @Test + public void showVenmoInGooglePlayStore_opensVenmoAppStoreURL() { + ActivityResultRegistry activityResultRegistry = mock(ActivityResultRegistry.class); + ComponentActivity activity = mock(ComponentActivity.class); + VenmoLauncher sut = new VenmoLauncher(activityResultRegistry, activity, callback); + + sut.showVenmoInGooglePlayStore(activity); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Intent.class); + + verify(activity).startActivity(captor.capture()); + assertEquals(captor.getValue().getData().toString(), + "https://play.google.com/store/apps/details?id=com.venmo"); + } } From bbf13d9b0476b17ca13ca8974986b47690432947 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Mon, 18 Dec 2023 14:47:30 -0600 Subject: [PATCH 2/3] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4850e947f..394b70d0aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ `VenmoClient#tokenize` * Change parameters of `VenmoIsReadyToPayCallback` and add `VenmoReadinessResult` * Add `VenmoClient#createPaymentAuthRequest` + * Move `showVenmoInGooglePlayStore` to `VenmoLauncher` * GooglePay * Remove `GooglePayListener` and `GooglePayRequestPaymentCallback` * Add `GooglePayLauncher`, `GooglePayPaymentAuthRequest`, From 2b57f1fed24ebe88d766e7b636d8ce3a25104b61 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Mon, 18 Dec 2023 14:50:21 -0600 Subject: [PATCH 3/3] revert demo app changes --- .../main/java/com/braintreepayments/demo/VenmoFragment.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java b/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java index 45ccac90b4..a96136581b 100644 --- a/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java +++ b/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java @@ -36,7 +36,7 @@ public class VenmoFragment extends BaseFragment { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_venmo, container, false); venmoButton = view.findViewById(R.id.venmo_button); - venmoButton.setOnClickListener(this::showVenmo); + venmoButton.setOnClickListener(this::launchVenmo); venmoLauncher = new VenmoLauncher(this, venmoAuthChallengeResult -> venmoClient.tokenize(venmoAuthChallengeResult, this::handleVenmoResult)); @@ -60,9 +60,6 @@ private void handleVenmoAccountNonce(VenmoAccountNonce venmoAccountNonce) { VenmoFragmentDirections.actionVenmoFragmentToDisplayNonceFragment(venmoAccountNonce); NavHostFragment.findNavController(this).navigate(action); } - public void showVenmo(View v) { - venmoLauncher.showVenmoInGooglePlayStore(requireActivity()); - } public void launchVenmo(View v) { getActivity().setProgressBarIndeterminateVisibility(true);