diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 88cfc31..575cdec 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -100,6 +100,23 @@ test:plugin: reports: junit: dd-sdk-android-gradle-plugin/build/test-results/test/TEST-*.xml +test:instrumented: + tags: [ "arch:amd64" ] + image: $CI_IMAGE_DOCKER + stage: test + timeout: 1h + script: + - git fetch --depth=1 origin main + - rm -rf ~/.gradle/daemon/ + - CODECOV_TOKEN=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android-gradle-plugin.codecov-token --with-decryption --query "Parameter.Value" --out text) + - export DD_AGENT_HOST="$BUILDENV_HOST_IP" + - GRADLE_OPTS="-Xmx2560m" DD_TAGS="test.module:instrumented" ./gradlew :instrumented:test --stacktrace --no-daemon -Dorg.gradle.jvmargs=-javaagent:$(pwd)/libs/dd-java-agent-1.26.1.jar=$DD_COMMON_AGENT_CONFIG + - bash <(cat ./codecov.sh) -t $CODECOV_TOKEN + artifacts: + reports: + junit: instrumented/build/test-results/test/TEST-*.xml + + # PUBLISH ARTIFACTS publish:publish-sonatype: diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 53323d4..cc99038 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,14 +1,17 @@ [versions] + # Commons kotlin = "1.9.23" +kotlinComposePlugin = "2.0.20" json = "20180813" okHttp = "4.12.0" +composeBom = "2024.04.01" +activityCompose = "1.9.3" # Android androidToolsPlugin = "8.7.2" - # AndroidX -androidx-core ="1.3.2" +androidx-core = "1.3.2" androidx-appcompat = "1.2.0" androidx-constraintlayout = "2.0.4" @@ -43,6 +46,9 @@ datadogPluginGradle = "1.15.0" # Kotlin Compiler Plugin kotlinCompilerEmbeddable = "1.8.20" autoService = "1.0.1" +junitVersion = "1.2.1" +espressoCoreVersion = "3.6.1" +lifecycleRuntimeKtx = "2.8.7" [libraries] @@ -62,9 +68,9 @@ json = { module = "org.json:json", version.ref = "json" } # AndroidX -androidx-core = { module = "androidx.core:core-ktx", version.ref="androidx-core" } -androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref="androidx-appcompat" } -androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref="androidx-constraintlayout" } +androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" } +androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" } +androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx-constraintlayout" } assertJ = { module = "org.assertj:assertj-core", version.ref = "assertJ" } @@ -98,9 +104,23 @@ datadogSdkRum = { module = "com.datadoghq:dd-sdk-android-rum", version.ref = "da datadogPluginGradle = { module = "com.datadoghq:dd-sdk-android-gradle-plugin", version.ref = "datadogPluginGradle" } # Kotlin Compiler Plugin -kotlinCompilerEmbeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "kotlinCompilerEmbeddable" } -autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" } -autoServiceAnnotation = { module = "com.google.auto.service:auto-service-annotations", version.ref = "autoService" } +kotlinCompilerEmbeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "kotlinCompilerEmbeddable" } +autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" } +autoServiceAnnotation = { module = "com.google.auto.service:auto-service-annotations", version.ref = "autoService" } + +# Compose +androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } +androidx-ui = { group = "androidx.compose.ui", name = "ui" } +androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } +androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } +androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } +androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } +androidx-material3 = { group = "androidx.compose.material3", name = "material3" } +androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } +androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCoreVersion" } +androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } [bundles] @@ -125,3 +145,4 @@ testTools = [ [plugins] versionsPluginGradle = { id = "com.github.ben-manes.versions", version.ref = "versionsPluginGradle" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlinComposePlugin" } diff --git a/instrumented/build.gradle.kts b/instrumented/build.gradle.kts new file mode 100644 index 0000000..9bca11b --- /dev/null +++ b/instrumented/build.gradle.kts @@ -0,0 +1,72 @@ +import com.datadog.gradle.config.AndroidConfig + +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") + alias(libs.plugins.compose.compiler) +} + +android { + namespace = "com.datadog.android.instrumented" + compileSdk = AndroidConfig.TARGET_SDK + + defaultConfig { + applicationId = "com.datadog.android.instrumented" + // Min SDK must be higher than 30 to make Android instrumented test support + // space characters in function names + minSdk = AndroidConfig.TARGET_SDK + targetSdk = AndroidConfig.TARGET_SDK + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } + buildFeatures { + compose = true + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + merges += "META-INF/LICENSE.md" + merges += "META-INF/LICENSE-notice.md" + } + } +} + +dependencies { + + kotlinCompilerPluginClasspath(project(":dd-sdk-android-gradle-plugin")) + implementation(libs.androidx.core) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.material3) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.bundles.jUnit5) + androidTestImplementation(libs.bundles.testTools) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} diff --git a/instrumented/src/androidTest/java/com/datadog/android/instrumented/SemanticsTest.kt b/instrumented/src/androidTest/java/com/datadog/android/instrumented/SemanticsTest.kt new file mode 100644 index 0000000..9744bb5 --- /dev/null +++ b/instrumented/src/androidTest/java/com/datadog/android/instrumented/SemanticsTest.kt @@ -0,0 +1,47 @@ +package com.datadog.android.instrumented + +import androidx.compose.ui.test.SemanticsMatcher +import androidx.compose.ui.test.junit4.createComposeRule +import fr.xgouchet.elmyr.junit5.ForgeExtension +import org.junit.Rule +import org.junit.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.junit.jupiter.api.extension.Extensions +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.junit.jupiter.MockitoSettings +import org.mockito.quality.Strictness + +@Extensions( + ExtendWith(MockitoExtension::class), + ExtendWith(ForgeExtension::class) +) +@MockitoSettings(strictness = Strictness.LENIENT) +class SemanticsTest { + + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun `M have no datadog semantics tag W compose kotlin compiler plugin is not registered`() { + composeTestRule.setContent { + TestScreen() + } + val semanticsMatcher = hasSemanticsValue(DD_SEMANTICS_KEY_NAME, DD_SEMANTICS_VALUE_DEFAULT) + composeTestRule.onNode(semanticsMatcher).assertDoesNotExist() + } + + private fun hasSemanticsValue( + keyName: String, + expectedValue: T + ): SemanticsMatcher { + return SemanticsMatcher("$keyName = $expectedValue") { node -> + val entry = node.config.firstOrNull { it.key.name == keyName } + entry != null && entry.value == expectedValue + } + } + + companion object { + private const val DD_SEMANTICS_KEY_NAME = "_dd_semantics" + private const val DD_SEMANTICS_VALUE_DEFAULT = "DD_DEFAULT_TAG" + } +} diff --git a/instrumented/src/main/AndroidManifest.xml b/instrumented/src/main/AndroidManifest.xml new file mode 100644 index 0000000..568741e --- /dev/null +++ b/instrumented/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/instrumented/src/main/java/com/datadog/android/instrumented/TestScreen.kt b/instrumented/src/main/java/com/datadog/android/instrumented/TestScreen.kt new file mode 100644 index 0000000..daf9f39 --- /dev/null +++ b/instrumented/src/main/java/com/datadog/android/instrumented/TestScreen.kt @@ -0,0 +1,12 @@ +package com.datadog.android.instrumented + +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable + +@Composable +internal fun TestScreen() { + Column { + Text("") + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index bc0528c..eaaeb13 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -11,3 +11,4 @@ include(":samples:ndk") include(":samples:variants") include(":samples:variants-kotlin") include(":samples:lib-module") +include(":instrumented")