From 38262dc7aeae4ebd17bece00ab7f721dd279009f Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Wed, 5 Jun 2024 10:33:55 +0200 Subject: [PATCH 01/16] Add MockWebServer dependency COAND-852 --- dependencies.gradle | 1 + example-app/build.gradle | 1 + gradle/verification-metadata.xml | 8 ++++++++ 3 files changed, 10 insertions(+) diff --git a/dependencies.gradle b/dependencies.gradle index b37d9cfdda..354dc132ff 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -177,6 +177,7 @@ ext { "org.mockito:mockito-android:$mockito_version", "org.mockito.kotlin:mockito-kotlin:$mockito_kotlin_version" ], + mockWebServer : "com.squareup.okhttp3:mockwebserver:$okhttp_version", robolectric : "org.robolectric:robolectric:$robolectric_version" ] } diff --git a/example-app/build.gradle b/example-app/build.gradle index 117eaf705f..ded9a555e0 100644 --- a/example-app/build.gradle +++ b/example-app/build.gradle @@ -112,6 +112,7 @@ dependencies { androidTestImplementation testLibraries.barista androidTestImplementation testLibraries.espresso androidTestImplementation testLibraries.hilt + androidTestImplementation testLibraries.mockWebServer kspAndroidTest testLibraries.hiltCompiler } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index de745624d3..1527b2c87c 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -7501,6 +7501,14 @@ + + + + + + + + From 0ce8f0e7b545e4c6dfefe5c9d6eff08f9e1a268f Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 10:35:07 +0200 Subject: [PATCH 02/16] Setup MockWebServer that delegates requests COAND-852 --- .../androidTest/assets/sessions_response.json | 43 ++++++++++++++++ .../checkout/server/CheckoutMockWebServer.kt | 51 +++++++++++++++++++ .../server/DelegatingBackendDispatcher.kt | 33 ++++++++++++ .../server/service/MockBackendService.kt | 32 ++++++++++++ .../server/service/MockCheckoutService.kt | 21 ++++++++ 5 files changed, 180 insertions(+) create mode 100644 example-app/src/androidTest/assets/sessions_response.json create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/server/CheckoutMockWebServer.kt create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/server/service/MockBackendService.kt create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/server/service/MockCheckoutService.kt diff --git a/example-app/src/androidTest/assets/sessions_response.json b/example-app/src/androidTest/assets/sessions_response.json new file mode 100644 index 0000000000..8430cf0ad9 --- /dev/null +++ b/example-app/src/androidTest/assets/sessions_response.json @@ -0,0 +1,43 @@ +{ + "amount" : { + "currency" : "EUR", + "value" : 1337 + }, + "authenticationData" : { + "attemptAuthentication" : "always", + "threeDSRequestData" : { + "nativeThreeDS" : "preferred" + } + }, + "channel" : "Android", + "countryCode" : "NL", + "expiresAt" : "2024-06-05T16:27:48+02:00", + "id" : "CSB0C8F0236F487105", + "lineItems" : [ + { + "amountExcludingTax" : 100, + "amountIncludingTax" : 100, + "description" : "Coffee", + "id" : "1717594066496", + "quantity" : 2, + "taxAmount" : 0, + "taxCategory" : "Low", + "taxPercentage" : 0 + } + ], + "merchantAccount" : "TestMerchantCheckout", + "recurringProcessingModel" : "Subscription", + "reference" : "android-test-components_1717594066497", + "returnUrl" : "adyencheckout:\/\/com.adyen.checkout.example", + "shopperEmail" : "", + "shopperIP" : "142.12.31.22", + "shopperLocale" : "en-US", + "shopperReference" : "test-android-components", + "showInstallmentAmount" : false, + "showRemovePaymentMethodButton" : true, + "splitCardFundingSources" : false, + "storePaymentMethodMode" : "askForConsent", + "threeDSAuthenticationOnly" : false, + "mode" : "embedded", + "sessionData" : "Ab02b4c0!BQABAgBE0IYldLlPrH34SYYyEx0dSnNuCbvnT1qo3F6J+pZqAydHpR\/DCqsmqaFL6fI8SREvHZX9ofDeHxgz2MlpKxBlqWFwz1w5\/nwfQVNbPgpXyYFnQv4I3SlXU2akUq6V1tzRcDEEuD8w29wyn3wpX+VXQKVObF98CB7b4Ood1N45MyCyRaoyOZhnYB1Sldn9+3pDvCk1xOLsQi\/wRL2FcBTBuwhIb10SgXTxoEXjXwtmhpYs09\/XRcsRE22smSDNFNrG9z5B3ZseJrVvnCf8nC0THHfC8wtESigHL7onUNYCVfnLG71B0IPsIykqq8wxjdTJqSqhRlVl1+Rc3f99IRjokM6HBEarPLndZi7VjV53zZCOeAG8TxZTWFT1aCTxH4fsNmW\/ntiDaFRfDXeTgavB99H6orD808RSkF1L9u\/a62Jfq9+CUkzGIV77cuJHhJzGuTdCL5rmNzJBxiJclMaeEq68zpdg3eHj1bwMdKQ8jOZ7FEG19jLJQUtjG2NejbiSdjOQBWJwWvFnuHbD+sOf9X5Ask9nb\/qjHNgXONDTpMHO7Km5vIoBDTzSZKuxc9EXKw8fACxmqjnlyLRA0OhM07pnDoeSIVkO53xGUr3C7KXnOKScj+1aYIHC2G6+2crfuXc0oSoxOERGTrie3RoCGaY59angiMud3wEAmGn\/JQyi0Q19AD7EDWfebNkASnsia2V5IjoiQUYwQUFBMTAzQ0E1MzdFQUVEODdDMjRERDUzOTA5QjgwQTc4QTkyM0UzODIzRDY4REFDQzk0QjlGRjgzMDVEQyJ9RTQG\/9vJd8g1y6GvceA9zDmq72L2k8hlYyyN\/DVDQNucnxOU824ZzomPnGloqwr6aKTBmsVmrp6Dy6fF3FiOxc2KSlOsYTEOl7frv5oBH8BHAPt8XZyCMBeGPcRwoTP4wUptwo\/cOmo4fcY2yEp+XsClTGkPfqAjjTpiFx4XrcL3EX2P058WYozS7BJqhh3FWJ51\/OoSPWJzro+ssbbPv3v9WyTD4gh1FqKeWp4harAoAQhPeYQQcWKWQWjGR0gInSSmJgU2mhwPW+IomgihsRDXXQWDf4NHd\/P3KorMz4oinKT5Snn0j1ygKOYkB1cPP56h0vi1t8iXboPC+5HMPgdrGpl+W+\/XKRjC6iSx2qhEylqV\/ULpoQlbQz22aNa6XPDCVPDRiXdNvN+IeBCmEUl6MuqQAGfhBpp56MGea4THQ2nT6pAp7eAt1EgoNFPYVgVOnkKQK4Skt5KnOlRQB8yFxJrnsYtpAocM0y+nLw+bbkkhL0B2bR8TPRN4VuWock7yqN9aoHLpncXn2ub5V9preoav6\/6jyCwLphAk60l1IPjnQTFUhmVefIFBL4aJ90JU8fJ8Kalyg3mDG0cH3GZOIaeMDeolCjE6KbGTGV34O5calXn+3mhzPZlcZiCAFo3CPGsT+rOu8kF66Ka9h3ti\/0B+cMVRuJ\/PnX1Krf3ku9uBKNHGQ+DwgUEL2ze\/rNg4xZX+\/HNFQv6TfqAU7CLnSuTCO2h+93EomTAHoM6AjrHSs97LARaOt4j3bEIiv4A+BhZfNx6OaRq8EWP9AqpU\/ZxehJts21chBFM+5IcV\/2gzl5v6OhLJUW7Vr3PcQF4+c0jCuSdgulMhZn\/7+9+Y2ayv8olCHWaBcO6Ce+c4kunOQjupwSI865o81WUvGPHfQ3BgAOYAGxYdP\/R2AD5rGV5tEVoIyly6VdrHohEmxzYQdcPmLFchWyXsGueyw\/D4W6p\/CeW8DyfmZnrnXiBgNfmHwo0JHAorcEK3XE13FTDXud4p7DXxBjHyDHAkiMM2thOunro4HnmT\/RwXJgtPlB5O42edLMKA6wplz5jh+dulUiQhBvwBYxjClR+fXTG7X9x+HULtgX2TcAHNG6y8YButEjVt50mCwGWtyS0oTAgrGT9jxnUc5ecsniyqDbuy2Be89CGk\/Hoxa4BQ0+HbKHWO0QWYkrvvITVS\/xkdw+dD1VRkxRtK1WbtIojWaNlvU2oi6pgszo0vVx2fBupsKNZyITNbLu50\/DxffBuYh9jS" +} diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/CheckoutMockWebServer.kt b/example-app/src/androidTest/java/com/adyen/checkout/server/CheckoutMockWebServer.kt new file mode 100644 index 0000000000..fd3815d3bd --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/server/CheckoutMockWebServer.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 5/6/2024. + */ + +package com.adyen.checkout.server + +import com.adyen.checkout.core.AdyenLogLevel +import com.adyen.checkout.core.internal.util.adyenLog +import okhttp3.mockwebserver.MockWebServer +import java.io.IOException + +object CheckoutMockWebServer { + + private const val DEFAULT_PORT = 8080 + + const val baseUrl = "http://127.0.0.1:8080/" + + private var mockWebServer: MockWebServer? = null + + fun start(): MockWebServer { + stop() + + val newServer = MockWebServer() + mockWebServer = newServer + + newServer.dispatcher = DelegatingBackendDispatcher() + + try { + newServer.start(DEFAULT_PORT) + } catch (e: IOException) { + adyenLog(AdyenLogLevel.ERROR, e) { "Failed to start mock web server." } + } + + return newServer + } + + fun stop() { + try { + mockWebServer?.let { + it.shutdown() + mockWebServer = null + } + } catch (e: IOException) { + adyenLog(AdyenLogLevel.ERROR, e) { "Failed to stop mock web server." } + } + } +} diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt b/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt new file mode 100644 index 0000000000..c1dd2f0074 --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 5/6/2024. + */ + +package com.adyen.checkout.server + +import com.adyen.checkout.core.AdyenLogLevel +import com.adyen.checkout.core.internal.util.adyenLog +import com.adyen.checkout.server.service.MockBackendService +import okhttp3.mockwebserver.Dispatcher +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.RecordedRequest +import java.net.HttpURLConnection.HTTP_INTERNAL_ERROR +import java.net.HttpURLConnection.HTTP_NOT_FOUND + +internal class DelegatingBackendDispatcher : Dispatcher() { + + private val delegates = listOf() + + override fun dispatch(request: RecordedRequest): MockResponse = try { + val service = delegates.firstOrNull { it.canHandleRequest(request) } + + service?.handleRequest(request) + ?: MockResponse().setResponseCode(HTTP_NOT_FOUND).setBody("Resource not found") + } catch (e: Exception) { + adyenLog(AdyenLogLevel.ERROR, e) { "Could not handle request: $request" } + MockResponse().setResponseCode(HTTP_INTERNAL_ERROR).setBody("Unexpected error") + } +} diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockBackendService.kt b/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockBackendService.kt new file mode 100644 index 0000000000..b8b3970e2d --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockBackendService.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 5/6/2024. + */ + +package com.adyen.checkout.server.service + +import com.adyen.checkout.util.JsonFileReader +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.RecordedRequest +import java.net.HttpURLConnection.HTTP_OK + +internal abstract class MockBackendService( + vararg paths: String, + private val useRegex: Boolean = false +) { + + private val pathSet = paths.toSet() + + fun canHandleRequest(request: RecordedRequest): Boolean = if (useRegex) { + pathSet.any { + Regex(it).matches(request.requestUrl?.encodedPath.orEmpty()) + } + } else { + request.requestUrl?.encodedPath in pathSet + } + + abstract fun handleRequest(request: RecordedRequest): MockResponse +} diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockCheckoutService.kt b/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockCheckoutService.kt new file mode 100644 index 0000000000..43b18ea096 --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockCheckoutService.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 5/6/2024. + */ + +package com.adyen.checkout.server.service + +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.RecordedRequest + +internal class MockCheckoutService : MockBackendService( + "/sessions" +) { + + override fun handleRequest(request: RecordedRequest): MockResponse { + return createJsonResponse("sessions_response.json") + } +} From 303f3ee93f4aa84f7e643e4c1a06477f1e88556e Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 10:39:10 +0200 Subject: [PATCH 03/16] Read JSON responses from asset files COAND-852 --- .../server/service/MockBackendService.kt | 8 ++++++ .../com/adyen/checkout/util/JsonFileReader.kt | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/util/JsonFileReader.kt diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockBackendService.kt b/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockBackendService.kt index b8b3970e2d..63aa079288 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockBackendService.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockBackendService.kt @@ -29,4 +29,12 @@ internal abstract class MockBackendService( } abstract fun handleRequest(request: RecordedRequest): MockResponse + + companion object { + + fun createJsonResponse(fileName: String) = MockResponse() + .setResponseCode(HTTP_OK) + .setHeader("Content-Type", "application/json") + .setBody(JsonFileReader(fileName)) + } } diff --git a/example-app/src/androidTest/java/com/adyen/checkout/util/JsonFileReader.kt b/example-app/src/androidTest/java/com/adyen/checkout/util/JsonFileReader.kt new file mode 100644 index 0000000000..75dafd0db3 --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/util/JsonFileReader.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 5/6/2024. + */ + +package com.adyen.checkout.util + +import androidx.test.platform.app.InstrumentationRegistry +import dagger.hilt.android.testing.HiltTestApplication +import java.io.InputStreamReader + +internal object JsonFileReader { + + operator fun invoke(fileName: String): String { + val application = + (InstrumentationRegistry.getInstrumentation().context) + val inputStream = application.assets.open(fileName) + val stringBuilder = StringBuilder() + val reader = InputStreamReader(inputStream) + reader.readLines().forEach { stringBuilder.append(it) } + return stringBuilder.toString() + } +} From f7774aa2bdb26aea2001bba3643bf51bc5c415fb Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 10:43:43 +0200 Subject: [PATCH 04/16] Mock /sessions COAND-852 --- .../adyen/checkout/server/DelegatingBackendDispatcher.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt b/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt index c1dd2f0074..21a08dbe26 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt @@ -10,7 +10,7 @@ package com.adyen.checkout.server import com.adyen.checkout.core.AdyenLogLevel import com.adyen.checkout.core.internal.util.adyenLog -import com.adyen.checkout.server.service.MockBackendService +import com.adyen.checkout.server.service.MockCheckoutService import okhttp3.mockwebserver.Dispatcher import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.RecordedRequest @@ -19,7 +19,9 @@ import java.net.HttpURLConnection.HTTP_NOT_FOUND internal class DelegatingBackendDispatcher : Dispatcher() { - private val delegates = listOf() + private val delegates = listOf( + MockCheckoutService(), + ) override fun dispatch(request: RecordedRequest): MockResponse = try { val service = delegates.firstOrNull { it.canHandleRequest(request) } From 3827c68ffe31eaa8af44147bd2b61aeab19b8409 Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 10:44:33 +0200 Subject: [PATCH 05/16] Mock /sessions/*/setup COAND-852 --- .../assets/sessions_setup_response.json | 273 ++++++++++++++++++ .../server/DelegatingBackendDispatcher.kt | 2 + .../server/service/MockSessionService.kt | 22 ++ 3 files changed, 297 insertions(+) create mode 100644 example-app/src/androidTest/assets/sessions_setup_response.json create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/server/service/MockSessionService.kt diff --git a/example-app/src/androidTest/assets/sessions_setup_response.json b/example-app/src/androidTest/assets/sessions_setup_response.json new file mode 100644 index 0000000000..8b5b878fbd --- /dev/null +++ b/example-app/src/androidTest/assets/sessions_setup_response.json @@ -0,0 +1,273 @@ +{ + "amount" : { + "currency" : "EUR", + "value" : 1337 + }, + "countryCode" : "NL", + "expiresAt" : "2024-06-05T16:27:48+02:00", + "id" : "CSB0C8F0236F487105", + "returnUrl" : "adyencheckout:\/\/com.adyen.checkout.example", + "shopperLocale" : "en-US", + "configuration" : { + "enableStoreDetails" : true, + "showInstallmentAmount" : false, + "showRemovePaymentMethodButton" : true + }, + "paymentMethods" : { + "paymentMethods" : [ + { + "issuers" : [ + { + "id" : "1164", + "name" : "SNS" + }, + { + "id" : "1121", + "name" : "Test Issuer" + }, + { + "id" : "1154", + "name" : "Test Issuer 5" + }, + { + "id" : "1165", + "name" : "iDeal Test Issuer" + }, + { + "id" : "1153", + "name" : "Test Issuer 4" + }, + { + "id" : "1152", + "name" : "Test Issuer 3" + }, + { + "id" : "1163", + "name" : "Ideal bridge test issuer" + }, + { + "id" : "1151", + "name" : "Test Issuer 2" + }, + { + "id" : "1162", + "name" : "Test Issuer Cancelled" + }, + { + "id" : "1161", + "name" : "Test Issuer Pending" + }, + { + "id" : "1160", + "name" : "Test Issuer Refused" + }, + { + "id" : "1159", + "name" : "Test Issuer 10" + }, + { + "id" : "1158", + "name" : "Test Issuer 9" + }, + { + "id" : "1157", + "name" : "Test Issuer 8" + }, + { + "id" : "1156", + "name" : "Test Issuer 7" + }, + { + "id" : "1155", + "name" : "Test Issuer 6" + } + ], + "name" : "iDEAL", + "type" : "ideal" + }, + { + "brands" : [ + "mc", + "visa", + "bijcard", + "amex", + "maestro", + "accel", + "cup", + "diners", + "discover", + "hipercard", + "jcb", + "nyce", + "pulse", + "sodexo", + "star", + "vale_refeicao", + "vale_refeicao_prepaid" + ], + "configuration" : { + "mcDpaId" : "6d41d4d6-45b1-42c3-a5d0-a28c0e69d4b1_dpa2", + "visaSrcInitiatorId" : "B9SECVKIQX2SOBQ6J9X721dVBBKHhJJl1nxxVbemHGn5oB6S8", + "mcSrcClientId" : "6d41d4d6-45b1-42c3-a5d0-a28c0e69d4b1", + "visaSrciDpaId" : "8e6e347c-254e-863f-0e6a-196bf2d9df02" + }, + "name" : "Credit Card", + "type" : "scheme" + }, + { + "configuration" : { + "merchantId" : "M6TNAESZ5FGNN", + "intent" : "authorize" + }, + "name" : "PayPal", + "type" : "paypal" + }, + { + "name" : "Riverty Invoice", + "type" : "afterpay_default" + }, + { + "name" : "SEPA Direct Debit", + "type" : "sepadirectdebit" + }, + { + "name" : "Paysafecard", + "type" : "paysafecard" + }, + { + "name" : "AliPay", + "type" : "alipay_wap" + }, + { + "name" : "Android Pay", + "type" : "androidpay" + }, + { + "name" : "c_cash", + "type" : "c_cash" + }, + { + "name" : "Alfamart", + "type" : "doku_alfamart" + }, + { + "brand" : "genericgiftcard", + "name" : "Generic GiftCard", + "type" : "giftcard" + }, + { + "brand" : "givex", + "name" : "Givex", + "type" : "giftcard" + }, + { + "configuration" : { + "merchantId" : "50", + "gatewayMerchantId" : "TestMerchantCheckout" + }, + "name" : "Google Pay", + "type" : "googlepay" + }, + { + "name" : "Pay over time with Klarna.", + "type" : "klarna_account" + }, + { + "name" : "Pay by Invoice for Businesses", + "type" : "klarna_b2b" + }, + { + "name" : "Up Titre-Restaurant", + "type" : "mealVoucher_FR_groupeup" + }, + { + "name" : "Bimpli (ex Apetiz) Titre-Restaurant", + "type" : "mealVoucher_FR_natixis" + }, + { + "name" : "Sodexo Titre-Restaurant", + "type" : "mealVoucher_FR_sodexo" + }, + { + "brand" : "plastix", + "name" : "Plastix", + "type" : "giftcard" + }, + { + "name" : "UnionPay", + "type" : "unionpay" + }, + { + "name" : "UPI Collect", + "type" : "upi_collect" + }, + { + "name" : "WeChat Pay", + "type" : "wechatpayMiniProgram" + }, + { + "name" : "WeChat Pay", + "type" : "wechatpayQR" + }, + { + "name" : "WeChat Pay", + "type" : "wechatpaySDK" + }, + { + "name" : "WeChat Pay", + "type" : "wechatpayWeb" + }, + { + "name" : "Pay later with Klarna.", + "type" : "klarna" + }, + { + "configuration" : { + "merchantId" : "A3SKIS53IXYBBU", + "storeId" : "amzn1.application-oa2-client.4cedd73b56134e5ea57aaf487bf5c77e", + "region" : "UK", + "publicKeyId" : "AG77NIXPURMDUC3DOC5WQPPH" + }, + "name" : "Amazon Pay", + "type" : "amazonpay" + }, + { + "brand" : "monizze_eco", + "name" : "Monizze Eco Card", + "type" : "giftcard" + }, + { + "brand" : "monizze_gift", + "name" : "Monizze Gift Card", + "type" : "giftcard" + }, + { + "brand" : "monizze_mealvoucher", + "name" : "Monizze Meal Voucher", + "type" : "giftcard" + } + ], + "storedPaymentMethods" : [ + { + "brand" : "mc", + "expiryMonth" : "03", + "expiryYear" : "30", + "holderName" : "Checkout Shopper PlaceHolder", + "id" : "B8DH7GX5G9QKTH65", + "lastFour" : "5454", + "name" : "MasterCard", + "supportedRecurringProcessingModels" : [ + "Subscription", + "UnscheduledCardOnFile", + "CardOnFile" + ], + "supportedShopperInteractions" : [ + "ContAuth", + "Ecommerce" + ], + "type" : "scheme" + } + ] + }, + "sessionData" : "Ab02b4c0!BQABAgBtv\/cy5Dv8Bc8dZ6wG6NfbNNec1RGytpRl+MBuvumeAmv8Vybv7Bi+jdzFps3wogC02fd3rXL3RcYrE6ksxJMM\/u61FnbT6q3lehlUuKtec91HTpSw0LTZD128T5Y9p0cfG4xpB1rDphVwtuJT8NbTUNKC45yVM40JyY30pvn0ZqO9TjE66jN\/QyCe4FVjEDtkd5FBIqvmWO2KWcwjamfgGJ2VWb\/LPflJttDCSVrf6ye9odnWs+RL0B1m+3Fze96bOFsyBz85r30LtM3cSw8TIA3VEmx+1b+jc6qIDsAQfcWdk8q\/WnF6zBdAU0HEWdZbVA3dw9UKt6+B0eeYH41Ag4Upb3gWIsNVpHHdRVh3S72aVxWJE0tOY1jt7AD1fe3wporLR6OxFaVdj2hsrBmOKy9YqZr5MKDRN5V3NbdrVue6gfhYGfkGwVs2vKFnR+L4T8j0P4gJczamLT11y8KRS4ACVxkBuUgE56bbvg+aj0lipQhgC11EdD6kcvYqEY96qxz4qzVAHvM6cXBHYGcHXQHihhTLrV9DnIH97q+bKT9GoI409n1qtyiY\/XMZd0YeqeHp7C57MEUQaEN1BTXwkgfh8rTgPmzNJfqOdnj9tIe8MWtu7ftB60nFGrz6NVorADVdCbtNoh6\/UXLSjvGjzRGb6B+nTx2\/1fmT5FUtQQyaN325pvUfDqSNMsgASnsia2V5IjoiQUYwQUFBMTAzQ0E1MzdFQUVEODdDMjRERDUzOTA5QjgwQTc4QTkyM0UzODIzRDY4REFDQzk0QjlGRjgzMDVEQyJ9ZrcTuv9Sz+HIzNPSVi93Y1V\/qqOVLsUlnZZgizZHKD4JMyzvTUhpmxDSsF+O\/wFnCgEr6MLZi8Pyjb+6yl7+CSz3xPONGSbaL69koTQsj6TmCdG+ZEJx+nOROE6InKfHJgIM7vItaDCXsq6Ynm5cebMhH9DzR9595j1uEybTaAoYVMeyd177tSSbd1W4opmIYUg9WalEfR9GTp8teYlaZYN1Pn8kTKer6tJGTujHO0d1Sz7uK26PFIVFMNvesQI08+\/EkYxyHwiTwtDlAoSsWaGWbXY8TYyo+IPWRwOCktv72iYEJgLkotRuEs6wTFLZ2sM6rz8Kd9lBfYtfFSlMaZy3hLUaTON4sx0\/IlJduXYPn2wEpiPPmIBMgndmhTGXxmebnNiGHKowRM7nG0pglTlgbac00OxrjKsW41KNIlFu7ig42PMB4NjekjoTXX4LhWjFf935X6hKcomPpthPrPoApoiOmLqdfbrev8CeQOsvkTCdOHRRLBFvDL9FQ4FHCl20e3g7\/GqkoJvcwBuxsjlJyZHILztRpUkIhErgL9jrhizTWz3zgEETQAoNVAFZXFdp0IS\/UmPCJ12y5ChmAnsKpkn8ppABBQuRcT7PbdeId+5+Plnq0BnYMDBxIEgfhxe2LYV\/FHzA6SshEuVpoAjg1Jf5HqNKXDwJGVbh5Ka2L\/6HXB1WiFrKMLA3M5SfXTCMPfhjZleNB7Yzrb\/ZmtR9eia7s3ntf6+7\/VDGkclZFy6wJf\/XsebJuiKCV07DkJK7zY5b\/ETOBurZ8GnT06YP6DNYquIsZ1+lzQEI6lTLrEUaTWEExqBfihr4eKUa8CXgqicQ1gnfB5d9JG0LEIA9p1udEe8MAsnNgfMmRvMzfOoZ7ZJ4ScUMdGR\/QnfnX8bA5UlpW7MA0rWEbjUI5TvNYXIUWZbRwom7znc+USJc8\/OpJJ9owIuxdj8zk1GpvcKTyRQojXuV+1ZPXzdRoBiSuJlS6RV91qiUgoaamt5uUU3ZlDeA\/bTyfx6tWO0S8RUtKCIae7xt\/AFfIzGN3xUkX3hBstV9qu07Cvx4llxnuKbk9X29L24Rvp2pT2ARVgD6cqB+HKRCYBvc0I\/+ctGp+kbhJ6CnWfvtDyhF228NYxOFYwpsovSkd7nZypUFLcJoMd\/7ZPPkcbC1kPRhIREUN9KeKW0lOPy7yaeDbflGqNjg6MHidFMkJuJq0cE30L5+RiL95EtCkxCCLP43vgYogBoDVoT7HblyHQL8\/Wwql7Re" +} diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt b/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt index 21a08dbe26..178565eb58 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt @@ -11,6 +11,7 @@ package com.adyen.checkout.server import com.adyen.checkout.core.AdyenLogLevel import com.adyen.checkout.core.internal.util.adyenLog import com.adyen.checkout.server.service.MockCheckoutService +import com.adyen.checkout.server.service.MockSessionService import okhttp3.mockwebserver.Dispatcher import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.RecordedRequest @@ -21,6 +22,7 @@ internal class DelegatingBackendDispatcher : Dispatcher() { private val delegates = listOf( MockCheckoutService(), + MockSessionService(), ) override fun dispatch(request: RecordedRequest): MockResponse = try { diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockSessionService.kt b/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockSessionService.kt new file mode 100644 index 0000000000..ab866b5607 --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockSessionService.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.server.service + +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.RecordedRequest + +internal class MockSessionService : MockBackendService( + "/v1/sessions/.*/setup", + useRegex = true, +) { + + override fun handleRequest(request: RecordedRequest): MockResponse { + return createJsonResponse("sessions_setup_response.json") + } +} From 06a5e52417ea48e27e2bd174104f45a8132ad97a Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 10:47:19 +0200 Subject: [PATCH 06/16] Mock /v1/clientKeys/* COAND-852 --- .../assets/public_key_response.json | 3 +++ .../server/DelegatingBackendDispatcher.kt | 2 ++ .../server/service/MockPublicKeyService.kt | 22 +++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 example-app/src/androidTest/assets/public_key_response.json create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/server/service/MockPublicKeyService.kt diff --git a/example-app/src/androidTest/assets/public_key_response.json b/example-app/src/androidTest/assets/public_key_response.json new file mode 100644 index 0000000000..8565821377 --- /dev/null +++ b/example-app/src/androidTest/assets/public_key_response.json @@ -0,0 +1,3 @@ +{ + "publicKey": "10001|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" +} diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt b/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt index 178565eb58..3152660aa4 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt @@ -11,6 +11,7 @@ package com.adyen.checkout.server import com.adyen.checkout.core.AdyenLogLevel import com.adyen.checkout.core.internal.util.adyenLog import com.adyen.checkout.server.service.MockCheckoutService +import com.adyen.checkout.server.service.MockPublicKeyService import com.adyen.checkout.server.service.MockSessionService import okhttp3.mockwebserver.Dispatcher import okhttp3.mockwebserver.MockResponse @@ -22,6 +23,7 @@ internal class DelegatingBackendDispatcher : Dispatcher() { private val delegates = listOf( MockCheckoutService(), + MockPublicKeyService(), MockSessionService(), ) diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockPublicKeyService.kt b/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockPublicKeyService.kt new file mode 100644 index 0000000000..023915fffd --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockPublicKeyService.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.server.service + +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.RecordedRequest + +internal class MockPublicKeyService : MockBackendService( + "/v1/clientKeys/.*", + useRegex = true, +) { + + override fun handleRequest(request: RecordedRequest): MockResponse { + return createJsonResponse("public_key_response.json") + } +} From 1f19a8de6f722b04ceb3ef5f2638480dbcdf5444 Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 10:49:29 +0200 Subject: [PATCH 07/16] Setup testing robots for main and drop-in COAND-852 --- .../src/main/res/layout/activity_drop_in.xml | 10 +++--- .../com/adyen/checkout/robot/DropInRobot.kt | 26 ++++++++++++++ .../com/adyen/checkout/robot/MainRobot.kt | 36 +++++++++++++++++++ .../com/adyen/checkout/robot/TestRobot.kt | 14 ++++++++ .../src/main/res/layout/activity_main.xml | 1 + 5 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/robot/DropInRobot.kt create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/robot/MainRobot.kt create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/robot/TestRobot.kt diff --git a/drop-in/src/main/res/layout/activity_drop_in.xml b/drop-in/src/main/res/layout/activity_drop_in.xml index a8d17c5e5c..87533742ef 100644 --- a/drop-in/src/main/res/layout/activity_drop_in.xml +++ b/drop-in/src/main/res/layout/activity_drop_in.xml @@ -1,5 +1,4 @@ - - - - \ No newline at end of file + diff --git a/example-app/src/androidTest/java/com/adyen/checkout/robot/DropInRobot.kt b/example-app/src/androidTest/java/com/adyen/checkout/robot/DropInRobot.kt new file mode 100644 index 0000000000..32ab449fef --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/robot/DropInRobot.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.robot + +import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed + +internal class DropInRobot : TestRobot { + + override fun verifyIsOnScreen() { + // Check if bottom sheet is displayed, because checking the layout from DropInActivity doesn't work + assertDisplayed(com.google.android.material.R.id.design_bottom_sheet) + } +} + +internal inline fun onDropIn(action: DropInRobot.() -> Unit) { + DropInRobot().apply { + verifyIsOnScreen() + action() + } +} diff --git a/example-app/src/androidTest/java/com/adyen/checkout/robot/MainRobot.kt b/example-app/src/androidTest/java/com/adyen/checkout/robot/MainRobot.kt new file mode 100644 index 0000000000..6eb7b8fc8c --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/robot/MainRobot.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.robot + +import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed +import com.adevinta.android.barista.interaction.BaristaCheckboxInteractions.check +import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn +import com.adyen.checkout.example.R + +internal class MainRobot : TestRobot { + + override fun verifyIsOnScreen() { + assertDisplayed(R.id.main_container) + } + + fun enableSessions() { + check(R.id.switch_sessions) + } + + fun startDropIn() { + clickOn("Start") + } +} + +internal inline fun onMain(action: MainRobot.() -> Unit) { + MainRobot().apply { + verifyIsOnScreen() + action() + } +} diff --git a/example-app/src/androidTest/java/com/adyen/checkout/robot/TestRobot.kt b/example-app/src/androidTest/java/com/adyen/checkout/robot/TestRobot.kt new file mode 100644 index 0000000000..4c363fe463 --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/robot/TestRobot.kt @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.robot + +internal interface TestRobot { + + fun verifyIsOnScreen() +} diff --git a/example-app/src/main/res/layout/activity_main.xml b/example-app/src/main/res/layout/activity_main.xml index 26cdcf52b1..d30fc35482 100644 --- a/example-app/src/main/res/layout/activity_main.xml +++ b/example-app/src/main/res/layout/activity_main.xml @@ -9,6 +9,7 @@ Date: Thu, 6 Jun 2024 10:50:40 +0200 Subject: [PATCH 08/16] Create test that asserts drop-in is displayed COAND-852 --- .../java/com/adyen/checkout/DropInTest.kt | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt diff --git a/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt b/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt new file mode 100644 index 0000000000..58bf39a298 --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import com.adyen.checkout.example.ui.main.MainActivity +import com.adyen.checkout.robot.onDropIn +import com.adyen.checkout.robot.onMain +import com.adyen.checkout.server.CheckoutMockWebServer +import dagger.hilt.android.testing.HiltAndroidRule +import dagger.hilt.android.testing.HiltAndroidTest +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +@HiltAndroidTest +internal class DropInTest { + + @get:Rule(order = 0) + var hiltRule = HiltAndroidRule(this) + + @get:Rule(order = 1) + var activityRule: ActivityScenarioRule = ActivityScenarioRule(MainActivity::class.java) + + @Before + fun before() { + CheckoutMockWebServer.start() + } + + @After + fun after() { + CheckoutMockWebServer.stop() + } + + @Test + fun whenDropInIsOpened_thenItIsDisplayed() { + onMain { + enableSessions() + startDropIn() + } + + onDropIn { + verifyIsOnScreen() + } + } +} From 46f550a1628800a5323dbe412b1b8385baaf6089 Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 10:52:11 +0200 Subject: [PATCH 09/16] Make base url injectable So we can override it in UI tests. COAND-852 --- .../adyen/checkout/di/FakeBaseUrlModule.kt | 29 +++++++++++++++++++ .../checkout/example/di/NetworkModule.kt | 17 ++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/di/FakeBaseUrlModule.kt diff --git a/example-app/src/androidTest/java/com/adyen/checkout/di/FakeBaseUrlModule.kt b/example-app/src/androidTest/java/com/adyen/checkout/di/FakeBaseUrlModule.kt new file mode 100644 index 0000000000..4d05344ad3 --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/di/FakeBaseUrlModule.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.di + +import com.adyen.checkout.example.di.BaseUrl +import com.adyen.checkout.example.di.NetworkModule +import com.adyen.checkout.server.CheckoutMockWebServer +import dagger.Module +import dagger.Provides +import dagger.hilt.components.SingletonComponent +import dagger.hilt.testing.TestInstallIn + +@Module +@TestInstallIn( + components = [SingletonComponent::class], + replaces = [NetworkModule.BaseUrlModule::class], +) +internal object FakeBaseUrlModule { + + @BaseUrl + @Provides + fun provideBaseUrl(): String = CheckoutMockWebServer.baseUrl +} diff --git a/example-app/src/main/java/com/adyen/checkout/example/di/NetworkModule.kt b/example-app/src/main/java/com/adyen/checkout/example/di/NetworkModule.kt index b0ad82c959..4103acbdbe 100644 --- a/example-app/src/main/java/com/adyen/checkout/example/di/NetworkModule.kt +++ b/example-app/src/main/java/com/adyen/checkout/example/di/NetworkModule.kt @@ -23,6 +23,7 @@ import retrofit2.Converter import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory import javax.inject.Named +import javax.inject.Qualifier import javax.inject.Singleton @Module @@ -73,9 +74,10 @@ object NetworkModule { internal fun provideRetrofit( okHttpClient: OkHttpClient, converterFactory: Converter.Factory, + @BaseUrl baseUrl: String, ): Retrofit = Retrofit.Builder() - .baseUrl(BuildConfig.MERCHANT_SERVER_URL) + .baseUrl(baseUrl) .client(okHttpClient) .addConverterFactory(converterFactory) .build() @@ -83,4 +85,17 @@ object NetworkModule { @Provides internal fun provideApiService(@Named("RetrofitCheckout") retrofit: Retrofit): CheckoutApiService = retrofit.create(CheckoutApiService::class.java) + + @Module + @InstallIn(SingletonComponent::class) + object BaseUrlModule { + + @BaseUrl + @Provides + fun provideBaseUrl(): String = BuildConfig.MERCHANT_SERVER_URL + } } + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class BaseUrl From 23152149e5c4234431ff3ad462a31b8b2ddc6b46 Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 10:53:47 +0200 Subject: [PATCH 10/16] Extract CheckoutConfigurationProvider into an interface So we can inject a fake implementation for UI tests later. COAND-852 --- .../example/di/ConfigurationModule.kt | 26 +++++++++++++++++++ .../CheckoutConfigurationProvider.kt | 4 +-- .../ui/configuration/ConfigurationProvider.kt | 16 ++++++++++++ .../checkout/example/ui/main/MainViewModel.kt | 4 +-- 4 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 example-app/src/main/java/com/adyen/checkout/example/di/ConfigurationModule.kt create mode 100644 example-app/src/main/java/com/adyen/checkout/example/ui/configuration/ConfigurationProvider.kt diff --git a/example-app/src/main/java/com/adyen/checkout/example/di/ConfigurationModule.kt b/example-app/src/main/java/com/adyen/checkout/example/di/ConfigurationModule.kt new file mode 100644 index 0000000000..51a94de5ba --- /dev/null +++ b/example-app/src/main/java/com/adyen/checkout/example/di/ConfigurationModule.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.example.di + +import com.adyen.checkout.example.ui.configuration.CheckoutConfigurationProvider +import com.adyen.checkout.example.ui.configuration.ConfigurationProvider +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +internal abstract class ConfigurationModule { + + @Singleton + @Binds + abstract fun bindConfigurationProvider(provider: CheckoutConfigurationProvider): ConfigurationProvider +} diff --git a/example-app/src/main/java/com/adyen/checkout/example/ui/configuration/CheckoutConfigurationProvider.kt b/example-app/src/main/java/com/adyen/checkout/example/ui/configuration/CheckoutConfigurationProvider.kt index f13bc2fba4..323f0363ab 100644 --- a/example-app/src/main/java/com/adyen/checkout/example/ui/configuration/CheckoutConfigurationProvider.kt +++ b/example-app/src/main/java/com/adyen/checkout/example/ui/configuration/CheckoutConfigurationProvider.kt @@ -34,7 +34,7 @@ import javax.inject.Singleton internal class CheckoutConfigurationProvider @Inject constructor( private val keyValueStorage: KeyValueStorage, @ApplicationContext private val context: Context, -) { +) : ConfigurationProvider { private val shopperLocale: Locale? get() { @@ -48,7 +48,7 @@ internal class CheckoutConfigurationProvider @Inject constructor( private val environment = Environment.TEST - val checkoutConfig: CheckoutConfiguration + override val checkoutConfig: CheckoutConfiguration get() = CheckoutConfiguration( environment = environment, clientKey = clientKey, diff --git a/example-app/src/main/java/com/adyen/checkout/example/ui/configuration/ConfigurationProvider.kt b/example-app/src/main/java/com/adyen/checkout/example/ui/configuration/ConfigurationProvider.kt new file mode 100644 index 0000000000..d258afcd5c --- /dev/null +++ b/example-app/src/main/java/com/adyen/checkout/example/ui/configuration/ConfigurationProvider.kt @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.example.ui.configuration + +import com.adyen.checkout.components.core.CheckoutConfiguration + +internal interface ConfigurationProvider { + + val checkoutConfig: CheckoutConfiguration +} diff --git a/example-app/src/main/java/com/adyen/checkout/example/ui/main/MainViewModel.kt b/example-app/src/main/java/com/adyen/checkout/example/ui/main/MainViewModel.kt index ccd060ec87..d51e1822fa 100644 --- a/example-app/src/main/java/com/adyen/checkout/example/ui/main/MainViewModel.kt +++ b/example-app/src/main/java/com/adyen/checkout/example/ui/main/MainViewModel.kt @@ -21,7 +21,7 @@ import com.adyen.checkout.example.repositories.PaymentsRepository import com.adyen.checkout.example.service.getPaymentMethodRequest import com.adyen.checkout.example.service.getSessionRequest import com.adyen.checkout.example.service.getSettingsInstallmentOptionsMode -import com.adyen.checkout.example.ui.configuration.CheckoutConfigurationProvider +import com.adyen.checkout.example.ui.configuration.ConfigurationProvider import com.adyen.checkout.sessions.core.CheckoutSession import com.adyen.checkout.sessions.core.CheckoutSessionProvider import com.adyen.checkout.sessions.core.CheckoutSessionResult @@ -40,7 +40,7 @@ internal class MainViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, private val paymentsRepository: PaymentsRepository, private val keyValueStorage: KeyValueStorage, - private val checkoutConfigurationProvider: CheckoutConfigurationProvider, + private val checkoutConfigurationProvider: ConfigurationProvider, ) : ViewModel() { private val lifecycleResumed: MutableSharedFlow = MutableSharedFlow() From 066710df3f8d99ae19fbeb16ad611e3570ddae0e Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 10:55:16 +0200 Subject: [PATCH 11/16] Inject fake CheckoutConfigurationProvider for UI tests COAND-852 --- .../checkout/di/FakeConfigurationModule.kt | 30 ++++++++++++ .../fake/FakeCheckoutConfigurationProvider.kt | 48 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/di/FakeConfigurationModule.kt create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/fake/FakeCheckoutConfigurationProvider.kt diff --git a/example-app/src/androidTest/java/com/adyen/checkout/di/FakeConfigurationModule.kt b/example-app/src/androidTest/java/com/adyen/checkout/di/FakeConfigurationModule.kt new file mode 100644 index 0000000000..dd700ad91e --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/di/FakeConfigurationModule.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.di + +import com.adyen.checkout.example.di.ConfigurationModule +import com.adyen.checkout.example.ui.configuration.ConfigurationProvider +import com.adyen.checkout.fake.FakeCheckoutConfigurationProvider +import dagger.Binds +import dagger.Module +import dagger.hilt.components.SingletonComponent +import dagger.hilt.testing.TestInstallIn +import javax.inject.Singleton + +@Module +@TestInstallIn( + components = [SingletonComponent::class], + replaces = [ConfigurationModule::class], +) +internal abstract class FakeConfigurationModule { + + @Singleton + @Binds + abstract fun bindConfigurationProvider(provider: FakeCheckoutConfigurationProvider): ConfigurationProvider +} diff --git a/example-app/src/androidTest/java/com/adyen/checkout/fake/FakeCheckoutConfigurationProvider.kt b/example-app/src/androidTest/java/com/adyen/checkout/fake/FakeCheckoutConfigurationProvider.kt new file mode 100644 index 0000000000..6aed84e5e9 --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/fake/FakeCheckoutConfigurationProvider.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.fake + +import com.adyen.checkout.components.core.Amount +import com.adyen.checkout.components.core.CheckoutConfiguration +import com.adyen.checkout.core.Environment +import com.adyen.checkout.example.ui.configuration.ConfigurationProvider +import com.adyen.checkout.server.CheckoutMockWebServer +import java.net.URL +import java.util.Locale +import javax.inject.Inject +import javax.inject.Singleton +import kotlin.reflect.full.primaryConstructor + +@Singleton +internal class FakeCheckoutConfigurationProvider @Inject constructor() : ConfigurationProvider { + + private val environment = Environment::class.primaryConstructor!!.call( + URL(CheckoutMockWebServer.baseUrl), + URL(CheckoutMockWebServer.baseUrl), + ) + + var locale: Locale = Locale.US + + var amount: Amount? = null + + var configurationBlock: CheckoutConfiguration.() -> Unit = {} + + override val checkoutConfig: CheckoutConfiguration + get() = CheckoutConfiguration( + environment = environment, + clientKey = TEST_CLIENT_KEY, + shopperLocale = locale, + amount = amount, + configurationBlock = configurationBlock, + ) + + companion object { + private const val TEST_CLIENT_KEY = "test_qwertyuiopasdfghjklzxcvbnmqwerty" + } +} From b6fd77b1ed94972b49e350712e6093cd54a47e0d Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 10:55:36 +0200 Subject: [PATCH 12/16] Enable verbose logging in UI tests COAND-852 --- .../src/androidTest/java/com/adyen/checkout/HiltTestRunner.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example-app/src/androidTest/java/com/adyen/checkout/HiltTestRunner.kt b/example-app/src/androidTest/java/com/adyen/checkout/HiltTestRunner.kt index 8597e1e407..3eef804e1c 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/HiltTestRunner.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/HiltTestRunner.kt @@ -11,6 +11,8 @@ package com.adyen.checkout import android.app.Application import android.content.Context import androidx.test.runner.AndroidJUnitRunner +import com.adyen.checkout.core.AdyenLogLevel +import com.adyen.checkout.core.AdyenLogger import dagger.hilt.android.testing.HiltTestApplication // This class is used from build.gradle @@ -18,6 +20,7 @@ import dagger.hilt.android.testing.HiltTestApplication class HiltTestRunner : AndroidJUnitRunner() { override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application { + AdyenLogger.setLogLevel(AdyenLogLevel.VERBOSE) return super.newApplication(cl, HiltTestApplication::class.java.name, context) } } From f07361a8a6187c46720e38ae5f3fa4467e9371ca Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 10:59:41 +0200 Subject: [PATCH 13/16] Make UI tests wait for background work This is achieved by using CountingIdlingResources and incrementing the counter everytime work is dispatched to either the default or IO dispatcher. COAND-852 --- example-app/build.gradle | 1 + .../java/com/adyen/checkout/DropInTest.kt | 4 ++ .../checkout/rule/IdlingDispatcherRule.kt | 67 +++++++++++++++++++ .../checkout/util/IdlingResourceDispatcher.kt | 32 +++++++++ 4 files changed, 104 insertions(+) create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/rule/IdlingDispatcherRule.kt create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/util/IdlingResourceDispatcher.kt diff --git a/example-app/build.gradle b/example-app/build.gradle index ded9a555e0..b1ff655db8 100644 --- a/example-app/build.gradle +++ b/example-app/build.gradle @@ -112,6 +112,7 @@ dependencies { androidTestImplementation testLibraries.barista androidTestImplementation testLibraries.espresso androidTestImplementation testLibraries.hilt + androidTestImplementation testLibraries.kotlinCoroutines androidTestImplementation testLibraries.mockWebServer kspAndroidTest testLibraries.hiltCompiler diff --git a/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt b/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt index 58bf39a298..84140e39aa 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt @@ -12,6 +12,7 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule import com.adyen.checkout.example.ui.main.MainActivity import com.adyen.checkout.robot.onDropIn import com.adyen.checkout.robot.onMain +import com.adyen.checkout.rule.IdlingDispatcherRule import com.adyen.checkout.server.CheckoutMockWebServer import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest @@ -29,6 +30,9 @@ internal class DropInTest { @get:Rule(order = 1) var activityRule: ActivityScenarioRule = ActivityScenarioRule(MainActivity::class.java) + @get:Rule(order = 2) + var dispatcherRule = IdlingDispatcherRule() + @Before fun before() { CheckoutMockWebServer.start() diff --git a/example-app/src/androidTest/java/com/adyen/checkout/rule/IdlingDispatcherRule.kt b/example-app/src/androidTest/java/com/adyen/checkout/rule/IdlingDispatcherRule.kt new file mode 100644 index 0000000000..7a013f55e3 --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/rule/IdlingDispatcherRule.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.rule + +import androidx.test.espresso.IdlingRegistry +import androidx.test.espresso.idling.CountingIdlingResource +import com.adyen.checkout.util.IdlingResourceDispatcher +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement + +class IdlingDispatcherRule : TestRule { + + override fun apply(base: Statement?, description: Description?): Statement = object : Statement() { + override fun evaluate() { + // Main dispatcher is not needed as this is not doing background work + val defaultDispatcher = Dispatchers.Default + val ioDispatcher = Dispatchers.IO + + val defaultIdlingResource = CountingIdlingResource("default") + val ioIdlingResource = CountingIdlingResource("io") + + IdlingRegistry.getInstance().apply { + register(defaultIdlingResource) + register(ioIdlingResource) + } + + val defaultIdlingDispatcher = IdlingResourceDispatcher(defaultDispatcher, defaultIdlingResource) + val ioIdlingDispatcher = IdlingResourceDispatcher(ioDispatcher, ioIdlingResource) + + overrideDispatchers(defaultIdlingDispatcher, ioIdlingDispatcher) + + try { + base?.evaluate() + } finally { + IdlingRegistry.getInstance().apply { + unregister(defaultIdlingResource) + unregister(ioIdlingResource) + } + overrideDispatchers(defaultDispatcher, ioDispatcher) + } + } + } + + private fun overrideDispatchers( + default: CoroutineDispatcher, + io: CoroutineDispatcher, + ) { + fun setField(name: String, value: CoroutineDispatcher) { + Dispatchers::class.java.getDeclaredField(name).apply { + isAccessible = true + set(Dispatchers, value) + } + } + + setField("Default", default) + setField("IO", io) + } +} diff --git a/example-app/src/androidTest/java/com/adyen/checkout/util/IdlingResourceDispatcher.kt b/example-app/src/androidTest/java/com/adyen/checkout/util/IdlingResourceDispatcher.kt new file mode 100644 index 0000000000..03d8f8e010 --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/util/IdlingResourceDispatcher.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.util + +import androidx.test.espresso.idling.CountingIdlingResource +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Runnable +import kotlin.coroutines.CoroutineContext + +internal class IdlingResourceDispatcher( + private val wrappedDispatcher: CoroutineDispatcher, + private val counter: CountingIdlingResource, +) : CoroutineDispatcher() { + + override fun dispatch(context: CoroutineContext, block: Runnable) { + counter.increment() + val runnable = Runnable { + try { + block.run() + } finally { + counter.decrement() + } + } + wrappedDispatcher.dispatch(context, runnable) + } +} From 5d6e4d490e52d464a1b2004167f636a54c479af6 Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 11:35:32 +0200 Subject: [PATCH 14/16] Combine all test rules into one This takes away a lot of boilerplate code in tests. COAND-852 --- .../java/com/adyen/checkout/DropInTest.kt | 28 ++----------- .../adyen/checkout/rule/CheckoutTestRule.kt | 40 +++++++++++++++++++ .../checkout/rule/IdlingDispatcherRule.kt | 4 +- .../com/adyen/checkout/rule/MockServerRule.kt | 28 +++++++++++++ 4 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/rule/CheckoutTestRule.kt create mode 100644 example-app/src/androidTest/java/com/adyen/checkout/rule/MockServerRule.kt diff --git a/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt b/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt index 84140e39aa..e1d8e28d67 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt @@ -8,40 +8,18 @@ package com.adyen.checkout -import androidx.test.ext.junit.rules.ActivityScenarioRule -import com.adyen.checkout.example.ui.main.MainActivity import com.adyen.checkout.robot.onDropIn import com.adyen.checkout.robot.onMain -import com.adyen.checkout.rule.IdlingDispatcherRule -import com.adyen.checkout.server.CheckoutMockWebServer -import dagger.hilt.android.testing.HiltAndroidRule +import com.adyen.checkout.rule.CheckoutTestRule import dagger.hilt.android.testing.HiltAndroidTest -import org.junit.After -import org.junit.Before import org.junit.Rule import org.junit.Test @HiltAndroidTest internal class DropInTest { - @get:Rule(order = 0) - var hiltRule = HiltAndroidRule(this) - - @get:Rule(order = 1) - var activityRule: ActivityScenarioRule = ActivityScenarioRule(MainActivity::class.java) - - @get:Rule(order = 2) - var dispatcherRule = IdlingDispatcherRule() - - @Before - fun before() { - CheckoutMockWebServer.start() - } - - @After - fun after() { - CheckoutMockWebServer.stop() - } + @get:Rule + var checkoutTestRule = CheckoutTestRule(this) @Test fun whenDropInIsOpened_thenItIsDisplayed() { diff --git a/example-app/src/androidTest/java/com/adyen/checkout/rule/CheckoutTestRule.kt b/example-app/src/androidTest/java/com/adyen/checkout/rule/CheckoutTestRule.kt new file mode 100644 index 0000000000..d981ce17cb --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/rule/CheckoutTestRule.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.rule + +import androidx.test.ext.junit.rules.ActivityScenarioRule +import com.adyen.checkout.example.ui.main.MainActivity +import dagger.hilt.android.testing.HiltAndroidRule +import org.junit.rules.RuleChain +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement + +class CheckoutTestRule( + testInstance: Any +) : TestRule { + + private val hiltRule = HiltAndroidRule(testInstance) + private val activityRule: ActivityScenarioRule = ActivityScenarioRule(MainActivity::class.java) + + override fun apply(base: Statement, description: Description?): Statement = + /* + * The order of the rules below is important! + * - HiltAndroidRule has to be the outer rule to ensure the dependency graph is built only once + * - MockServerRule comes second to make sure the backend is ready asap + * - IdlingDispatcherRule comes after MockServerRule + * - Rules after ActivityScenarioRule will be executed after the activity is launched + */ + RuleChain + .outerRule(hiltRule) + .around(MockServerRule()) + .around(IdlingDispatcherRule()) + .around(activityRule) + .apply(base, description) +} diff --git a/example-app/src/androidTest/java/com/adyen/checkout/rule/IdlingDispatcherRule.kt b/example-app/src/androidTest/java/com/adyen/checkout/rule/IdlingDispatcherRule.kt index 7a013f55e3..44275d0608 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/rule/IdlingDispatcherRule.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/rule/IdlingDispatcherRule.kt @@ -19,7 +19,7 @@ import org.junit.runners.model.Statement class IdlingDispatcherRule : TestRule { - override fun apply(base: Statement?, description: Description?): Statement = object : Statement() { + override fun apply(base: Statement, description: Description?): Statement = object : Statement() { override fun evaluate() { // Main dispatcher is not needed as this is not doing background work val defaultDispatcher = Dispatchers.Default @@ -39,7 +39,7 @@ class IdlingDispatcherRule : TestRule { overrideDispatchers(defaultIdlingDispatcher, ioIdlingDispatcher) try { - base?.evaluate() + base.evaluate() } finally { IdlingRegistry.getInstance().apply { unregister(defaultIdlingResource) diff --git a/example-app/src/androidTest/java/com/adyen/checkout/rule/MockServerRule.kt b/example-app/src/androidTest/java/com/adyen/checkout/rule/MockServerRule.kt new file mode 100644 index 0000000000..15d169e12d --- /dev/null +++ b/example-app/src/androidTest/java/com/adyen/checkout/rule/MockServerRule.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 6/6/2024. + */ + +package com.adyen.checkout.rule + +import com.adyen.checkout.server.CheckoutMockWebServer +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement + +class MockServerRule : TestRule { + + override fun apply(base: Statement, description: Description?): Statement = object : Statement() { + override fun evaluate() { + try { + CheckoutMockWebServer.start() + base.evaluate() + } finally { + CheckoutMockWebServer.stop() + } + } + } +} From 46bff2890b402ccce7bafe1273af6c107646d1ac Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 11:36:35 +0200 Subject: [PATCH 15/16] Remove MainTest This test was there only for testing purposes and did not test anything really. COAND-852 --- .../java/com/adyen/checkout/MainTest.kt | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 example-app/src/androidTest/java/com/adyen/checkout/MainTest.kt diff --git a/example-app/src/androidTest/java/com/adyen/checkout/MainTest.kt b/example-app/src/androidTest/java/com/adyen/checkout/MainTest.kt deleted file mode 100644 index 449f49543f..0000000000 --- a/example-app/src/androidTest/java/com/adyen/checkout/MainTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2024 Adyen N.V. - * - * This file is open source and available under the MIT license. See the LICENSE file for more info. - * - * Created by oscars on 19/4/2024. - */ - -package com.adyen.checkout - -import androidx.test.ext.junit.rules.ActivityScenarioRule -import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed -import com.adyen.checkout.example.ui.main.MainActivity -import dagger.hilt.android.testing.HiltAndroidRule -import dagger.hilt.android.testing.HiltAndroidTest -import org.junit.Rule -import org.junit.Test - -@HiltAndroidTest -internal class MainTest { - - @get:Rule(order = 0) - var hiltRule = HiltAndroidRule(this) - - @get:Rule(order = 1) - var activityRule: ActivityScenarioRule = ActivityScenarioRule(MainActivity::class.java) - - @Test - fun whenMainActivityIsOpened_thenIntegrationOptionsAreShown() { - assertDisplayed("Drop In") - } -} From ea1458636c87954208f154997c19cfbad1bb3054 Mon Sep 17 00:00:00 2001 From: Oscar Spruit Date: Thu, 6 Jun 2024 11:38:04 +0200 Subject: [PATCH 16/16] Move all test utils to test package COAND-852 --- example-app/build.gradle | 2 +- .../com/adyen/checkout/{ => dropin}/DropInTest.kt | 8 ++++---- .../com/adyen/checkout/{ => test}/HiltTestRunner.kt | 2 +- .../checkout/{ => test}/di/FakeBaseUrlModule.kt | 4 ++-- .../{ => test}/di/FakeConfigurationModule.kt | 4 ++-- .../fake/FakeCheckoutConfigurationProvider.kt | 4 ++-- .../adyen/checkout/{ => test}/robot/DropInRobot.kt | 2 +- .../com/adyen/checkout/{ => test}/robot/MainRobot.kt | 2 +- .../com/adyen/checkout/{ => test}/robot/TestRobot.kt | 2 +- .../checkout/{ => test}/rule/CheckoutTestRule.kt | 12 ++++++------ .../checkout/{ => test}/rule/IdlingDispatcherRule.kt | 4 ++-- .../adyen/checkout/{ => test}/rule/MockServerRule.kt | 4 ++-- .../{ => test}/server/CheckoutMockWebServer.kt | 4 ++-- .../{ => test}/server/DelegatingBackendDispatcher.kt | 10 +++++----- .../{ => test}/server/service/MockBackendService.kt | 6 +++--- .../{ => test}/server/service/MockCheckoutService.kt | 4 ++-- .../server/service/MockPublicKeyService.kt | 2 +- .../{ => test}/server/service/MockSessionService.kt | 2 +- .../{ => test}/util/IdlingResourceDispatcher.kt | 2 +- .../adyen/checkout/{ => test}/util/JsonFileReader.kt | 5 ++--- 20 files changed, 42 insertions(+), 43 deletions(-) rename example-app/src/androidTest/java/com/adyen/checkout/{ => dropin}/DropInTest.kt (77%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/HiltTestRunner.kt (96%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/di/FakeBaseUrlModule.kt (87%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/di/FakeConfigurationModule.kt (88%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/fake/FakeCheckoutConfigurationProvider.kt (93%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/robot/DropInRobot.kt (94%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/robot/MainRobot.kt (95%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/robot/TestRobot.kt (86%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/rule/CheckoutTestRule.kt (84%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/rule/IdlingDispatcherRule.kt (95%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/rule/MockServerRule.kt (87%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/server/CheckoutMockWebServer.kt (94%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/server/DelegatingBackendDispatcher.kt (81%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/server/service/MockBackendService.kt (88%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/server/service/MockCheckoutService.kt (84%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/server/service/MockPublicKeyService.kt (91%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/server/service/MockSessionService.kt (91%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/util/IdlingResourceDispatcher.kt (95%) rename example-app/src/androidTest/java/com/adyen/checkout/{ => test}/util/JsonFileReader.kt (85%) diff --git a/example-app/build.gradle b/example-app/build.gradle index b1ff655db8..50d298f9d8 100644 --- a/example-app/build.gradle +++ b/example-app/build.gradle @@ -42,7 +42,7 @@ android { versionCode version_code versionName version_name - testInstrumentationRunner 'com.adyen.checkout.HiltTestRunner' + testInstrumentationRunner 'com.adyen.checkout.test.HiltTestRunner' } testOptions { diff --git a/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt b/example-app/src/androidTest/java/com/adyen/checkout/dropin/DropInTest.kt similarity index 77% rename from example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt rename to example-app/src/androidTest/java/com/adyen/checkout/dropin/DropInTest.kt index e1d8e28d67..66d6334f56 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/DropInTest.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/dropin/DropInTest.kt @@ -6,11 +6,11 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout +package com.adyen.checkout.dropin -import com.adyen.checkout.robot.onDropIn -import com.adyen.checkout.robot.onMain -import com.adyen.checkout.rule.CheckoutTestRule +import com.adyen.checkout.test.robot.onDropIn +import com.adyen.checkout.test.robot.onMain +import com.adyen.checkout.test.rule.CheckoutTestRule import dagger.hilt.android.testing.HiltAndroidTest import org.junit.Rule import org.junit.Test diff --git a/example-app/src/androidTest/java/com/adyen/checkout/HiltTestRunner.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/HiltTestRunner.kt similarity index 96% rename from example-app/src/androidTest/java/com/adyen/checkout/HiltTestRunner.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/HiltTestRunner.kt index 3eef804e1c..f6cfa6274d 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/HiltTestRunner.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/HiltTestRunner.kt @@ -6,7 +6,7 @@ * Created by oscars on 19/4/2024. */ -package com.adyen.checkout +package com.adyen.checkout.test import android.app.Application import android.content.Context diff --git a/example-app/src/androidTest/java/com/adyen/checkout/di/FakeBaseUrlModule.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/di/FakeBaseUrlModule.kt similarity index 87% rename from example-app/src/androidTest/java/com/adyen/checkout/di/FakeBaseUrlModule.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/di/FakeBaseUrlModule.kt index 4d05344ad3..3e67cb546b 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/di/FakeBaseUrlModule.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/di/FakeBaseUrlModule.kt @@ -6,11 +6,11 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.di +package com.adyen.checkout.test.di import com.adyen.checkout.example.di.BaseUrl import com.adyen.checkout.example.di.NetworkModule -import com.adyen.checkout.server.CheckoutMockWebServer +import com.adyen.checkout.test.server.CheckoutMockWebServer import dagger.Module import dagger.Provides import dagger.hilt.components.SingletonComponent diff --git a/example-app/src/androidTest/java/com/adyen/checkout/di/FakeConfigurationModule.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/di/FakeConfigurationModule.kt similarity index 88% rename from example-app/src/androidTest/java/com/adyen/checkout/di/FakeConfigurationModule.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/di/FakeConfigurationModule.kt index dd700ad91e..6c7dbca6a6 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/di/FakeConfigurationModule.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/di/FakeConfigurationModule.kt @@ -6,11 +6,11 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.di +package com.adyen.checkout.test.di import com.adyen.checkout.example.di.ConfigurationModule import com.adyen.checkout.example.ui.configuration.ConfigurationProvider -import com.adyen.checkout.fake.FakeCheckoutConfigurationProvider +import com.adyen.checkout.test.fake.FakeCheckoutConfigurationProvider import dagger.Binds import dagger.Module import dagger.hilt.components.SingletonComponent diff --git a/example-app/src/androidTest/java/com/adyen/checkout/fake/FakeCheckoutConfigurationProvider.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/fake/FakeCheckoutConfigurationProvider.kt similarity index 93% rename from example-app/src/androidTest/java/com/adyen/checkout/fake/FakeCheckoutConfigurationProvider.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/fake/FakeCheckoutConfigurationProvider.kt index 6aed84e5e9..a44f3b9e1b 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/fake/FakeCheckoutConfigurationProvider.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/fake/FakeCheckoutConfigurationProvider.kt @@ -6,13 +6,13 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.fake +package com.adyen.checkout.test.fake import com.adyen.checkout.components.core.Amount import com.adyen.checkout.components.core.CheckoutConfiguration import com.adyen.checkout.core.Environment import com.adyen.checkout.example.ui.configuration.ConfigurationProvider -import com.adyen.checkout.server.CheckoutMockWebServer +import com.adyen.checkout.test.server.CheckoutMockWebServer import java.net.URL import java.util.Locale import javax.inject.Inject diff --git a/example-app/src/androidTest/java/com/adyen/checkout/robot/DropInRobot.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/robot/DropInRobot.kt similarity index 94% rename from example-app/src/androidTest/java/com/adyen/checkout/robot/DropInRobot.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/robot/DropInRobot.kt index 32ab449fef..325edb51f9 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/robot/DropInRobot.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/robot/DropInRobot.kt @@ -6,7 +6,7 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.robot +package com.adyen.checkout.test.robot import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed diff --git a/example-app/src/androidTest/java/com/adyen/checkout/robot/MainRobot.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/robot/MainRobot.kt similarity index 95% rename from example-app/src/androidTest/java/com/adyen/checkout/robot/MainRobot.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/robot/MainRobot.kt index 6eb7b8fc8c..1f4432ec87 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/robot/MainRobot.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/robot/MainRobot.kt @@ -6,7 +6,7 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.robot +package com.adyen.checkout.test.robot import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed import com.adevinta.android.barista.interaction.BaristaCheckboxInteractions.check diff --git a/example-app/src/androidTest/java/com/adyen/checkout/robot/TestRobot.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/robot/TestRobot.kt similarity index 86% rename from example-app/src/androidTest/java/com/adyen/checkout/robot/TestRobot.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/robot/TestRobot.kt index 4c363fe463..96da8f2c0a 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/robot/TestRobot.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/robot/TestRobot.kt @@ -6,7 +6,7 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.robot +package com.adyen.checkout.test.robot internal interface TestRobot { diff --git a/example-app/src/androidTest/java/com/adyen/checkout/rule/CheckoutTestRule.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/rule/CheckoutTestRule.kt similarity index 84% rename from example-app/src/androidTest/java/com/adyen/checkout/rule/CheckoutTestRule.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/rule/CheckoutTestRule.kt index d981ce17cb..0b31edb98d 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/rule/CheckoutTestRule.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/rule/CheckoutTestRule.kt @@ -6,7 +6,7 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.rule +package com.adyen.checkout.test.rule import androidx.test.ext.junit.rules.ActivityScenarioRule import com.adyen.checkout.example.ui.main.MainActivity @@ -32,9 +32,9 @@ class CheckoutTestRule( * - Rules after ActivityScenarioRule will be executed after the activity is launched */ RuleChain - .outerRule(hiltRule) - .around(MockServerRule()) - .around(IdlingDispatcherRule()) - .around(activityRule) - .apply(base, description) + .outerRule(hiltRule) + .around(MockServerRule()) + .around(IdlingDispatcherRule()) + .around(activityRule) + .apply(base, description) } diff --git a/example-app/src/androidTest/java/com/adyen/checkout/rule/IdlingDispatcherRule.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/rule/IdlingDispatcherRule.kt similarity index 95% rename from example-app/src/androidTest/java/com/adyen/checkout/rule/IdlingDispatcherRule.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/rule/IdlingDispatcherRule.kt index 44275d0608..ddfa72bcd6 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/rule/IdlingDispatcherRule.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/rule/IdlingDispatcherRule.kt @@ -6,11 +6,11 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.rule +package com.adyen.checkout.test.rule import androidx.test.espresso.IdlingRegistry import androidx.test.espresso.idling.CountingIdlingResource -import com.adyen.checkout.util.IdlingResourceDispatcher +import com.adyen.checkout.test.util.IdlingResourceDispatcher import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import org.junit.rules.TestRule diff --git a/example-app/src/androidTest/java/com/adyen/checkout/rule/MockServerRule.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/rule/MockServerRule.kt similarity index 87% rename from example-app/src/androidTest/java/com/adyen/checkout/rule/MockServerRule.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/rule/MockServerRule.kt index 15d169e12d..62f15a8c72 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/rule/MockServerRule.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/rule/MockServerRule.kt @@ -6,9 +6,9 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.rule +package com.adyen.checkout.test.rule -import com.adyen.checkout.server.CheckoutMockWebServer +import com.adyen.checkout.test.server.CheckoutMockWebServer import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/CheckoutMockWebServer.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/server/CheckoutMockWebServer.kt similarity index 94% rename from example-app/src/androidTest/java/com/adyen/checkout/server/CheckoutMockWebServer.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/server/CheckoutMockWebServer.kt index fd3815d3bd..1d26e65d24 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/server/CheckoutMockWebServer.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/server/CheckoutMockWebServer.kt @@ -3,10 +3,10 @@ * * This file is open source and available under the MIT license. See the LICENSE file for more info. * - * Created by oscars on 5/6/2024. + * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.server +package com.adyen.checkout.test.server import com.adyen.checkout.core.AdyenLogLevel import com.adyen.checkout.core.internal.util.adyenLog diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/server/DelegatingBackendDispatcher.kt similarity index 81% rename from example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/server/DelegatingBackendDispatcher.kt index 3152660aa4..6d1ea2d97d 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/server/DelegatingBackendDispatcher.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/server/DelegatingBackendDispatcher.kt @@ -3,16 +3,16 @@ * * This file is open source and available under the MIT license. See the LICENSE file for more info. * - * Created by oscars on 5/6/2024. + * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.server +package com.adyen.checkout.test.server import com.adyen.checkout.core.AdyenLogLevel import com.adyen.checkout.core.internal.util.adyenLog -import com.adyen.checkout.server.service.MockCheckoutService -import com.adyen.checkout.server.service.MockPublicKeyService -import com.adyen.checkout.server.service.MockSessionService +import com.adyen.checkout.test.server.service.MockCheckoutService +import com.adyen.checkout.test.server.service.MockPublicKeyService +import com.adyen.checkout.test.server.service.MockSessionService import okhttp3.mockwebserver.Dispatcher import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.RecordedRequest diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockBackendService.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockBackendService.kt similarity index 88% rename from example-app/src/androidTest/java/com/adyen/checkout/server/service/MockBackendService.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockBackendService.kt index 63aa079288..37e8f9db43 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockBackendService.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockBackendService.kt @@ -3,12 +3,12 @@ * * This file is open source and available under the MIT license. See the LICENSE file for more info. * - * Created by oscars on 5/6/2024. + * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.server.service +package com.adyen.checkout.test.server.service -import com.adyen.checkout.util.JsonFileReader +import com.adyen.checkout.test.util.JsonFileReader import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.RecordedRequest import java.net.HttpURLConnection.HTTP_OK diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockCheckoutService.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockCheckoutService.kt similarity index 84% rename from example-app/src/androidTest/java/com/adyen/checkout/server/service/MockCheckoutService.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockCheckoutService.kt index 43b18ea096..ae60501a5d 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockCheckoutService.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockCheckoutService.kt @@ -3,10 +3,10 @@ * * This file is open source and available under the MIT license. See the LICENSE file for more info. * - * Created by oscars on 5/6/2024. + * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.server.service +package com.adyen.checkout.test.server.service import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.RecordedRequest diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockPublicKeyService.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockPublicKeyService.kt similarity index 91% rename from example-app/src/androidTest/java/com/adyen/checkout/server/service/MockPublicKeyService.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockPublicKeyService.kt index 023915fffd..fd0e915efe 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockPublicKeyService.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockPublicKeyService.kt @@ -6,7 +6,7 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.server.service +package com.adyen.checkout.test.server.service import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.RecordedRequest diff --git a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockSessionService.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockSessionService.kt similarity index 91% rename from example-app/src/androidTest/java/com/adyen/checkout/server/service/MockSessionService.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockSessionService.kt index ab866b5607..934e5ee403 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/server/service/MockSessionService.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/server/service/MockSessionService.kt @@ -6,7 +6,7 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.server.service +package com.adyen.checkout.test.server.service import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.RecordedRequest diff --git a/example-app/src/androidTest/java/com/adyen/checkout/util/IdlingResourceDispatcher.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/util/IdlingResourceDispatcher.kt similarity index 95% rename from example-app/src/androidTest/java/com/adyen/checkout/util/IdlingResourceDispatcher.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/util/IdlingResourceDispatcher.kt index 03d8f8e010..5dff8f9b2f 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/util/IdlingResourceDispatcher.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/util/IdlingResourceDispatcher.kt @@ -6,7 +6,7 @@ * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.util +package com.adyen.checkout.test.util import androidx.test.espresso.idling.CountingIdlingResource import kotlinx.coroutines.CoroutineDispatcher diff --git a/example-app/src/androidTest/java/com/adyen/checkout/util/JsonFileReader.kt b/example-app/src/androidTest/java/com/adyen/checkout/test/util/JsonFileReader.kt similarity index 85% rename from example-app/src/androidTest/java/com/adyen/checkout/util/JsonFileReader.kt rename to example-app/src/androidTest/java/com/adyen/checkout/test/util/JsonFileReader.kt index 75dafd0db3..15143652fb 100644 --- a/example-app/src/androidTest/java/com/adyen/checkout/util/JsonFileReader.kt +++ b/example-app/src/androidTest/java/com/adyen/checkout/test/util/JsonFileReader.kt @@ -3,13 +3,12 @@ * * This file is open source and available under the MIT license. See the LICENSE file for more info. * - * Created by oscars on 5/6/2024. + * Created by oscars on 6/6/2024. */ -package com.adyen.checkout.util +package com.adyen.checkout.test.util import androidx.test.platform.app.InstrumentationRegistry -import dagger.hilt.android.testing.HiltTestApplication import java.io.InputStreamReader internal object JsonFileReader {