From 124eedc869dcd2519a6b100f50a1fd35a9aaa838 Mon Sep 17 00:00:00 2001 From: Tim Chow Date: Thu, 31 Oct 2024 14:48:51 -0500 Subject: [PATCH] Refactor BraintreeClient Constructors (#1199) * Refactor BraintreeClient constructors and remove BraintreeClientParams and BraintreeOptions * Fix doc typo --- .../api/core/BraintreeClient.kt | 71 +++++--------- .../api/core/BraintreeClientParams.kt | 42 -------- .../api/core/BraintreeOptions.kt | 12 --- .../api/core/BraintreeClientUnitTest.kt | 96 ++++++++----------- 4 files changed, 66 insertions(+), 155 deletions(-) delete mode 100644 BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeClientParams.kt delete mode 100644 BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeOptions.kt diff --git a/BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeClient.kt b/BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeClient.kt index 4cdfc055be..6582383a53 100644 --- a/BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeClient.kt +++ b/BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeClient.kt @@ -4,7 +4,6 @@ import android.content.Context import android.content.pm.ActivityInfo import android.net.Uri import androidx.annotation.RestrictTo -import androidx.annotation.VisibleForTesting import com.braintreepayments.api.sharedutils.HttpResponseCallback import com.braintreepayments.api.sharedutils.HttpResponseTiming import com.braintreepayments.api.sharedutils.ManifestValidator @@ -17,7 +16,7 @@ import org.json.JSONObject */ @Suppress("LargeClass", "LongParameterList", "TooManyFunctions") @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -class BraintreeClient @VisibleForTesting internal constructor( +class BraintreeClient internal constructor( /** * @suppress @@ -34,41 +33,26 @@ class BraintreeClient @VisibleForTesting internal constructor( */ val authorization: Authorization, - private val analyticsClient: AnalyticsClient, - private val httpClient: BraintreeHttpClient, - private val graphQLClient: BraintreeGraphQLClient, - private val configurationLoader: ConfigurationLoader, - private val manifestValidator: ManifestValidator, - private val time: Time, private val returnUrlScheme: String, - private val braintreeDeepLinkReturnUrlScheme: String, + /** * @suppress */ val appLinkReturnUri: Uri?, + + private val analyticsClient: AnalyticsClient = AnalyticsClient(applicationContext), + private val httpClient: BraintreeHttpClient = BraintreeHttpClient(), + private val graphQLClient: BraintreeGraphQLClient = BraintreeGraphQLClient(), + private val configurationLoader: ConfigurationLoader = ConfigurationLoader(applicationContext, httpClient), + private val manifestValidator: ManifestValidator = ManifestValidator(), + private val time: Time = Time(), ) { private val crashReporter: CrashReporter private var launchesBrowserSwitchAsNewTask: Boolean = false - // NOTE: this constructor is used to make dependency injection easy - internal constructor( - params: BraintreeClientParams, - time: Time = Time() - ) : this( - applicationContext = params.applicationContext, - integrationType = params.integrationType, - authorization = params.authorization, - analyticsClient = params.analyticsClient, - httpClient = params.httpClient, - graphQLClient = params.graphQLClient, - configurationLoader = params.configurationLoader, - manifestValidator = params.manifestValidator, - time = time, - returnUrlScheme = params.returnUrlScheme, - braintreeDeepLinkReturnUrlScheme = params.braintreeReturnUrlScheme, - appLinkReturnUri = params.appLinkReturnUri - ) + private val braintreeDeepLinkReturnUrlScheme: String = + "${getAppPackageNameWithoutUnderscores(applicationContext)}.braintree.deeplinkhandler" /** * @suppress @@ -78,27 +62,14 @@ class BraintreeClient @VisibleForTesting internal constructor( authorization: String, returnUrlScheme: String? = null, appLinkReturnUri: Uri? = null, + integrationType: IntegrationType? = null, ) : this( - BraintreeOptions( - context = context, - authorization = Authorization.fromString(authorization), - returnUrlScheme = returnUrlScheme, - appLinkReturnUri = appLinkReturnUri - ) - ) - - internal constructor(options: BraintreeOptions) : this(BraintreeClientParams(options)) - - internal constructor( - context: Context, - authorization: Authorization, - integrationType: IntegrationType - ) : this( - BraintreeOptions( - context = context, - authorization = authorization, - integrationType = integrationType, - ) + applicationContext = context.applicationContext, + authorization = Authorization.fromString(authorization), + returnUrlScheme = returnUrlScheme + ?: "${getAppPackageNameWithoutUnderscores(context.applicationContext)}.braintree", + appLinkReturnUri = appLinkReturnUri, + integrationType = integrationType ?: IntegrationType.CUSTOM, ) init { @@ -370,4 +341,10 @@ class BraintreeClient @VisibleForTesting internal constructor( val message = "Valid authorization required. See $clientSDKSetupURL for more info." return BraintreeException(message) } + + companion object { + private fun getAppPackageNameWithoutUnderscores(context: Context): String { + return context.applicationContext.packageName.replace("_", "") + } + } } diff --git a/BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeClientParams.kt b/BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeClientParams.kt deleted file mode 100644 index c162696fc3..0000000000 --- a/BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeClientParams.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.braintreepayments.api.core - -import android.content.Context -import android.net.Uri -import com.braintreepayments.api.BrowserSwitchClient -import com.braintreepayments.api.sharedutils.ManifestValidator - -internal data class BraintreeClientParams( - val context: Context, - val authorization: Authorization, - val returnUrlScheme: String, - val appLinkReturnUri: Uri?, - val httpClient: BraintreeHttpClient = BraintreeHttpClient(), - val graphQLClient: BraintreeGraphQLClient = BraintreeGraphQLClient(), - val analyticsClient: AnalyticsClient = AnalyticsClient(context), - val browserSwitchClient: BrowserSwitchClient = BrowserSwitchClient(), - val manifestValidator: ManifestValidator = ManifestValidator(), - val configurationLoader: ConfigurationLoader = ConfigurationLoader(context, httpClient), - val integrationType: IntegrationType, -) { - - constructor(options: BraintreeOptions) : this( - context = options.context, - authorization = options.authorization, - returnUrlScheme = options.returnUrlScheme ?: createDefaultReturnUrlScheme(options.context), - appLinkReturnUri = options.appLinkReturnUri, - integrationType = options.integrationType ?: IntegrationType.CUSTOM - ) - - val applicationContext: Context = context.applicationContext - val braintreeReturnUrlScheme = - "${getAppPackageNameWithoutUnderscores(context)}.braintree.deeplinkhandler" - - companion object { - - private fun getAppPackageNameWithoutUnderscores(context: Context) = - context.applicationContext.packageName.replace("_", "") - - private fun createDefaultReturnUrlScheme(context: Context) = - "${getAppPackageNameWithoutUnderscores(context)}.braintree" - } -} diff --git a/BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeOptions.kt b/BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeOptions.kt deleted file mode 100644 index d4afae4dcc..0000000000 --- a/BraintreeCore/src/main/java/com/braintreepayments/api/core/BraintreeOptions.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.braintreepayments.api.core - -import android.content.Context -import android.net.Uri - -internal data class BraintreeOptions( - val context: Context, - val authorization: Authorization, - val returnUrlScheme: String? = null, - val appLinkReturnUri: Uri? = null, - val integrationType: IntegrationType? = null, -) diff --git a/BraintreeCore/src/test/java/com/braintreepayments/api/core/BraintreeClientUnitTest.kt b/BraintreeCore/src/test/java/com/braintreepayments/api/core/BraintreeClientUnitTest.kt index deb4689927..f906d88533 100644 --- a/BraintreeCore/src/test/java/com/braintreepayments/api/core/BraintreeClientUnitTest.kt +++ b/BraintreeCore/src/test/java/com/braintreepayments/api/core/BraintreeClientUnitTest.kt @@ -66,8 +66,7 @@ class BraintreeClientUnitTest { .configuration(configuration) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) val callback = mockk(relaxed = true) sut.getConfiguration(callback) @@ -81,8 +80,7 @@ class BraintreeClientUnitTest { .configurationError(configFetchError) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) val callback = mockk(relaxed = true) sut.getConfiguration(callback) @@ -110,8 +108,7 @@ class BraintreeClientUnitTest { .configuration(configuration) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) val httpResponseCallback = mockk(relaxed = true) val networkResponseCallbackSlot = slot() @@ -135,8 +132,7 @@ class BraintreeClientUnitTest { .configurationError(configError) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) val httpResponseCallback = mockk(relaxed = true) sut.sendGET("sample-url", httpResponseCallback) @@ -164,8 +160,7 @@ class BraintreeClientUnitTest { .configuration(configuration) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) val networkResponseCallbackSlot = slot() val httpResponseCallback = mockk(relaxed = true) @@ -191,8 +186,7 @@ class BraintreeClientUnitTest { .configurationError(exception) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) val httpResponseCallback = mockk(relaxed = true) sut.sendPOST("sample-url", "{}", emptyMap(), httpResponseCallback) @@ -204,8 +198,7 @@ class BraintreeClientUnitTest { val configurationLoader = MockkConfigurationLoaderBuilder() .configuration(mockk(relaxed = true)) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) sut.sendPOST( url = "sample-url", @@ -230,8 +223,7 @@ class BraintreeClientUnitTest { val configurationLoader = MockkConfigurationLoaderBuilder() .configuration(mockk(relaxed = true)) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) val headers = mapOf("name" to "value") sut.sendPOST( @@ -273,8 +265,7 @@ class BraintreeClientUnitTest { .configuration(configuration) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) val httpResponseCallback = mockk(relaxed = true) val networkResponseCallbackSlot = slot() @@ -298,8 +289,7 @@ class BraintreeClientUnitTest { .configurationError(exception) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) val httpResponseCallback = mockk(relaxed = true) sut.sendGraphQLPOST(JSONObject(), httpResponseCallback) @@ -330,8 +320,7 @@ class BraintreeClientUnitTest { val time: Time = mockk() every { time.currentTime } returns 123 - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params, time) + val sut = createBraintreeClient(configurationLoader, time) sut.sendAnalyticsEvent("event.started") verify { @@ -350,8 +339,7 @@ class BraintreeClientUnitTest { .configurationError(Exception("error")) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) sut.sendAnalyticsEvent("event.started") verify { analyticsClient wasNot Called } @@ -367,8 +355,7 @@ class BraintreeClientUnitTest { ) } returns true - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) assertTrue( sut.isUrlSchemeDeclaredInAndroidManifest("a-url-scheme", FragmentActivity::class.java) ) @@ -381,15 +368,14 @@ class BraintreeClientUnitTest { manifestValidator.getActivityInfo(applicationContext, FragmentActivity::class.java) } returns activityInfo - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) assertSame(activityInfo, sut.getManifestActivityInfo(FragmentActivity::class.java)) } @Test fun returnUrlScheme_returnsUrlSchemeBasedOnApplicationIdByDefault() { val context = ApplicationProvider.getApplicationContext() - val sut = BraintreeClient(BraintreeOptions(context, authorization)) + val sut = BraintreeClient(context, authorization.toString()) assertEquals("com.braintreepayments.api.core.test.braintree", sut.getReturnUrlScheme()) } @@ -398,10 +384,9 @@ class BraintreeClientUnitTest { val context = ApplicationProvider.getApplicationContext() val returnUrlScheme = "custom-url-scheme" val sut = BraintreeClient( - BraintreeOptions( - context, authorization, returnUrlScheme = - returnUrlScheme - ) + context = context, + authorization = authorization.toString(), + returnUrlScheme = returnUrlScheme ) assertEquals("custom-url-scheme", sut.getReturnUrlScheme()) } @@ -409,7 +394,7 @@ class BraintreeClientUnitTest { @Test fun returnUrlScheme_whenDefaultDeepLinkHandlerEnabled_returnsDefaultDeepLinkHandlerScheme() { val context = ApplicationProvider.getApplicationContext() - val sut = BraintreeClient(BraintreeOptions(context, authorization)) + val sut = BraintreeClient(context, authorization.toString()) sut.launchesBrowserSwitchAsNewTask(true) assertEquals( "com.braintreepayments.api.core.test.braintree.deeplinkhandler", @@ -420,14 +405,18 @@ class BraintreeClientUnitTest { @Test fun integrationType_returnsCustomByDefault() { val context = ApplicationProvider.getApplicationContext() - val sut = BraintreeClient(BraintreeOptions(context, authorization)) + val sut = BraintreeClient(context, authorization.toString()) assertEquals("custom", sut.integrationType.stringValue) } @Test fun integrationType_returnsIntegrationTypeDefinedInConstructor() { val context = ApplicationProvider.getApplicationContext() - val sut = BraintreeClient(context, authorization, IntegrationType.DROP_IN) + val sut = BraintreeClient( + context = context, + authorization = authorization.toString(), + integrationType = IntegrationType.DROP_IN + ) assertEquals("dropin", sut.integrationType.stringValue) } @@ -438,8 +427,7 @@ class BraintreeClientUnitTest { val configurationLoader = MockkConfigurationLoaderBuilder() .configuration(configuration) .build() - val params = createDefaultParams(configurationLoader) - val sut = BraintreeClient(params) + val sut = createBraintreeClient(configurationLoader) sut.reportCrash() val callbackSlot = slot() @@ -459,20 +447,20 @@ class BraintreeClientUnitTest { } } - private fun createDefaultParams( - configurationLoader: ConfigurationLoader - ): BraintreeClientParams = - BraintreeClientParams( - context = context, - authorization = authorization, - returnUrlScheme = "sample-return-url-scheme", - appLinkReturnUri = Uri.parse("https://example.com"), - httpClient = braintreeHttpClient, - graphQLClient = braintreeGraphQLClient, - analyticsClient = analyticsClient, - browserSwitchClient = browserSwitchClient, - manifestValidator = manifestValidator, - configurationLoader = configurationLoader, - integrationType = IntegrationType.CUSTOM - ) + private fun createBraintreeClient( + configurationLoader: ConfigurationLoader, + time: Time = Time() + ) = BraintreeClient( + applicationContext = applicationContext, + integrationType = IntegrationType.CUSTOM, + authorization = authorization, + returnUrlScheme = "sample-return-url-scheme", + appLinkReturnUri = Uri.parse("https://example.com"), + httpClient = braintreeHttpClient, + graphQLClient = braintreeGraphQLClient, + analyticsClient = analyticsClient, + manifestValidator = manifestValidator, + configurationLoader = configurationLoader, + time = time + ) }