diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index edd04783..e3476ae8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -13,6 +13,9 @@ on:
paths-ignore:
- '**.md'
+env:
+ JAVA_VERSION: '17'
+
jobs:
test:
name: 'Test Unit'
@@ -21,7 +24,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
- java-version: '11'
+ java-version: ${{ env.JAVA_VERSION }}
distribution: adopt
- uses: gradle/gradle-build-action@v2
with:
@@ -44,6 +47,9 @@ jobs:
fail-fast: false
matrix:
include:
+ - compile: 34
+ target: 34
+ appcompat: 1.6.1
- compile: 33
target: 33
appcompat: 1.5.1
@@ -60,7 +66,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
- java-version: '11'
+ java-version: ${{ env.JAVA_VERSION }}
distribution: adopt
- uses: gradle/gradle-build-action@v2
with:
@@ -82,7 +88,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
- java-version: '11'
+ java-version: ${{ env.JAVA_VERSION }}
distribution: adopt
- uses: gradle/gradle-build-action@v2
with:
@@ -119,14 +125,72 @@ jobs:
profile: Nexus 6
script: |
brew install parallel
- parallel --retries 3 ::: "./gradlew sdk:connectedCheck"
+ parallel --retries 3 ::: "./gradlew test:connectedCheck"
- if: failure()
uses: actions/upload-artifact@v3
with:
name: androidTest-results
path: |
- sdk/build/outputs/androidTest-results
- sdk/build/reports/androidTests
+ test/build/outputs/androidTest-results
+ test/build/reports/androidTests
+
+ test-minified:
+ name: 'Test UI Minified'
+ runs-on: macos-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ api-level: [29]
+ target: [default]
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-java@v3
+ with:
+ java-version: ${{ env.JAVA_VERSION }}
+ distribution: adopt
+ - uses: gradle/gradle-build-action@v2
+ with:
+ cache-read-only: false
+ - name: 'Cache AVD'
+ uses: actions/cache@v3
+ id: avd-cache
+ with:
+ path: |
+ ~/.android/avd/*
+ ~/.android/adb*
+ key: avd-api-${{ matrix.api-level }}-target-${{ matrix.target }}
+ - name: 'Create AVD'
+ if: steps.avd-cache.outputs.cache-hit != 'true'
+ uses: reactivecircus/android-emulator-runner@v2
+ with:
+ api-level: ${{ matrix.api-level }}
+ target: ${{ matrix.target }}
+ emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
+ force-avd-creation: false
+ disable-animations: false
+ arch: x86_64
+ profile: Nexus 6
+ script: echo "Generated AVD snapshot for caching."
+ - name: 'Tests'
+ uses: reactivecircus/android-emulator-runner@v2
+ with:
+ api-level: ${{ matrix.api-level }}
+ target: ${{ matrix.target }}
+ emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
+ force-avd-creation: false
+ disable-animations: true
+ arch: x86_64
+ profile: Nexus 6
+ script: |
+ brew install parallel
+ parallel --retries 3 ::: "./gradlew test:connectedCheck -P testingMinimizedBuild=true -P android.enableR8.fullMode=false"
+ - if: failure()
+ uses: actions/upload-artifact@v3
+ with:
+ name: androidTest-minified-results
+ path: |
+ test/build/outputs/androidTest-results
+ test/build/reports/androidTests
test-benchmark:
name: 'Test Benchmark'
@@ -140,7 +204,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
- java-version: '11'
+ java-version: ${{ env.JAVA_VERSION }}
distribution: adopt
- uses: gradle/gradle-build-action@v2
with:
@@ -174,13 +238,13 @@ jobs:
disable-animations: true
arch: x86_64
profile: Nexus 6
- script: ./gradlew bench:connectedReleaseAndroidTest
+ script: ./gradlew benchmark:connectedReleaseAndroidTest
- name: Diff benchmark result
id: diff-benchmark
uses: ./.github/actions/android-benchmark-diff
with:
reference: benchmark/data/ci-benchmarkData.json
- compare-with: benchmark/build/outputs/connected_android_test_additional_output/releaseAndroidTest/connected/test(AVD) - 10/com.hcaptcha.sdk.bench.test-benchmarkData.json
+ compare-with: benchmark/build/outputs/connected_android_test_additional_output/releaseAndroidTest/connected/test(AVD) - 10/com_hcaptcha_sdk_bench_test-benchmarkData.json
- name: Log diff benchmark reuslts
run: echo "${{ steps.diff-benchmark.outputs.markdown-table }}"
- uses: peter-evans/find-comment@v2
@@ -215,7 +279,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-java@v3
with:
- java-version: '11'
+ java-version: ${{ env.JAVA_VERSION }}
distribution: adopt
- uses: gradle/gradle-build-action@v2
with:
@@ -241,7 +305,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-java@v3
with:
- java-version: '11'
+ java-version: ${{ env.JAVA_VERSION }}
distribution: adopt
- uses: gradle/gradle-build-action@v2
with:
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index 7703a48f..f776e392 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -7,8 +7,22 @@
There is automated testing for every `push` command through github actions (see `.github/workflows/ci.yml`).
You can manually test before pushing by running both unit tests and instrumented tests:
-* ```gradlew test```
-* ```gradlew connectedDebugAndroidTest```
+* `./gradlew sdk:test`
+* `./gradlew test:connectedAndroidTest`
+* `./gradlew test:connectedAndroidTest -P testingMinimizedBuild=true -P android.enableR8.fullMode=false`
+
+## Manual testing
+
++ {normal,invisible,compact} -> verify -> success -> mark used
++ {normal,invisible,compact} -> verify -> success -> token timeout
+
++ {normal,invisible,compact} -> verify -> touch outside -> challenge closed
++ {normal,invisible,compact} -> verify -> back button -> challenge closed
+
++ {normal,invisible,compact} -> verify -> rotate device (recreate activity) -> hcaptcha gone, no callbacks fired
++ {normal,invisible,compact} -> verify -> send app to background -> open app from history again -> hcaptcha is displayed
+
++ {hide dialog} -> verify -> token obtained -> mark used
# Publishing
diff --git a/benchmark/build.gradle b/benchmark/build.gradle
index 0c487b3c..e8015157 100644
--- a/benchmark/build.gradle
+++ b/benchmark/build.gradle
@@ -4,7 +4,7 @@ plugins {
}
android {
- compileSdkVersion 33
+ compileSdk 34
namespace 'com.hcaptcha.sdk.bench'
compileOptions {
@@ -14,7 +14,7 @@ android {
defaultConfig {
minSdkVersion 16
- targetSdkVersion 33
+ targetSdkVersion 34
testInstrumentationRunner 'androidx.benchmark.junit4.AndroidBenchmarkRunner'
testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,EMULATOR,LOW-BATTERY,UNLOCKED"
@@ -36,14 +36,29 @@ android {
}
dependencies {
- androidTestImplementation 'androidx.test:runner:1.5.1'
- androidTestImplementation 'androidx.test.ext:junit:1.1.4'
+ androidTestImplementation 'androidx.test:runner:1.5.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.benchmark:benchmark-junit4:1.1.1'
+ androidTestImplementation 'androidx.benchmark:benchmark-junit4:1.2.0'
implementation project(path: ':sdk')
- implementation 'androidx.appcompat:appcompat:1.5.1'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
}
// Workaround for: java.lang.ClassNotFoundException: com.android.tools.lint.client.api.Vendor
-lint.enabled = false
\ No newline at end of file
+lint.enabled = false
+
+tasks.register('pullBenchmarkData', Exec) {
+ def packageName = android.namespace + ".test"
+
+ commandLine java.nio.file.Paths.get(android.sdkDirectory.absolutePath, "platform-tools", "adb"),
+ "pull",
+ "/storage/emulated/0/Android/media/" \
+ + "${packageName}/additional_test_output/" \
+ + "${packageName.replace('.', '_')}-benchmarkData.json",
+ "${projectDir}/build/outputs/"
+
+ doFirst {
+ println "pullBenchmarkData: ${commandLine.join(' ')}"
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 562958a8..292133d2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,8 +6,9 @@ buildscript {
maven { url 'https://jitpack.io' }
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.2.2'
- classpath 'androidx.benchmark:benchmark-gradle-plugin:1.1.1'
+ classpath 'com.android.tools.build:gradle:8.1.3'
+ classpath 'androidx.benchmark:benchmark-gradle-plugin:1.2.0'
+ classpath 'com.slack.keeper:keeper:0.15.0'
}
}
diff --git a/example-app/build.gradle b/example-app/build.gradle
index dc4c3f08..fbc7f607 100644
--- a/example-app/build.gradle
+++ b/example-app/build.gradle
@@ -9,14 +9,12 @@ def prop(name, fallback) {
}
android {
- compileSdkVersion intProp("exampleCompileSdkVersion", 32)
- buildToolsVersion "30.0.3"
+ compileSdk intProp("exampleCompileSdkVersion", 34)
namespace 'com.hcaptcha.example'
defaultConfig {
- applicationId "com.hcaptcha.example"
minSdkVersion 16
- targetSdkVersion intProp("exampleTargetSdkVersion", 32)
+ targetSdkVersion intProp("exampleTargetSdkVersion", 34)
versionCode 1
versionName "0.0.1"
diff --git a/example-app/src/main/java/com/hcaptcha/example/App.java b/example-app/src/main/java/com/hcaptcha/example/App.java
index d783b16a..28bc8ff8 100644
--- a/example-app/src/main/java/com/hcaptcha/example/App.java
+++ b/example-app/src/main/java/com/hcaptcha/example/App.java
@@ -8,7 +8,7 @@ public class App extends Application {
public void onCreate() {
super.onCreate();
- if (BuildConfig.DEBUG) {
+ if (com.hcaptcha.sdk.BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(
new StrictMode.ThreadPolicy.Builder()
.detectAll()
diff --git a/gradle.properties b/gradle.properties
index 710b2f09..2b1e584a 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -17,7 +17,5 @@ org.gradle.jvmargs=-Xmx2048m
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
-# Software Components will not be created automatically for Maven publishing from Android Gradle Plugin 8.0
-android.disableAutomaticComponentCreation=true
# To test more aggressive optimizations
android.enableR8.fullMode=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index ae04661e..84a0b92f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/sdk/build.gradle b/sdk/build.gradle
index 7901da5d..84535379 100644
--- a/sdk/build.gradle
+++ b/sdk/build.gradle
@@ -1,23 +1,25 @@
plugins {
+ id "com.android.library"
id "pmd"
id "jacoco"
id "checkstyle"
- id "com.github.spotbugs" version "4.8.0"
+ id "maven-publish"
+ id "com.github.spotbugs" version "5.2.3"
id "org.owasp.dependencycheck" version "7.1.1"
id "org.sonarqube" version "3.4.0.2513"
}
-apply plugin: 'com.android.library'
-apply plugin: 'maven-publish'
-
android {
- compileSdkVersion 33
- buildToolsVersion "30.0.3"
+ compileSdk 34
namespace 'com.hcaptcha.sdk'
+ buildFeatures {
+ buildConfig true
+ }
+
defaultConfig {
minSdkVersion 16
- targetSdkVersion 33
+ targetSdkVersion 34
// See https://developer.android.com/studio/publish/versioning
// versionCode must be integer and be incremented by one for every new update
@@ -30,10 +32,8 @@ android {
buildConfigField 'String', 'VERSION_NAME', "\"${defaultConfig.versionName}_${defaultConfig.versionCode}\""
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- multiDexEnabled true
}
compileOptions {
@@ -65,27 +65,15 @@ android {
}
dependencies {
- implementation fileTree(dir: "libs", include: ["*.jar"])
//noinspection GradleDependency
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.3'
- compileOnly 'org.projectlombok:lombok:1.18.16'
- annotationProcessor 'org.projectlombok:lombok:1.18.16'
+ compileOnly 'org.projectlombok:lombok:1.18.30'
+ annotationProcessor 'org.projectlombok:lombok:1.18.30'
testImplementation 'junit:junit:4.13.2'
- testImplementation 'org.mockito:mockito-inline:3.6.28'
- testImplementation 'org.skyscreamer:jsonassert:1.5.0'
-
- androidTestImplementation 'androidx.test:core:1.5.0'
- androidTestImplementation 'androidx.test:runner:1.5.2'
- androidTestImplementation 'androidx.test:rules:1.5.0'
- androidTestImplementation 'androidx.test.ext:junit:1.1.5'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
- androidTestImplementation 'androidx.test.espresso:espresso-web:3.5.1'
- androidTestImplementation 'androidx.fragment:fragment-testing:1.4.1' // cannot upgrade because https://issuetracker.google.com/issues/266687550
-
- androidTestImplementation "androidx.multidex:multidex:2.0.1"
- androidTestImplementation "org.mockito:mockito-android:3.6.28"
+ testImplementation 'org.mockito:mockito-inline:4.8.1'
+ testImplementation 'org.skyscreamer:jsonassert:1.5.1'
compileOnly 'com.google.code.findbugs:annotations:3.0.1'
}
@@ -143,8 +131,8 @@ android.libraryVariants.all { variant ->
dependsOn variant.packageLibraryProvider
doFirst {
- String aarPath = variant.packageLibraryProvider.get().archivePath
- long aarSizeKb = file(aarPath).length() / 1024
+ var aarPath = variant.packageLibraryProvider.get().archiveFile.get().getAsFile()
+ long aarSizeKb = aarPath.length() / 1024
println("File ${aarPath} is ${aarSizeKb}Kbyte")
}
}
@@ -155,8 +143,8 @@ android.libraryVariants.all { variant ->
dependsOn variant.packageLibraryProvider
doFirst {
- String aarPath = variant.packageLibraryProvider.get().archivePath
- long aarSizeKb = file(aarPath).length() / 1024
+ var aarFile = variant.packageLibraryProvider.get().archiveFile.get().getAsFile()
+ long aarSizeKb = aarFile.length() / 1024
if (aarSizeKb > MAX_AAR_SIZE_KB) {
throw new GradleException("${aarPath} size exceeded! ${aarSizeKb}Kbyte > ${MAX_AAR_SIZE_KB}Kbyte")
}
@@ -244,8 +232,8 @@ spotbugs {
gradle.taskGraph.beforeTask { task ->
if (task.name.toLowerCase().contains('spotbugs')) {
task.reports {
- html.enabled = true
- xml.enabled = true
+ html.enabled true
+ xml.enabled true
}
}
}
@@ -271,8 +259,8 @@ task jacocoUnitTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest'])
executionData.from = "${project.buildDir}/jacoco/testDebugUnitTest.exec"
reports {
- xml.enabled = true
- html.enabled = true
+ xml.required = true
+ html.required = true
}
}
@@ -289,7 +277,7 @@ sonarqube {
property "sonar.sources", "src/main"
property "sonar.java.binaries", "${project.buildDir}/intermediates/javac/debug/classes"
- property "sonar.tests", ["src/test/", "src/androidTest/"]
+ property "sonar.tests", ["src/test/", "../test/src/androidTest/"]
property "sonar.android.lint.report", "${project.buildDir}/outputs/lint-results.xml"
property "sonar.java.spotbugs.reportPaths", ["${project.buildDir}/reports/spotbugs/debug.xml", "${project.buildDir}/reports/spotbugs/release.xml"]
@@ -300,3 +288,4 @@ sonarqube {
}
project.tasks["sonarqube"].dependsOn "check"
+
diff --git a/sdk/consumer-rules.pro b/sdk/consumer-rules.pro
index 8d5fa2b0..d08a981c 100644
--- a/sdk/consumer-rules.pro
+++ b/sdk/consumer-rules.pro
@@ -1,6 +1,10 @@
-dontwarn javax.annotation.processing.**
-dontwarn lombok.core.configuration.**
-dontwarn org.apache.tools.**
+-dontwarn android.content.pm.PackageManager$ApplicationInfoFlags
+-dontwarn edu.umd.cs.findbugs.annotations.*
+-dontwarn java.beans.*
+-dontwarn lombok.*
# Prevent obfuscating the names when serializing to JSON
-keep class com.hcaptcha.sdk.HCaptchaConfig { *; }
diff --git a/sdk/src/androidTest/AndroidManifest.xml b/sdk/src/androidTest/AndroidManifest.xml
deleted file mode 100644
index f3d6cf30..00000000
--- a/sdk/src/androidTest/AndroidManifest.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/sdk/src/androidTest/java/com/hcaptcha/sdk/ExampleInstrumentedTest.java b/sdk/src/androidTest/java/com/hcaptcha/sdk/ExampleInstrumentedTest.java
deleted file mode 100644
index 7fc12d44..00000000
--- a/sdk/src/androidTest/java/com/hcaptcha/sdk/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.hcaptcha.sdk;
-
-import static org.junit.Assert.assertEquals;
-
-import android.content.Context;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Instrumented test, which will execute on an Android device.
- *
- * @see Testing documentation
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() {
- // Context of the app under test.
- final Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
- assertEquals("com.hcaptcha.sdk.test", appContext.getPackageName());
- }
-}
diff --git a/sdk/src/androidTest/java/com/hcaptcha/sdk/TestActivity.java b/sdk/src/androidTest/java/com/hcaptcha/sdk/TestActivity.java
deleted file mode 100644
index 64d17547..00000000
--- a/sdk/src/androidTest/java/com/hcaptcha/sdk/TestActivity.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.hcaptcha.sdk;
-
-import androidx.fragment.app.FragmentActivity;
-
-public class TestActivity extends FragmentActivity {
-}
diff --git a/sdk/src/test/java/com/hcaptcha/sdk/HCaptchaTest.java b/sdk/src/test/java/com/hcaptcha/sdk/HCaptchaTest.java
index ac5136d5..620dd902 100644
--- a/sdk/src/test/java/com/hcaptcha/sdk/HCaptchaTest.java
+++ b/sdk/src/test/java/com/hcaptcha/sdk/HCaptchaTest.java
@@ -125,11 +125,11 @@ public void test_verify_with_hcaptcha_passes_site_key_as_config() {
final String siteKey = HCaptchaConfigTest.MOCK_SITE_KEY;
final HCaptcha hCaptcha = HCaptcha.getClient(fragmentActivity);
- dialogFragmentMock.verify(never(), () ->
+ dialogFragmentMock.verify(() ->
HCaptchaDialogFragment.newInstance(
any(HCaptchaConfig.class),
any(HCaptchaInternalConfig.class),
- any(HCaptchaStateListener.class)));
+ any(HCaptchaStateListener.class)), never());
hCaptcha.verifyWithHCaptcha(siteKey);
@@ -199,11 +199,11 @@ public void test_verify_config_has_priority_over_setup_config() throws Exception
.verifyWithHCaptcha(verifyConfig);
verify(packageManager, never()).getApplicationInfo(any(String.class), anyInt());
- dialogFragmentMock.verify(times(2), () ->
+ dialogFragmentMock.verify(() ->
HCaptchaDialogFragment.newInstance(
hCaptchaConfigCaptor.capture(),
any(HCaptchaInternalConfig.class),
- any(HCaptchaStateListener.class)));
+ any(HCaptchaStateListener.class)), times(2));
assertEquals(verifyConfig, hCaptchaConfigCaptor.getValue());
}
@@ -216,11 +216,11 @@ public void test_verify_site_key_has_priority_over_setup_config() throws Excepti
.verifyWithHCaptcha(siteKey);
verify(packageManager, never()).getApplicationInfo(any(String.class), anyInt());
- dialogFragmentMock.verify(times(2), () ->
+ dialogFragmentMock.verify(() ->
HCaptchaDialogFragment.newInstance(
hCaptchaConfigCaptor.capture(),
any(HCaptchaInternalConfig.class),
- any(HCaptchaStateListener.class)));
+ any(HCaptchaStateListener.class)), times(2));
assertEquals(siteKey, hCaptchaConfigCaptor.getValue().getSiteKey());
}
diff --git a/settings.gradle b/settings.gradle
index 96e2fce7..892e2df7 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,4 +1,5 @@
-include ':example-app'
-include ':sdk'
rootProject.name = "hcaptcha-android-sdk"
+include ':sdk'
+include ':test'
include ':benchmark'
+include ':example-app'
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/test/build.gradle b/test/build.gradle
new file mode 100644
index 00000000..e4387dca
--- /dev/null
+++ b/test/build.gradle
@@ -0,0 +1,61 @@
+apply plugin: 'com.android.application'
+if (project.hasProperty("testingMinimizedBuild")) {
+ apply plugin: 'com.slack.keeper'
+}
+
+android {
+ compileSdk 34
+ namespace 'com.hcaptcha.sdk.test'
+
+ defaultConfig {
+ applicationId "com.hcaptcha.sdk.test"
+ minSdkVersion 19
+ targetSdkVersion 34
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ signingConfig signingConfigs.debug
+ minifyEnabled true
+ shrinkResources true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), '../sdk/consumer-rules.pro'
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ testBuildType = project.hasProperty("testingMinimizedBuild") ? "release" : "debug"
+}
+
+androidComponents {
+ beforeVariants(selector().all()) { variantBuilder ->
+ if (variantBuilder.name == "release") {
+ variantBuilder.registerExtension(
+ com.slack.keeper.KeeperVariantMarker.class,
+ com.slack.keeper.KeeperVariantMarker.INSTANCE)
+ }
+ }
+}
+
+dependencies {
+ implementation project(path: ':sdk')
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+
+ testImplementation 'junit:junit:4.13.2'
+
+ androidTestImplementation 'androidx.fragment:fragment-testing:1.6.2'
+ androidTestImplementation 'androidx.test:core:1.5.0'
+ androidTestImplementation 'androidx.test:rules:1.5.0'
+ androidTestImplementation 'androidx.test:runner:1.5.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+ androidTestImplementation 'androidx.test.espresso:espresso-web:3.5.1'
+ androidTestImplementation 'org.mockito:mockito-android:5.3.1'
+}
diff --git a/test/proguard-rules.pro b/test/proguard-rules.pro
new file mode 100644
index 00000000..e23fa22e
--- /dev/null
+++ b/test/proguard-rules.pro
@@ -0,0 +1 @@
+# Proguard rules that are applied to your test apk/code.
diff --git a/sdk/src/androidTest/java/com/hcaptcha/sdk/AssertUtil.java b/test/src/androidTest/java/com/hcaptcha/sdk/AssertUtil.java
similarity index 100%
rename from sdk/src/androidTest/java/com/hcaptcha/sdk/AssertUtil.java
rename to test/src/androidTest/java/com/hcaptcha/sdk/AssertUtil.java
diff --git a/sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaDialogFragmentTest.java b/test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaDialogFragmentTest.java
similarity index 97%
rename from sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaDialogFragmentTest.java
rename to test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaDialogFragmentTest.java
index 3cd4f57b..c4ef51c4 100644
--- a/sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaDialogFragmentTest.java
+++ b/test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaDialogFragmentTest.java
@@ -41,6 +41,9 @@
import androidx.test.espresso.web.webdriver.Locator;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.hcaptcha.sdk.test.TestActivity;
+
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -217,6 +220,8 @@ void onFailure(HCaptchaException exception) {
@Test
public void webViewNotInstalled() throws InterruptedException {
+ Assume.assumeTrue("Skip test for release, because impossible to mock LayoutInflater", BuildConfig.DEBUG);
+
final LayoutInflater inflater = mock(LayoutInflater.class);
when(inflater.inflate(eq(R.layout.hcaptcha_fragment), any(), eq(false)))
.thenThrow(InflateException.class);
@@ -350,13 +355,14 @@ public void testVerifyOnStoppedFragmentNoException() throws InterruptedException
@Test(expected = IllegalArgumentException.class)
public void testReset() {
- final FragmentScenario scenario = launchInContainer(
- config, new HCaptchaStateTestAdapter());
+ try (final FragmentScenario scenario = launchInContainer(
+ config, new HCaptchaStateTestAdapter())) {
- scenario.onFragment(HCaptchaDialogFragment::reset);
+ scenario.onFragment(HCaptchaDialogFragment::reset);
- // The fragment has been removed from the FragmentManager already.
- scenario.onFragment(fragment -> assertTrue(fragment.isDetached()));
+ // The fragment has been removed from the FragmentManager already.
+ scenario.onFragment(fragment -> assertTrue(fragment.isDetached()));
+ }
}
@Test
diff --git a/sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaHeadlessWebViewTest.java b/test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaHeadlessWebViewTest.java
similarity index 99%
rename from sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaHeadlessWebViewTest.java
rename to test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaHeadlessWebViewTest.java
index 9dc2073d..45bafe1d 100644
--- a/sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaHeadlessWebViewTest.java
+++ b/test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaHeadlessWebViewTest.java
@@ -13,6 +13,8 @@
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.hcaptcha.sdk.test.TestActivity;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaStateTestAdapter.java b/test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaStateTestAdapter.java
similarity index 100%
rename from sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaStateTestAdapter.java
rename to test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaStateTestAdapter.java
diff --git a/sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaTest.java b/test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaTest.java
similarity index 97%
rename from sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaTest.java
rename to test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaTest.java
index d8088bbd..1754eb8d 100644
--- a/sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaTest.java
+++ b/test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaTest.java
@@ -9,6 +9,8 @@
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import com.hcaptcha.sdk.tasks.OnSuccessListener;
+import com.hcaptcha.sdk.test.TestActivity;
+
import org.junit.Rule;
import org.junit.Test;
@@ -99,7 +101,7 @@ public void e2eWithDebugTokenFragmentDialog() throws Exception {
response.markUsed();
latch.countDown();
})
- .addOnFailureListener(exception -> fail("No errors expected")));
+ .addOnFailureListener(exception -> fail("No errors expected but received: " + exception.getHCaptchaError())));
assertTrue(latch.await(E2E_AWAIT_CALLBACK_MS, TimeUnit.MILLISECONDS));
}
diff --git a/sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaTestHtml.java b/test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaTestHtml.java
similarity index 100%
rename from sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaTestHtml.java
rename to test/src/androidTest/java/com/hcaptcha/sdk/HCaptchaTestHtml.java
diff --git a/test/src/main/AndroidManifest.xml b/test/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..d9151625
--- /dev/null
+++ b/test/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/src/main/java/com/hcaptcha/sdk/test/TestActivity.java b/test/src/main/java/com/hcaptcha/sdk/test/TestActivity.java
new file mode 100644
index 00000000..0287f9a1
--- /dev/null
+++ b/test/src/main/java/com/hcaptcha/sdk/test/TestActivity.java
@@ -0,0 +1,4 @@
+package com.hcaptcha.sdk.test;
+
+public class TestActivity extends androidx.appcompat.app.AppCompatActivity {
+}
\ No newline at end of file
diff --git a/test/src/main/res/drawable/ic_launcher_background.xml b/test/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..07d5da9c
--- /dev/null
+++ b/test/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/test/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..317d6ccf
Binary files /dev/null and b/test/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/test/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/test/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..b45165c8
Binary files /dev/null and b/test/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/test/src/main/res/values/strings.xml b/test/src/main/res/values/strings.xml
new file mode 100644
index 00000000..fde7ba53
--- /dev/null
+++ b/test/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ test
+
\ No newline at end of file