Skip to content

Commit

Permalink
Add Error when Tokenization Key is Used for ShopperInsights (#1057)
Browse files Browse the repository at this point in the history
* Add error when tokenization key is used for ShopperInsights
  • Loading branch information
jaxdesmarais authored Jul 11, 2024
1 parent 681435c commit 26f69af
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 17 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

* PayPal
* Fix issue that causes a JSON parsing error when Pay Later is selected during checkout.
* ShopperInsights (BETA)
* Add error when using an invalid authorization type

## 4.49.0 (2024-07-08)

Expand Down
3 changes: 3 additions & 0 deletions ShopperInsights/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ dependencies {
testImplementation deps.jsonAssert
testImplementation deps.kotlinTest
testImplementation deps.mockk
testImplementation deps.robolectric
testImplementation deps.junitTest
testImplementation project(':TestUtils')
}

// region signing and publishing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class ShopperInsightsClient @VisibleForTesting internal constructor(
/**
* Retrieves recommended payment methods based on the provided shopper insights request.
*
* @param context Android context
* @param request The [ShopperInsightsRequest] containing information about the shopper.
* @return A [ShopperInsightsResult] object indicating the recommended payment methods.
* Note: This feature is in beta. Its public API may change or be removed in future releases
Expand All @@ -54,23 +53,43 @@ class ShopperInsightsClient @VisibleForTesting internal constructor(
return
}

api.findEligiblePayments(
EligiblePaymentsApiRequest(
request,
currencyCode = currencyCode,
countryCode = countryCode,
accountDetails = includeAccountDetails,
constraintType = constraintType,
paymentSources = paymentSources
),
callback = { result, error ->
handleFindEligiblePaymentsResult(
result,
error,
callback
)
braintreeClient.getAuthorization { authorization, authorizationError ->
if (authorization != null) {
when (authorization) {
is TokenizationKey -> {
callbackFailure(
callback = callback,
error = BraintreeException(
"Invalid authorization. This feature can only be used with a client token."
)
)
return@getAuthorization
}

is ClientToken -> {
api.findEligiblePayments(
EligiblePaymentsApiRequest(
request,
currencyCode = currencyCode,
countryCode = countryCode,
accountDetails = includeAccountDetails,
constraintType = constraintType,
paymentSources = paymentSources
),
callback = { result, error ->
handleFindEligiblePaymentsResult(
result,
error,
callback
)
}
)
}
}
} else if (authorizationError != null) {
callbackFailure(callback = callback, error = BraintreeException(authorizationError?.message))
}
)
}
}

private fun handleFindEligiblePaymentsResult(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.braintreepayments.api

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
Expand All @@ -8,6 +10,8 @@ import io.mockk.slot
import io.mockk.verify
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
Expand All @@ -19,18 +23,25 @@ import kotlin.test.assertTrue
* It focuses on testing how the client handles different scenarios when fetching recommended
* payment methods.
*/
@RunWith(RobolectricTestRunner::class)
@OptIn(ExperimentalBetaApi::class)
class ShopperInsightsClientUnitTest {

private lateinit var sut: ShopperInsightsClient
private lateinit var api: ShopperInsightsApi
private lateinit var braintreeClient: BraintreeClient
private lateinit var context: Context

private val authorizationCallbackSlot = slot<AuthorizationCallback>()

@Before
fun beforeEach() {
api = mockk(relaxed = true)
braintreeClient = mockk(relaxed = true)
sut = ShopperInsightsClient(api, braintreeClient)
context = ApplicationProvider.getApplicationContext()

every { braintreeClient.getAuthorization(capture(authorizationCallbackSlot)) } just runs
}

@Test
Expand Down Expand Up @@ -365,6 +376,27 @@ class ShopperInsightsClientUnitTest {
verifySuccessAnalyticsEvent()
}

@Test
fun `test getRecommendPaymentMethods is called with a tokenization key, error is sent`() {
val braintreeClient = MockkBraintreeClientBuilder()
.authorizationSuccess(Authorization.fromString(Fixtures.TOKENIZATION_KEY))
.build()

sut = ShopperInsightsClient(api, braintreeClient)

val request = ShopperInsightsRequest("some-email", null)
sut.getRecommendedPaymentMethods(request) { result ->
assertTrue { result is ShopperInsightsResult.Failure }
assertTrue {
(result as ShopperInsightsResult.Failure).error is BraintreeException
}
assertEquals(
"Invalid authorization. This feature can only be used with a client token.",
(result as ShopperInsightsResult.Failure).error.message
)
}
}

@Test
fun `test paypal presented analytics event`() {
sut.sendPayPalPresentedEvent()
Expand Down Expand Up @@ -399,6 +431,7 @@ class ShopperInsightsClientUnitTest {
every { api.findEligiblePayments(any(), capture(apiCallbackSlot)) } just runs

sut.getRecommendedPaymentMethods(request, callback)
authorizationCallbackSlot.captured.onAuthorizationResult(ClientToken(Fixtures.BASE64_CLIENT_TOKEN), null)

apiCallbackSlot.captured.onResult(result = result, error = error)
}
Expand Down
1 change: 1 addition & 0 deletions ShopperInsights/src/test/resources/robolectric.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sdk=28

0 comments on commit 26f69af

Please sign in to comment.