From 4eaa764587ff3b694366af339dd24a1cd8aa627c Mon Sep 17 00:00:00 2001 From: Jheng-Hao Lin Date: Tue, 14 Oct 2025 13:48:17 +0100 Subject: [PATCH] feat/pimob-4057: Upgrade AGP to 8.12.3 Updates the Gradle wrapper, Android Gradle Plugin, and related configurations. - Bumps Gradle wrapper from 8.2.1 to 8.13. - Upgrades Android Gradle Plugin from 8.1.2 to 8.12.3. --- .gitignore | 1 + app/build.gradle | 16 +-- build.gradle.kts | 8 +- buildSrc/build.gradle.kts | 2 +- buildSrc/gradle.properties | 4 +- buildSrc/src/main/java/Dependencies.kt | 8 +- buildSrc/src/main/java/Versions.kt | 11 +- .../checkout/buildsrc/AndroidJunit4Config.kt | 1 + .../checkout/buildsrc/AndroidJunit5Config.kt | 1 + .../com/checkout/buildsrc/BaseDependencies.kt | 16 +-- .../com/checkout/buildsrc/CommonConfig.kt | 47 ++------ .../com/checkout/buildsrc/JacocoTestReport.kt | 2 +- .../utils/DependencyHandlerUtilExtensions.kt | 8 +- .../buildsrc/utils/ProjectExtensions.kt | 16 --- .../java/precompiled-android-app.gradle.kts | 13 +-- checkout/build.gradle.kts | 17 ++- .../usecase/ProcessThreeDSUseCase.kt | 9 +- .../tokenization/entity/AddressEntity.kt | 1 + .../tokenization/entity/PhoneEntity.kt | 1 + .../tokenization/entity/TokenDataEntity.kt | 1 + .../model/AddressValidationRequest.kt | 1 + .../model/PhoneValidationRequest.kt | 1 + .../threedsecure/utils/UriExtensionKtTest.kt | 9 +- .../webview/ThreeDSWebViewClientTest.kt | 4 +- .../tokenization/TokenNetworkApiClientTest.kt | 42 +------ .../repository/TokenRepositoryImplTest.kt | 107 +++++++----------- example_app_frames/build.gradle.kts | 13 +-- frames/build.gradle.kts | 23 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 3 +- 30 files changed, 149 insertions(+), 239 deletions(-) diff --git a/.gitignore b/.gitignore index 9ac14882a..4e808c314 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /local.properties /.idea/* .DS_Store +.kotlin /build /captures .externalNativeBuild diff --git a/app/build.gradle b/app/build.gradle index 27bbfc181..cc87b03fc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,7 @@ plugins { id("com.android.application") id("org.jetbrains.kotlin.android") + id("org.jetbrains.kotlin.plugin.compose") } android { @@ -15,7 +16,7 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } testOptions { - execution 'ANDROIDX_TEST_ORCHESTRATOR' + execution = "ANDROIDX_TEST_ORCHESTRATOR" animationsDisabled = true } signingConfigs { @@ -34,20 +35,21 @@ android { buildTypes { release { - minifyEnabled true - signingConfig signingConfigs.release - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + minifyEnabled = true + signingConfig = signingConfigs.release + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } // Create baseline for lint check to ignore old issues. - lintOptions { - baseline(project.file("lint-baseline.xml")) + lint { + baseline = file('lint-baseline.xml') } } dependencies { implementation 'androidx.activity:activity:1.8.0' + implementation 'androidx.appcompat:appcompat:1.7.1' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test:runner:1.5.2' @@ -64,7 +66,7 @@ dependencies { implementation FramesConfig.framesAndroidDependency } -configurations.all { +configurations.configureEach { resolutionStrategy.dependencySubstitution { if (FramesConfig.useLocalModuleDependencies) { diff --git a/build.gradle.kts b/build.gradle.kts index 05efa2677..48c0b7790 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,11 +2,15 @@ import com.vanniktech.code.quality.tools.CodeQualityToolsPluginExtension import org.jetbrains.dokka.gradle.DokkaMultiModuleTask // Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + id("com.google.devtools.ksp") version "2.2.20-2.0.2" apply false + id("org.jetbrains.kotlin.plugin.compose") version "2.2.20" apply false +} + buildscript { repositories { google() mavenCentral() - jcenter() } dependencies { @@ -44,7 +48,7 @@ allprojects { } tasks.register("clean", Delete::class) { - delete(rootProject.buildDir) + delete(rootProject.layout.buildDirectory) } /* Code quality tools config */ diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 24cdedc2e..ca5cdb7d6 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -13,7 +13,7 @@ java { } dependencies { - implementation("com.android.tools.build:gradle:8.1.2") + implementation("com.android.tools.build:gradle:8.12.3") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.property("kotlinVersion")}") implementation("de.mannodermaus.gradle.plugins:android-junit5:${project.property("mannodermausAndroidJunit5Version")}") implementation("org.jetbrains.dokka:dokka-gradle-plugin:${project.property("dokkaVersion")}") diff --git a/buildSrc/gradle.properties b/buildSrc/gradle.properties index ff806dfe7..e063b6e55 100644 --- a/buildSrc/gradle.properties +++ b/buildSrc/gradle.properties @@ -1,5 +1,5 @@ -kotlinVersion=1.9.10 -gradleVersion=8.1.2 +kotlinVersion=2.2.20 +gradleVersion=8.12.3 mannodermausAndroidJunit5Version=1.8.0.0 dokkaVersion=1.9.0 codeQualityToolsPlugin=0.21.0 \ No newline at end of file diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index c6c340f24..912f3a846 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -11,10 +11,6 @@ object Dependencies { "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.kotlinCoroutines}" const val coreKtx = "androidx.core:core-ktx:${Versions.coreKtx}" const val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat}" - const val constraintLayout = - "androidx.constraintlayout:constraintlayout:${Versions.constraintLayout}" - const val materialDesign = "com.google.android.material:material:${Versions.materialDesign}" - const val lifeCycleLiveData = "androidx.lifecycle:lifecycle-livedata-ktx:${Versions.lifeCycle}" const val lifeCycleRunTime = "androidx.lifecycle:lifecycle-runtime-ktx:${Versions.lifeCycle}" const val lifecycle_viewmodel = "androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.lifeCycle}" @@ -51,8 +47,6 @@ object Dependencies { // Dependency injection const val dagger = "com.google.dagger:dagger-android:${Versions.dagger}" - const val dagger_support = "com.google.dagger:dagger-android-support:${Versions.dagger}" - const val dagger_processor = "com.google.dagger:dagger-android-processor:${Versions.dagger}" const val dagger_compiler = "com.google.dagger:dagger-compiler:${Versions.dagger}" // Instrumented Test @@ -74,6 +68,7 @@ object Dependencies { const val junitJupiterApi = "org.junit.jupiter:junit-jupiter-api:${Versions.junit5Jupiter}" const val junitJupiterEngine = "org.junit.jupiter:junit-jupiter-engine:${Versions.junit5Jupiter}" + const val junitPlatformLauncher = "org.junit.platform:junit-platform-launcher:${Versions.junitPlatformLauncher}" const val junitJupiterParams = "org.junit.jupiter:junit-jupiter-params:${Versions.junit5Jupiter}" const val mannodermausAndroidJunitCore = @@ -88,6 +83,7 @@ object Dependencies { const val kluentAndroid = "org.amshove.kluent:kluent-android:${Versions.kluent}" const val robolectric = "org.robolectric:robolectric:${Versions.robolectric}" const val truth = "com.google.truth:truth:${Versions.truth}" + const val testRunner = "androidx.test:runner:${Versions.testRunner}" const val okhttpMockServer = "com.squareup.okhttp3:mockwebserver:${Versions.okhttp}" const val kotlinCoroutinesTest = "org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.kotlinCoroutines}" const val jsonTest = "org.json:json:${Versions.jsonTest}" diff --git a/buildSrc/src/main/java/Versions.kt b/buildSrc/src/main/java/Versions.kt index 2b58d0e6c..4ad848219 100644 --- a/buildSrc/src/main/java/Versions.kt +++ b/buildSrc/src/main/java/Versions.kt @@ -17,10 +17,7 @@ object Versions { const val jsonTest = "20180813" const val coreKtx = "1.2.0" const val appcompat = "1.3.1" - const val constraintLayout = "2.1.1" - const val materialDesign = "1.4.0" const val lifeCycle = "2.5.1" - const val compose_compiler_ext = "1.5.3" const val compose_material3 = "1.1.2" const val compose_version = "1.7.4" const val compose_activity_version = "1.8.0" @@ -39,13 +36,15 @@ object Versions { const val riskSdk = "2.1.0" // Unit Testing Dependencies - const val junit5Jupiter = "5.8.0" + const val junit5Jupiter = "5.13.4" const val junit4 = "4.13.2" const val junitVintageEngine = "5.8.2" + const val junitPlatformLauncher = "1.11.4" const val kluent = "1.68" - const val mockk = "1.13.8" + const val mockk = "1.14.6" const val robolectric = "4.11-beta-2" const val truth = "1.1.5" + const val testRunner = "1.7.0" const val jacoco = "0.8.10" // Instrumented Testing Dependencies @@ -62,7 +61,7 @@ object Versions { const val eventLogger = "1.0.1" // Dependency injection - const val dagger = "2.48.1" + const val dagger = "2.57.2" } fun loadVersionProperty(): Properties { diff --git a/buildSrc/src/main/java/com/checkout/buildsrc/AndroidJunit4Config.kt b/buildSrc/src/main/java/com/checkout/buildsrc/AndroidJunit4Config.kt index 581587106..7127cb4de 100644 --- a/buildSrc/src/main/java/com/checkout/buildsrc/AndroidJunit4Config.kt +++ b/buildSrc/src/main/java/com/checkout/buildsrc/AndroidJunit4Config.kt @@ -10,5 +10,6 @@ fun Project.applyAndroidJUnit4Configuration() { testImplementation(Dependencies.junitVintageEngine) testImplementation(Dependencies.robolectric) testImplementation(Dependencies.truth) + testImplementation(Dependencies.testRunner) } } diff --git a/buildSrc/src/main/java/com/checkout/buildsrc/AndroidJunit5Config.kt b/buildSrc/src/main/java/com/checkout/buildsrc/AndroidJunit5Config.kt index da5e07aab..ef8c87a19 100644 --- a/buildSrc/src/main/java/com/checkout/buildsrc/AndroidJunit5Config.kt +++ b/buildSrc/src/main/java/com/checkout/buildsrc/AndroidJunit5Config.kt @@ -45,6 +45,7 @@ private val Project.junitPlatform: AndroidJUnitPlatformExtension private fun DependencyHandler.junit5() { testImplementation(Dependencies.junitJupiterApi) testRuntimeOnly(Dependencies.junitJupiterEngine) + testRuntimeOnly(Dependencies.junitPlatformLauncher) testImplementation(Dependencies.junitJupiterParams) } diff --git a/buildSrc/src/main/java/com/checkout/buildsrc/BaseDependencies.kt b/buildSrc/src/main/java/com/checkout/buildsrc/BaseDependencies.kt index fbd630a9c..9c46010de 100644 --- a/buildSrc/src/main/java/com/checkout/buildsrc/BaseDependencies.kt +++ b/buildSrc/src/main/java/com/checkout/buildsrc/BaseDependencies.kt @@ -4,7 +4,7 @@ import Dependencies import com.checkout.buildsrc.utils.androidTestImplementation import com.checkout.buildsrc.utils.debugImplementation import com.checkout.buildsrc.utils.implementation -import com.checkout.buildsrc.utils.kapt +import com.checkout.buildsrc.utils.ksp import com.checkout.buildsrc.utils.testImplementation import org.gradle.api.artifacts.dsl.DependencyHandler @@ -19,14 +19,6 @@ fun DependencyHandler.commonDependencies() { implementation(Dependencies.appcompat) } -/** - * Dependencies usually required for modules with a Imperative UI - */ -fun DependencyHandler.androidImperativeUI() { - implementation(Dependencies.constraintLayout) - implementation(Dependencies.materialDesign) -} - /** * Dependencies usually required for modules with a Declarative UI */ @@ -51,7 +43,7 @@ fun DependencyHandler.networkingDependencies() { implementation(Dependencies.okhttp) implementation(Dependencies.loggingInterceptor) implementation(Dependencies.moshi) - kapt(Dependencies.moshiCodeGen) + ksp(Dependencies.moshiCodeGen) } fun DependencyHandler.riskSdkDependencies() { @@ -70,9 +62,7 @@ fun DependencyHandler.logging() { */ fun DependencyHandler.dependencyInjection() { implementation(Dependencies.dagger) - implementation(Dependencies.dagger_support) - kapt(Dependencies.dagger_processor) - kapt(Dependencies.dagger_compiler) + ksp(Dependencies.dagger_compiler) } /** diff --git a/buildSrc/src/main/java/com/checkout/buildsrc/CommonConfig.kt b/buildSrc/src/main/java/com/checkout/buildsrc/CommonConfig.kt index 4dba4b70e..eb4bc18d9 100644 --- a/buildSrc/src/main/java/com/checkout/buildsrc/CommonConfig.kt +++ b/buildSrc/src/main/java/com/checkout/buildsrc/CommonConfig.kt @@ -5,9 +5,9 @@ import com.android.build.gradle.AppExtension import com.android.build.gradle.LibraryExtension import com.checkout.buildsrc.utils.android import com.checkout.buildsrc.utils.kotlin -import com.checkout.buildsrc.utils.kotlinOptions import org.gradle.api.JavaVersion import org.gradle.api.Project +import org.jetbrains.kotlin.gradle.dsl.JvmTarget fun Project.applyCommonConfigurations() { android { @@ -25,8 +25,10 @@ fun Project.applyCommonConfigurations() { targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() + kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + } } testOptions { @@ -79,33 +81,6 @@ fun Project.applyDIConfigurations() { } } -fun Project.applyCommonAppConfigurations() { - android { - require(this is AppExtension) { - "Android application plugin has not been applied" - } - - applyCommonConfigurations() - - buildTypes { - getByName("release") { - isMinifyEnabled = true - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro", - ) - } - getByName("debug") { - isMinifyEnabled = false - } - } - - buildFeatures.apply { - viewBinding = true - } - } -} - fun Project.applyCommonLibConfigurations() { android { require(this is LibraryExtension) { @@ -133,12 +108,12 @@ fun Project.applyCommonLibConfigurations() { kotlin { explicitApi() - } - - kotlinOptions { - freeCompilerArgs = freeCompilerArgs + - "-opt-in=kotlin.contracts.ExperimentalContracts" + - "-Xexplicit-api=strict" + compilerOptions { + freeCompilerArgs.addAll( + "-opt-in=kotlin.contracts.ExperimentalContracts", + "-Xexplicit-api=strict", + ) + } } packagingOptions.resources { diff --git a/buildSrc/src/main/java/com/checkout/buildsrc/JacocoTestReport.kt b/buildSrc/src/main/java/com/checkout/buildsrc/JacocoTestReport.kt index 5943e3b9d..cc0fe538b 100644 --- a/buildSrc/src/main/java/com/checkout/buildsrc/JacocoTestReport.kt +++ b/buildSrc/src/main/java/com/checkout/buildsrc/JacocoTestReport.kt @@ -30,7 +30,7 @@ fun Project.applyJacocoTestReport() { xml.required.set(true) html.required.set(true) } - val buildDir = project.buildDir + val buildDir = project.layout.buildDirectory val javaTree = fileTree("$buildDir/intermediates/javac/debug/classes") { setExcludes(FILE_FILTER) } val kotlinTree = fileTree("$buildDir/tmp/kotlin-classes/debug") { setExcludes(FILE_FILTER) } val execSrc = fileTree(buildDir) { setIncludes(listOf("**/*.exec")) } diff --git a/buildSrc/src/main/java/com/checkout/buildsrc/utils/DependencyHandlerUtilExtensions.kt b/buildSrc/src/main/java/com/checkout/buildsrc/utils/DependencyHandlerUtilExtensions.kt index f9c76b231..f807121a2 100644 --- a/buildSrc/src/main/java/com/checkout/buildsrc/utils/DependencyHandlerUtilExtensions.kt +++ b/buildSrc/src/main/java/com/checkout/buildsrc/utils/DependencyHandlerUtilExtensions.kt @@ -7,12 +7,8 @@ fun DependencyHandler.implementation(dependency: String) { add("implementation", dependency) } -fun DependencyHandler.kapt(dependency: String) { - add("kapt", dependency) -} - -fun DependencyHandler.annotationProcessor(dependency: String) { - add("annotationProcessor", dependency) +fun DependencyHandler.ksp(dependency: String) { + add("ksp", dependency) } fun DependencyHandler.androidTestImplementation(dependency: String) { diff --git a/buildSrc/src/main/java/com/checkout/buildsrc/utils/ProjectExtensions.kt b/buildSrc/src/main/java/com/checkout/buildsrc/utils/ProjectExtensions.kt index f67aaf700..26d77125b 100644 --- a/buildSrc/src/main/java/com/checkout/buildsrc/utils/ProjectExtensions.kt +++ b/buildSrc/src/main/java/com/checkout/buildsrc/utils/ProjectExtensions.kt @@ -6,16 +6,6 @@ import com.android.build.gradle.LibraryExtension import org.gradle.api.Project import org.gradle.api.plugins.ExtensionAware import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension -import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions - -internal fun Project.getProperty(property: String): String? = - project.findProperty(property) as String? ?: System.getenv(property) - -internal fun Project.getRequiredProperty(property: String): String { - val propertyValue = getProperty(property) - check(!propertyValue.isNullOrEmpty()) { "Required property $property is not defined" } - return propertyValue -} /** * Configures the [kotlin][org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension] extension. @@ -34,9 +24,3 @@ internal fun Project.android(configure: BaseExtension.() -> Unit) { check(androidExtension is BaseExtension) { "Unable to access Android project extensions" } androidExtension.apply(configure) } - -/** - * Configures the [kotlinOptions][org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions] extension. - */ -internal fun BaseExtension.kotlinOptions(configure: KotlinJvmOptions.() -> Unit): Unit = - (this as ExtensionAware).extensions.configure("kotlinOptions", configure) diff --git a/buildSrc/src/main/java/precompiled-android-app.gradle.kts b/buildSrc/src/main/java/precompiled-android-app.gradle.kts index 60b5d8c5c..f810785ea 100644 --- a/buildSrc/src/main/java/precompiled-android-app.gradle.kts +++ b/buildSrc/src/main/java/precompiled-android-app.gradle.kts @@ -6,7 +6,8 @@ import com.checkout.buildsrc.genericAndroidTestDependencies import com.checkout.buildsrc.genericTestDependencies import com.checkout.buildsrc.utils.android import com.checkout.buildsrc.utils.implementation -import com.checkout.buildsrc.utils.kotlinOptions +import com.checkout.buildsrc.utils.kotlin +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { id("com.android.application") @@ -29,12 +30,10 @@ android { targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - - composeOptions { - kotlinCompilerExtensionVersion = Versions.compose_compiler_ext + kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + } } } diff --git a/checkout/build.gradle.kts b/checkout/build.gradle.kts index 6874ef188..e6cc3a189 100644 --- a/checkout/build.gradle.kts +++ b/checkout/build.gradle.kts @@ -9,7 +9,7 @@ import com.checkout.buildsrc.applyRiskSdkConfigurations plugins { id("com.android.library") kotlin("android") - kotlin("kapt") + id("com.google.devtools.ksp") id("org.jetbrains.dokka") id("maven-publish") } @@ -47,7 +47,16 @@ android { consumerProguardFiles("consumer-rules.pro") } - + publishing { + singleVariant("release") {} + } + kotlin { + compilerOptions { + freeCompilerArgs.addAll( + "-Xannotation-default-target=param-property", + ) + } + } buildTypes { release { proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") @@ -102,11 +111,11 @@ tasks.withType().configureEach { } tasks.named("dokkaHtmlPartial") { - dependsOn(tasks.named("kaptReleaseKotlin")) + dependsOn(tasks.named("kspReleaseKotlin")) } tasks.named("dokkaHtmlPartial") { - dependsOn(tasks.named("kaptDebugKotlin")) + dependsOn(tasks.named("kspDebugKotlin")) } afterEvaluate { diff --git a/checkout/src/main/java/com/checkout/threedsecure/usecase/ProcessThreeDSUseCase.kt b/checkout/src/main/java/com/checkout/threedsecure/usecase/ProcessThreeDSUseCase.kt index 993e5d963..88f6d35b8 100644 --- a/checkout/src/main/java/com/checkout/threedsecure/usecase/ProcessThreeDSUseCase.kt +++ b/checkout/src/main/java/com/checkout/threedsecure/usecase/ProcessThreeDSUseCase.kt @@ -2,6 +2,7 @@ package com.checkout.threedsecure.usecase import android.net.Uri import androidx.annotation.RestrictTo +import androidx.core.net.toUri import com.checkout.base.usecase.UseCase import com.checkout.threedsecure.error.ThreeDSError import com.checkout.threedsecure.model.ProcessThreeDSRequest @@ -17,10 +18,10 @@ public class ProcessThreeDSUseCase : UseCase { + successUrl.toUri().matches(redirectUri) -> { val token = provideToken(redirectUrl) if (token == null) { @@ -30,7 +31,7 @@ public class ProcessThreeDSUseCase : UseCase ThreeDSResult.Failure + failureUrl.toUri().matches(redirectUri) -> ThreeDSResult.Failure else -> null } } @@ -39,7 +40,7 @@ public class ProcessThreeDSUseCase : UseCase>( arrayOf("www.example.com/Success", "https://www.example.com/Success", false), arrayOf("https://www.example.com/Success", "www.example.com/Success", false), arrayOf("https://www.example.com/Success", "https://www.example.com/Success", true), @@ -40,10 +41,10 @@ internal class UriExtensionKtTest( ) } - @org.junit.Test + @Test fun test() { // When - val actualResult = Uri.parse(expectedUrl).matches(Uri.parse(targetUrl)) + val actualResult = expectedUrl.toUri().matches(targetUrl.toUri()) // Then assertEquals(result, actualResult) diff --git a/checkout/src/test/java/com/checkout/threedsecure/webview/ThreeDSWebViewClientTest.kt b/checkout/src/test/java/com/checkout/threedsecure/webview/ThreeDSWebViewClientTest.kt index 0c39b7848..09d9125a6 100644 --- a/checkout/src/test/java/com/checkout/threedsecure/webview/ThreeDSWebViewClientTest.kt +++ b/checkout/src/test/java/com/checkout/threedsecure/webview/ThreeDSWebViewClientTest.kt @@ -2,7 +2,7 @@ package com.checkout.threedsecure.webview import android.os.Build import android.webkit.WebViewClient -import androidx.annotation.RequiresApi +import androidx.test.filters.SdkSuppress import com.checkout.threedsecure.logging.ThreeDSLogger import io.mockk.MockKAnnotations import io.mockk.impl.annotations.RelaxedMockK @@ -38,7 +38,7 @@ internal class ThreeDSWebViewClientTest { verify(exactly = 1) { logger.logPresentedEvent() } } - @RequiresApi(Build.VERSION_CODES.M) + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.M) @Test fun `when page committed visible for the first time then log loaded event`() { // When diff --git a/checkout/src/test/java/com/checkout/tokenization/TokenNetworkApiClientTest.kt b/checkout/src/test/java/com/checkout/tokenization/TokenNetworkApiClientTest.kt index 0b0a6a5d1..e9ff76c8c 100644 --- a/checkout/src/test/java/com/checkout/tokenization/TokenNetworkApiClientTest.kt +++ b/checkout/src/test/java/com/checkout/tokenization/TokenNetworkApiClientTest.kt @@ -130,12 +130,6 @@ internal class TokenNetworkApiClientTest { phone.shouldBeEqualTo(TokenizationRequestTestData.phoneEntity) name.shouldBeEqualTo("Bruce Wayne") } - - assertFalse(response is NetworkApiResponse.ServerError) - - assertFalse(response is NetworkApiResponse.NetworkError) - - assertFalse(response is NetworkApiResponse.InternalError) } } @@ -164,13 +158,9 @@ internal class TokenNetworkApiClientTest { assertTrue(response is NetworkApiResponse.ServerError) with((response as NetworkApiResponse.ServerError).body) { this?.requestId.shouldNotBeNull() - this?.errorCodes.shouldNotBeNull() - this?.errorType.shouldNotBeNull() + this.errorCodes.shouldNotBeNull() + this.errorType.shouldNotBeNull() } - - assertFalse(response is NetworkApiResponse.NetworkError) - - assertFalse(response is NetworkApiResponse.InternalError) } } @@ -198,8 +188,6 @@ internal class TokenNetworkApiClientTest { with((response as NetworkApiResponse.NetworkError)) { throwable.shouldNotBeNull() } - - assertFalse(response is NetworkApiResponse.InternalError) } } } @@ -231,12 +219,6 @@ internal class TokenNetworkApiClientTest { token.shouldBeEqualTo("tok_ubfj2q76miwundwlk72vxt2i7q") expiresOn.shouldBeEqualTo("2019-08-24T14:15:22Z") } - - assertFalse(response is NetworkApiResponse.ServerError) - - assertFalse(response is NetworkApiResponse.NetworkError) - - assertFalse(response is NetworkApiResponse.InternalError) } } @@ -265,13 +247,9 @@ internal class TokenNetworkApiClientTest { assertTrue(response is NetworkApiResponse.ServerError) with((response as NetworkApiResponse.ServerError).body) { this?.requestId.shouldNotBeNull() - this?.errorCodes.shouldNotBeNull() - this?.errorType.shouldNotBeNull() + this.errorCodes.shouldNotBeNull() + this.errorType.shouldNotBeNull() } - - assertFalse(response is NetworkApiResponse.NetworkError) - - assertFalse(response is NetworkApiResponse.InternalError) } } @@ -299,8 +277,6 @@ internal class TokenNetworkApiClientTest { with((response as NetworkApiResponse.NetworkError)) { throwable.shouldNotBeNull() } - - assertFalse(response is NetworkApiResponse.InternalError) } } } @@ -394,13 +370,9 @@ internal class TokenNetworkApiClientTest { assertTrue(response is NetworkApiResponse.ServerError) with((response as NetworkApiResponse.ServerError).body) { this?.requestId.shouldNotBeNull() - this?.errorCodes.shouldNotBeNull() - this?.errorType.shouldNotBeNull() + this.errorCodes.shouldNotBeNull() + this.errorType.shouldNotBeNull() } - - assertFalse(response is NetworkApiResponse.NetworkError) - - assertFalse(response is NetworkApiResponse.InternalError) } } @@ -431,8 +403,6 @@ internal class TokenNetworkApiClientTest { with((response as NetworkApiResponse.NetworkError)) { throwable.shouldNotBeNull() } - - assertFalse(response is NetworkApiResponse.InternalError) } } } diff --git a/checkout/src/test/java/com/checkout/tokenization/repository/TokenRepositoryImplTest.kt b/checkout/src/test/java/com/checkout/tokenization/repository/TokenRepositoryImplTest.kt index 1a259b46b..b898cc060 100644 --- a/checkout/src/test/java/com/checkout/tokenization/repository/TokenRepositoryImplTest.kt +++ b/checkout/src/test/java/com/checkout/tokenization/repository/TokenRepositoryImplTest.kt @@ -30,6 +30,7 @@ import io.mockk.impl.annotations.RelaxedMockK import io.mockk.junit5.MockKExtension import io.mockk.mockk import io.mockk.verify +import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -38,9 +39,11 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.setMain import org.amshove.kluent.internal.assertEquals +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach @@ -69,22 +72,28 @@ internal class TokenRepositoryImplTest { private lateinit var mockTokenizationLogger: TokenizationLogger private lateinit var tokenRepositoryImpl: TokenRepositoryImpl + private val testDispatcher = UnconfinedTestDispatcher() @BeforeEach fun setUp() { - tokenRepositoryImpl = - TokenRepositoryImpl( - networkApiClient = mockTokenNetworkApiClient, - cardToTokenRequestMapper = CardToTokenRequestMapper(), - cvvToTokenNetworkRequestMapper = CVVToTokenNetworkRequestMapper(), - cardTokenizationNetworkDataMapper = CardTokenizationNetworkDataMapper(), - validateTokenizationDataUseCase = mockValidateTokenizationDataUseCase, - validateCVVTokenizationDataUseCase = mockValidateCVVTokenizationDataUseCase, - logger = mockTokenizationLogger, - publicKey = "test_key", - cvvTokenizationNetworkDataMapper = CVVTokenizationNetworkDataMapper(), - riskSdkUseCase = mockRiskSdkUseCase, - ) + Dispatchers.setMain(testDispatcher) + tokenRepositoryImpl = TokenRepositoryImpl( + networkApiClient = mockTokenNetworkApiClient, + cardToTokenRequestMapper = CardToTokenRequestMapper(), + cvvToTokenNetworkRequestMapper = CVVToTokenNetworkRequestMapper(), + cardTokenizationNetworkDataMapper = CardTokenizationNetworkDataMapper(), + validateTokenizationDataUseCase = mockValidateTokenizationDataUseCase, + validateCVVTokenizationDataUseCase = mockValidateCVVTokenizationDataUseCase, + logger = mockTokenizationLogger, + publicKey = "test_key", + cvvTokenizationNetworkDataMapper = CVVTokenizationNetworkDataMapper(), + riskSdkUseCase = mockRiskSdkUseCase, + ) + } + + @AfterEach + fun teardown() { + Dispatchers.resetMain() } @DisplayName("CardToken Details invocation") @@ -144,10 +153,7 @@ internal class TokenRepositoryImplTest { // Given val response = mockk>() - val testDispatcher = UnconfinedTestDispatcher(testScheduler) - Dispatchers.setMain(testDispatcher) - - tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(StandardTestDispatcher(testScheduler)) + tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(testDispatcher) every { mockValidateTokenizationDataUseCase.execute(any()) } returns ValidationResult.Success(Unit) coEvery { mockTokenNetworkApiClient.sendCardTokenRequest(any()) } returns response @@ -180,10 +186,7 @@ internal class TokenRepositoryImplTest { // Given var isSuccess = false - val testDispatcher = UnconfinedTestDispatcher(testScheduler) - Dispatchers.setMain(testDispatcher) - - tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(StandardTestDispatcher(testScheduler)) + tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(testDispatcher) coEvery { mockValidateTokenizationDataUseCase.execute(any()) } returns ValidationResult.Success(Unit) @@ -223,10 +226,7 @@ internal class TokenRepositoryImplTest { NetworkApiResponse.ServerError(serverErrorBody, 501) } - val testDispatcher = UnconfinedTestDispatcher(testScheduler) - Dispatchers.setMain(testDispatcher) - - tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(StandardTestDispatcher(testScheduler)) + tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(testDispatcher) every { mockValidateTokenizationDataUseCase.execute(any()) } returns ValidationResult.Success(Unit) coEvery { mockTokenNetworkApiClient.sendCardTokenRequest(any()) } returns response @@ -343,10 +343,7 @@ internal class TokenRepositoryImplTest { ) val captureError = mutableListOf() - val testDispatcher = UnconfinedTestDispatcher(testScheduler) - Dispatchers.setMain(testDispatcher) - - tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(StandardTestDispatcher(testScheduler)) + tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(testDispatcher) coEvery { mockTokenNetworkApiClient.sendGooglePayTokenRequest(any()) @@ -391,10 +388,7 @@ internal class TokenRepositoryImplTest { // Given val response = mockk>() - val testDispatcher = UnconfinedTestDispatcher(testScheduler) - Dispatchers.setMain(testDispatcher) - - tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(StandardTestDispatcher(testScheduler)) + tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(testDispatcher) coEvery { mockTokenNetworkApiClient.sendCardTokenRequest(any()) } returns response @@ -422,11 +416,9 @@ internal class TokenRepositoryImplTest { // Given var isSuccess: Boolean? = null - val testDispatcher = UnconfinedTestDispatcher(testScheduler) tokenRepositoryImpl = createTokenRepository(testDispatcher) - Dispatchers.setMain(testDispatcher) - tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(StandardTestDispatcher(testScheduler)) + tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(testDispatcher) coEvery { mockTokenNetworkApiClient.sendGooglePayTokenRequest(any()) } returns response coEvery { mockRiskSdkUseCase.execute(any()) } returns Unit @@ -451,10 +443,7 @@ internal class TokenRepositoryImplTest { var errorMessage = "" val successHandlerInvoked = false - val testDispatcher = UnconfinedTestDispatcher(testScheduler) - Dispatchers.setMain(testDispatcher) - - tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(StandardTestDispatcher(testScheduler)) + tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(testDispatcher) coEvery { mockTokenNetworkApiClient.sendGooglePayTokenRequest(any()) } returns response @@ -493,10 +482,7 @@ internal class TokenRepositoryImplTest { NetworkApiResponse.ServerError(serverErrorBody, 501) } - val testDispatcher = UnconfinedTestDispatcher(testScheduler) - Dispatchers.setMain(testDispatcher) - - tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(StandardTestDispatcher(testScheduler)) + tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(testDispatcher) coEvery { mockTokenNetworkApiClient.sendGooglePayTokenRequest(any()) } returns response @@ -559,10 +545,8 @@ internal class TokenRepositoryImplTest { fun `when sendCVVTokenizationRequest invoked with success response then success handler invoked`() { testCVVTokenResultInvocation( successHandlerInvoked = true, - response = - NetworkApiResponse.Success( - body = - CVVTokenDetailsResponse( + response = NetworkApiResponse.Success( + body = CVVTokenDetailsResponse( type = "cvv", token = "test_token", expiresOn = "2019-08-24T14:15:22Z", @@ -591,8 +575,7 @@ internal class TokenRepositoryImplTest { fun `when sendCVVTokenizationRequest invoked with internal error response then failure handler invoked`() { testCVVTokenResultInvocation( successHandlerInvoked = false, - response = - NetworkApiResponse.InternalError( + response = NetworkApiResponse.InternalError( TokenizationError( errorCode = "internal_error", message = "exception.message", @@ -627,9 +610,7 @@ internal class TokenRepositoryImplTest { coEvery { mockTokenNetworkApiClient.sendCVVTokenRequest(any()) } returns response // When - tokenRepositoryImpl.sendCVVTokenizationRequest( - cvvTokenizationRequest, - ) + tokenRepositoryImpl.sendCVVTokenizationRequest(cvvTokenizationRequest) // Then launch { @@ -648,11 +629,9 @@ internal class TokenRepositoryImplTest { ) = runTest { // Given var isSuccess: Boolean? = null + val resultReceived = CompletableDeferred() - val testDispatcher = UnconfinedTestDispatcher(testScheduler) - Dispatchers.setMain(testDispatcher) - - tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(StandardTestDispatcher(testScheduler)) + tokenRepositoryImpl.networkCoroutineScope = CoroutineScope(testDispatcher) coEvery { mockValidateCVVTokenizationDataUseCase.execute(any()) } returns ValidationResult.Success(Unit) @@ -665,17 +644,19 @@ internal class TokenRepositoryImplTest { cvv = "123", cardScheme = CardScheme.VISA, resultHandler = { result -> - isSuccess = - when (result) { - is CVVTokenizationResultHandler.Success -> true - is CVVTokenizationResultHandler.Failure -> false - } + isSuccess = when (result) { + is CVVTokenizationResultHandler.Success -> true + is CVVTokenizationResultHandler.Failure -> false + } + resultReceived.complete(Unit) }, ), ) + advanceUntilIdle() + resultReceived.await() // Then - launch { assertEquals(isSuccess.toString(), successHandlerInvoked.toString()) } + assertEquals(isSuccess.toString(), successHandlerInvoked.toString()) } private fun testCVVTokenizationEventInvocation(isSuccessResponse: Boolean) = diff --git a/example_app_frames/build.gradle.kts b/example_app_frames/build.gradle.kts index 176a7dc0e..aad77d19c 100644 --- a/example_app_frames/build.gradle.kts +++ b/example_app_frames/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("precompiled-android-app") + id("org.jetbrains.kotlin.plugin.compose") } android { @@ -20,15 +21,7 @@ android { } } - buildFeatures { - compose = true - } - - composeOptions { - kotlinCompilerExtensionVersion = Versions.compose_compiler_ext - } - - packagingOptions { + packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } @@ -39,7 +32,7 @@ dependencies { implementation(FramesConfig.framesAndroidDependency) } -configurations.all { +configurations.configureEach { resolutionStrategy.dependencySubstitution { if (FramesConfig.useLocalModuleDependencies) { diff --git a/frames/build.gradle.kts b/frames/build.gradle.kts index 72aa6409c..58d751031 100644 --- a/frames/build.gradle.kts +++ b/frames/build.gradle.kts @@ -10,7 +10,8 @@ import org.jetbrains.dokka.gradle.DokkaTask plugins { id("com.android.library") kotlin("android") - kotlin("kapt") + id("com.google.devtools.ksp") + id("org.jetbrains.kotlin.plugin.compose") id("org.jetbrains.dokka") id("maven-publish") } @@ -55,24 +56,26 @@ android { } buildFeatures { - compose = true viewBinding = true } - - composeOptions { - kotlinCompilerExtensionVersion = Versions.compose_compiler_ext + publishing { + singleVariant("release") {} } - buildTypes { release { proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") } } - kotlinOptions { - // Needed to prevent warning when ViewModelProvider.Factory inherited - // "Inheritance from an interface with '@JvmDefault' members is only allowed with -Xjvm-default option" - freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all-compatibility" + kotlin { + compilerOptions { + // Needed to prevent warning when ViewModelProvider.Factory inherited + // "Inheritance from an interface with '@JvmDefault' members is only allowed with -Xjvm-default option" + freeCompilerArgs.addAll( + "-Xjvm-default=all-compatibility", + "-Xannotation-default-target=param-property", + ) + } } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7b03c52d6..9b8b67c75 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Fri Jul 15 15:23:43 BST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle.kts b/settings.gradle.kts index df67129c9..2b5df15de 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,6 @@ @file:Suppress("UnstableApiUsage") -include(":app", ":checkout", ":frames",":example_app_frames") +include(":app", ":checkout", ":frames", ":example_app_frames") /** * Setup dependencies for all projects @@ -11,7 +11,6 @@ dependencyResolutionManagement { mavenLocal() google() mavenCentral() - jcenter() maven { url = uri("https://jitpack.io") } maven { url = uri("https://maven.fpregistry.io/releases") } }