From 9a6d41598d33e872c7766061b1edf0bf2180393b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 21 May 2024 14:59:51 +0000 Subject: [PATCH 01/80] Adds Dropshots and edge-to-edge tests Change-Id: I4e0d5d0c9dfbf106acea951266c04139fab93c53 # Conflicts: # build.gradle.kts --- .github/workflows/Build.yaml | 38 +++++- app/build.gradle.kts | 3 + .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 113 ++++++++++++++++++ .../AndroidApplicationConventionPlugin.kt | 1 + build.gradle.kts | 1 + gradle.properties | 2 +- gradle/libs.versions.toml | 8 +- 7 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 6bee0ddfb..878be4d11 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -189,7 +189,8 @@ jobs: - name: Setup Gradle uses: gradle/gradle-build-action@v3 - - name: Build projects and run instrumentation tests + - name: Build projects and run instrumentation tests including screenshots + id: dropshotsverify uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} @@ -197,8 +198,43 @@ jobs: disable-animations: true disk-size: 6000M heap-size: 600M + profile: pixel_5 + ram-size: 4096M + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none script: ./gradlew connectedDemoDebugAndroidTest --daemon + - name: Prevent pushing new screenshots if this is a fork (instrumented) + id: checkfork_screenshots_instrumented + continue-on-error: false + if: steps.dropshotsverify.outcome == 'failure' && github.event.pull_request.head.repo.full_name != github.repository + run: | + echo "::error::Instrumented screenshot tests failed, please create a PR in your fork first." && exit 1 + + + - name: Record new instrumented screenshots + id: screenshotsrecordinstrumented + if: steps.dropshotsverify.outcome == 'failure' && github.event_name == 'pull_request' + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ matrix.api-level }} + arch: x86_64 + disable-animations: true + disk-size: 6000M + heap-size: 600M + profile: pixel_5 + force-avd-creation: false + ram-size: 4096M + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + script: adb shell rm -rf /storage/emulated/0/Download/screenshots && ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --stacktrace + + - name: Push new screenshots if available + uses: stefanzweifel/git-auto-commit-action@4b8a201e31cadd9829df349894b28c54e6c19fe6 + if: steps.screenshotsrecordinstrumented.outcome == 'success' + with: + file_pattern: '*/*.png' + disable_globbing: true + commit_message: "🤖 Updates instrumented screenshots" + - name: Run local tests (including Roborazzi) for the combined coverage report (only API 30) if: matrix.api-level == 30 # There is no need to verify Roborazzi tests to generate coverage. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 355ec42c0..e9919a368 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -126,9 +126,12 @@ dependencies { androidTestImplementation(projects.core.dataTest) androidTestImplementation(projects.core.datastoreTest) androidTestImplementation(libs.androidx.test.espresso.core) + androidTestImplementation(libs.androidx.test.core) androidTestImplementation(libs.androidx.navigation.testing) androidTestImplementation(libs.androidx.compose.ui.test) androidTestImplementation(libs.hilt.android.testing) + androidTestImplementation(libs.androidx.test.espresso.device) + androidTestImplementation(libs.androidx.test.uiautomator) baselineProfile(projects.benchmarks) } diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt new file mode 100644 index 000000000..51f5bc1ec --- /dev/null +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -0,0 +1,113 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.samples.apps.nowinandroid.ui + +import androidx.test.core.app.takeScreenshot +import androidx.test.espresso.device.common.executeShellCommand +import androidx.test.espresso.device.filter.RequiresDisplay +import androidx.test.espresso.device.sizeclass.HeightSizeClass.Companion.HeightSizeClassEnum +import androidx.test.espresso.device.sizeclass.WidthSizeClass.Companion.WidthSizeClassEnum +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.filters.SdkSuppress +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.dropbox.dropshots.Dropshots +import com.google.samples.apps.nowinandroid.MainActivity +import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPermissionRule +import dagger.hilt.android.testing.BindValue +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 +import org.junit.rules.TemporaryFolder + +@HiltAndroidTest +class EdgeToEdgeTest { + /** + * Manages the components' state and is used to perform injection on your test + */ + @get:Rule(order = 0) + val hiltRule = HiltAndroidRule(this) + + /** + * Create a temporary folder used to create a Data Store file. This guarantees that + * the file is removed in between each test, preventing a crash. + */ + @BindValue + @get:Rule(order = 1) + val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build() + + /** + * Grant [android.Manifest.permission.POST_NOTIFICATIONS] permission. + */ + @get:Rule(order = 2) + val postNotificationsPermission = GrantPostNotificationsPermissionRule() + + @get:Rule(order = 3) + val activityScenarioRule = ActivityScenarioRule(MainActivity::class.java) + + @get:Rule(order = 4) + val dropshots = Dropshots() + + @Before + fun setup() = hiltRule.inject() + + @Before + fun enableDemoMode() { + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { + executeShellCommand("cmd overlay enable-exclusive com.android.internal.systemui.navbar.threebutton") + executeShellCommand("settings put global sysui_demo_allowed 1") + executeShellCommand("am broadcast -a com.android.systemui.demo -e command enter") + executeShellCommand("am broadcast -a com.android.systemui.demo -e command notifications -e visible false") + executeShellCommand("am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1234") + executeShellCommand("am broadcast -a com.android.systemui.demo -e command network -e wifi hide") + executeShellCommand("am broadcast -a com.android.systemui.demo -e command network -e mobile hide") + } + } + + @After + fun resetDemoMode() { + executeShellCommand("am broadcast -a com.android.systemui.demo -e command exit") + } + + @RequiresDisplay(WidthSizeClassEnum.COMPACT, HeightSizeClassEnum.MEDIUM) + @SdkSuppress(minSdkVersion = 26, maxSdkVersion = 26) + @Test + fun edgeToEdge_Phone_Api26() { + testEdgeToEdge("edgeToEdge_Phone_Api26") + } + + @RequiresDisplay(WidthSizeClassEnum.COMPACT, HeightSizeClassEnum.MEDIUM) + @SdkSuppress(minSdkVersion = 30, maxSdkVersion = 30) + @Test + fun edgeToEdge_Phone_Api30() { + testEdgeToEdge("edgeToEdge_Phone_Api30") + } + + @RequiresDisplay(WidthSizeClassEnum.EXPANDED, HeightSizeClassEnum.MEDIUM) + @SdkSuppress(minSdkVersion = 30, maxSdkVersion = 30) + @Test + fun edgeToEdge_Tablet_Api30() { + testEdgeToEdge("edgeToEdge_Tablet_Api30") + } + + private fun testEdgeToEdge(screenshotFileName: String) { + dropshots.assertSnapshot(takeScreenshot(), screenshotFileName) + } +} diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt index f4d5bb0d0..1b39887f8 100644 --- a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt @@ -34,6 +34,7 @@ class AndroidApplicationConventionPlugin : Plugin { apply("org.jetbrains.kotlin.android") apply("nowinandroid.android.lint") apply("com.dropbox.dependency-guard") + apply("com.dropbox.dropshots") } extensions.configure { diff --git a/build.gradle.kts b/build.gradle.kts index dffc0c0dd..e1b477eb6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,6 +40,7 @@ plugins { alias(libs.plugins.kotlin.jvm) apply false alias(libs.plugins.kotlin.serialization) apply false alias(libs.plugins.dependencyGuard) apply false + alias(libs.plugins.dropshots) apply false alias(libs.plugins.firebase.crashlytics) apply false alias(libs.plugins.firebase.perf) apply false alias(libs.plugins.gms) apply false diff --git a/gradle.properties b/gradle.properties index 97f940e2e..16906e249 100644 --- a/gradle.properties +++ b/gradle.properties @@ -37,7 +37,7 @@ kotlin.code.style=official # Disable build features that are enabled by default, # https://developer.android.com/build/releases/gradle-plugin#default-changes -android.defaults.buildfeatures.resvalues=false +#android.defaults.buildfeatures.resvalues=false android.defaults.buildfeatures.shaders=false # Run Roborazzi screenshot tests with the local tests diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e0b938e75..740baa0cc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,22 +17,24 @@ androidxCore = "1.12.0" androidxCoreSplashscreen = "1.0.1" androidxDataStore = "1.0.0" androidxEspresso = "3.5.1" +androidxEspressoDevice = "1.0.0-beta01" androidxHiltNavigationCompose = "1.2.0" androidxLifecycle = "2.7.0" androidxMacroBenchmark = "1.2.4" androidxMetrics = "1.0.0-alpha04" androidxNavigation = "2.8.0-alpha06" androidxProfileinstaller = "1.3.1" -androidxTestCore = "1.5.0" +androidxTestCore = "1.6.0-beta01" androidxTestExt = "1.1.5" androidxTestRules = "1.5.0" androidxTestRunner = "1.5.2" androidxTracing = "1.3.0-alpha02" -androidxUiAutomator = "2.2.0" +androidxUiAutomator = "2.3.0" androidxWindowManager = "1.3.0-alpha03" androidxWork = "2.9.0" coil = "2.6.0" dependencyGuard = "0.5.0" +dropshots = "0.4.1" firebaseBom = "32.4.0" firebaseCrashlyticsPlugin = "2.9.9" firebasePerfPlugin = "1.4.2" @@ -98,6 +100,7 @@ androidx-navigation-testing = { group = "androidx.navigation", name = "navigatio androidx-profileinstaller = { group = "androidx.profileinstaller", name = "profileinstaller", version.ref = "androidxProfileinstaller" } androidx-test-core = { group = "androidx.test", name = "core", version.ref = "androidxTestCore" } androidx-test-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidxEspresso" } +androidx-test-espresso-device = { group = "androidx.test.espresso", name = "espresso-device", version.ref = "androidxEspressoDevice" } androidx-test-ext = { group = "androidx.test.ext", name = "junit-ktx", version.ref = "androidxTestExt" } androidx-test-rules = { group = "androidx.test", name = "rules", version.ref = "androidxTestRules" } androidx-test-runner = { group = "androidx.test", name = "runner", version.ref = "androidxTestRunner" } @@ -160,6 +163,7 @@ android-test = { id = "com.android.test", version.ref = "androidGradlePlugin" } baselineprofile = { id = "androidx.baselineprofile", version.ref = "androidxMacroBenchmark"} compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } dependencyGuard = { id = "com.dropbox.dependency-guard", version.ref = "dependencyGuard" } +dropshots = { id = "com.dropbox.dropshots", version.ref = "dropshots" } firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebaseCrashlyticsPlugin" } firebase-perf = { id = "com.google.firebase.firebase-perf", version.ref = "firebasePerfPlugin" } gms = { id = "com.google.gms.google-services", version.ref = "gmsPlugin" } From 9b7317d00e33d135e425f7fa151b896a05e714ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 21 May 2024 17:00:54 +0000 Subject: [PATCH 02/80] CI and temporary (?) fix in 26 Change-Id: Ibf487f37d3a9274d34ff78b47a3909fd275648e5 --- .github/workflows/Build.yaml | 1 + .../google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt | 3 ++- app/src/debug/AndroidManifest.xml | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 app/src/debug/AndroidManifest.xml diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 878be4d11..64c63f40f 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -213,6 +213,7 @@ jobs: - name: Record new instrumented screenshots id: screenshotsrecordinstrumented + continue-on-error: true if: steps.dropshotsverify.outcome == 'failure' && github.event_name == 'pull_request' uses: reactivecircus/android-emulator-runner@v2 with: diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index 51f5bc1ec..ceae429d5 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -54,7 +54,8 @@ class EdgeToEdgeTest { val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build() /** - * Grant [android.Manifest.permission.POST_NOTIFICATIONS] permission. + * Grant [android.Manifest.permission.POST_NOTIFICATIONS] permission to prevent the + * permissions dialog from showing on top. */ @get:Rule(order = 2) val postNotificationsPermission = GrantPostNotificationsPermissionRule() diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..5920995fb --- /dev/null +++ b/app/src/debug/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + + + From 9d8a8e2399f53a48385727d90d95d7a4a61f54da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 21 May 2024 17:14:36 +0000 Subject: [PATCH 03/80] CI Change-Id: Ide1cbc35f3b69675e504b2d9b7f699e1b1086bb8 --- .github/workflows/Build.yaml | 4 ++-- app/src/debug/AndroidManifest.xml | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 64c63f40f..d24f35b76 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -191,6 +191,7 @@ jobs: - name: Build projects and run instrumentation tests including screenshots id: dropshotsverify + continue-on-error: true uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} @@ -213,7 +214,6 @@ jobs: - name: Record new instrumented screenshots id: screenshotsrecordinstrumented - continue-on-error: true if: steps.dropshotsverify.outcome == 'failure' && github.event_name == 'pull_request' uses: reactivecircus/android-emulator-runner@v2 with: @@ -228,7 +228,7 @@ jobs: emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none script: adb shell rm -rf /storage/emulated/0/Download/screenshots && ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --stacktrace - - name: Push new screenshots if available + - name: Push new device screenshots if available uses: stefanzweifel/git-auto-commit-action@4b8a201e31cadd9829df349894b28c54e6c19fe6 if: steps.screenshotsrecordinstrumented.outcome == 'success' with: diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index 5920995fb..bc214c778 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -1,4 +1,19 @@ + From cf9e35cfb201a417291c79e71d11942b63639450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Wed, 22 May 2024 08:41:10 +0000 Subject: [PATCH 04/80] CI Change-Id: Ic3e3dd719147c6c98bb16ff16dbb029a519194ea --- .github/workflows/Build.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index d24f35b76..c6cf1843c 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -200,7 +200,6 @@ jobs: disk-size: 6000M heap-size: 600M profile: pixel_5 - ram-size: 4096M emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none script: ./gradlew connectedDemoDebugAndroidTest --daemon @@ -224,7 +223,6 @@ jobs: heap-size: 600M profile: pixel_5 force-avd-creation: false - ram-size: 4096M emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none script: adb shell rm -rf /storage/emulated/0/Download/screenshots && ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --stacktrace From a5798a60a11d360d8674d50a8c64e042e95595d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Wed, 22 May 2024 09:20:28 +0000 Subject: [PATCH 05/80] CI: enable AVD snapshot Change-Id: Idf584b0c599eb61c01b08ec64918b8b69d70a46b --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index c6cf1843c..941bf3d3a 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -200,7 +200,7 @@ jobs: disk-size: 6000M heap-size: 600M profile: pixel_5 - emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none script: ./gradlew connectedDemoDebugAndroidTest --daemon - name: Prevent pushing new screenshots if this is a fork (instrumented) From bfa05cba5ce5c510294970ecba578c302125f21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 23 May 2024 08:25:43 +0000 Subject: [PATCH 06/80] Workaround for emulator bug Change-Id: Ica9ca60071427f852be9125d3565aa37be932dc9 --- .github/workflows/Build.yaml | 24 +++++++++++++++++++ .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 12 +++++----- .../apps/nowinandroid/GradleManagedDevices.kt | 6 ++--- gradle/libs.versions.toml | 2 +- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 941bf3d3a..299d58a92 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -203,6 +203,30 @@ jobs: emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none script: ./gradlew connectedDemoDebugAndroidTest --daemon + # Workaround for https://github.com/ReactiveCircus/android-emulator-runner/issues/391 + # From https://github.com/TWiStErRob/github-workflows/blob/main/.github/workflows/instrumentation.yml + - name: "Workaround for emulator bug." + id: script + env: + SCRIPT: | + # Workaround for https://github.com/ReactiveCircus/android-emulator-runner/issues/373 + pre_terminate_crashpad() { + # For some reason pgrep/pkill sees only crashpad_handle, not crashpad_handler, + # but it's definitely called ${ANDROID_HOME}/emulator/crashpad_handler. + + # Best-effort gracefully terminate all crashpad_handler processes. + pkill --exact --echo --signal SIGTERM crashpad_handle || return + sleep 10 + pkill --exact --echo --signal SIGKILL crashpad_handle || return + } + trap pre_terminate_crashpad EXIT + + ${{ inputs.script }} + run: | + script_file="${RUNNER_TEMP}/reactivecircus-android-emulator-runner-prepared-script.sh" + echo "${SCRIPT}" > "${script_file}" + echo "file=${script_file}" >> "${GITHUB_OUTPUT}" + - name: Prevent pushing new screenshots if this is a fork (instrumented) id: checkfork_screenshots_instrumented continue-on-error: false diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index ceae429d5..4308796ce 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -88,17 +88,17 @@ class EdgeToEdgeTest { } @RequiresDisplay(WidthSizeClassEnum.COMPACT, HeightSizeClassEnum.MEDIUM) - @SdkSuppress(minSdkVersion = 26, maxSdkVersion = 26) + @SdkSuppress(minSdkVersion = 27, maxSdkVersion = 27) @Test - fun edgeToEdge_Phone_Api26() { - testEdgeToEdge("edgeToEdge_Phone_Api26") + fun edgeToEdge_Phone_Api27() { + testEdgeToEdge("edgeToEdge_Phone_Api27") } @RequiresDisplay(WidthSizeClassEnum.COMPACT, HeightSizeClassEnum.MEDIUM) - @SdkSuppress(minSdkVersion = 30, maxSdkVersion = 30) + @SdkSuppress(minSdkVersion = 31, maxSdkVersion = 31) @Test - fun edgeToEdge_Phone_Api30() { - testEdgeToEdge("edgeToEdge_Phone_Api30") + fun edgeToEdge_Phone_Api31() { + testEdgeToEdge("edgeToEdge_Phone_Api31") } @RequiresDisplay(WidthSizeClassEnum.EXPANDED, HeightSizeClassEnum.MEDIUM) diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/GradleManagedDevices.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/GradleManagedDevices.kt index f67e9093d..f6a599cd2 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/GradleManagedDevices.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/GradleManagedDevices.kt @@ -27,12 +27,12 @@ import org.gradle.kotlin.dsl.invoke internal fun configureGradleManagedDevices( commonExtension: CommonExtension<*, *, *, *, *, *>, ) { - val pixel4 = DeviceConfig("Pixel 4", 30, "aosp-atd") + val pixel4 = DeviceConfig("Pixel 4", 27, "aosp") val pixel6 = DeviceConfig("Pixel 6", 31, "aosp") - val pixelC = DeviceConfig("Pixel C", 30, "aosp-atd") + val pixelC = DeviceConfig("Pixel C", 30, "aosp") val allDevices = listOf(pixel4, pixel6, pixelC) - val ciDevices = listOf(pixel4, pixelC) + val ciDevices = listOf(pixel4, pixel6, pixelC) commonExtension.testOptions { managedDevices { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 740baa0cc..0b44d9841 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ accompanist = "0.34.0" androidDesugarJdkLibs = "2.0.4" # AGP and tools should be updated together -androidGradlePlugin = "8.4.0" +androidGradlePlugin = "8.4.1" androidTools = "31.4.0" androidxActivity = "1.8.2" androidxAppCompat = "1.6.1" From 8a37013bd8b23ba90e98074bef7cbae3da813cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 23 May 2024 08:53:38 +0000 Subject: [PATCH 07/80] Changes api levels Change-Id: I6c24c5104f53b223a60fc38d024aff7b476bd1c8 --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 299d58a92..c1356d31f 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -153,7 +153,7 @@ jobs: timeout-minutes: 55 strategy: matrix: - api-level: [26, 30] + device: [27, 31] steps: - name: Delete unnecessary tools 🔧 From 08ed42ee2e17c173cfc771448d15f16ea9cd24c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 23 May 2024 08:58:05 +0000 Subject: [PATCH 08/80] Changes api levels Change-Id: Ia9cd92a76aafcc3bd33166680a24eb8b0053c526 --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index c1356d31f..717dfbb0f 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -153,7 +153,7 @@ jobs: timeout-minutes: 55 strategy: matrix: - device: [27, 31] + api-level: [27, 31] steps: - name: Delete unnecessary tools 🔧 From 3b398fb6b7daa63684b0f78d3a4be66f0b8d512e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 23 May 2024 10:25:06 +0000 Subject: [PATCH 09/80] Problems running emulators twice Change-Id: Ib4437cdd3fe34b8fadf57b545eb31c6fd1f82612 --- .github/workflows/Build.yaml | 61 +++++++++++------------------------- 1 file changed, 19 insertions(+), 42 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 717dfbb0f..0b938e21d 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -201,31 +201,8 @@ jobs: heap-size: 600M profile: pixel_5 emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - script: ./gradlew connectedDemoDebugAndroidTest --daemon - - # Workaround for https://github.com/ReactiveCircus/android-emulator-runner/issues/391 - # From https://github.com/TWiStErRob/github-workflows/blob/main/.github/workflows/instrumentation.yml - - name: "Workaround for emulator bug." - id: script - env: - SCRIPT: | - # Workaround for https://github.com/ReactiveCircus/android-emulator-runner/issues/373 - pre_terminate_crashpad() { - # For some reason pgrep/pkill sees only crashpad_handle, not crashpad_handler, - # but it's definitely called ${ANDROID_HOME}/emulator/crashpad_handler. - - # Best-effort gracefully terminate all crashpad_handler processes. - pkill --exact --echo --signal SIGTERM crashpad_handle || return - sleep 10 - pkill --exact --echo --signal SIGKILL crashpad_handle || return - } - trap pre_terminate_crashpad EXIT - - ${{ inputs.script }} - run: | - script_file="${RUNNER_TEMP}/reactivecircus-android-emulator-runner-prepared-script.sh" - echo "${SCRIPT}" > "${script_file}" - echo "file=${script_file}" >> "${GITHUB_OUTPUT}" + # Run tests, if they fail, record screenshots and exit with a failure + script: ./gradlew connectedDemoDebugAndroidTest --daemon || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --stacktrace - name: Prevent pushing new screenshots if this is a fork (instrumented) id: checkfork_screenshots_instrumented @@ -234,27 +211,27 @@ jobs: run: | echo "::error::Instrumented screenshot tests failed, please create a PR in your fork first." && exit 1 - - - name: Record new instrumented screenshots - id: screenshotsrecordinstrumented - if: steps.dropshotsverify.outcome == 'failure' && github.event_name == 'pull_request' - uses: reactivecircus/android-emulator-runner@v2 - with: - api-level: ${{ matrix.api-level }} - arch: x86_64 - disable-animations: true - disk-size: 6000M - heap-size: 600M - profile: pixel_5 - force-avd-creation: false - emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - script: adb shell rm -rf /storage/emulated/0/Download/screenshots && ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --stacktrace +# +# - name: Record new instrumented screenshots +# id: screenshotsrecordinstrumented +# if: steps.dropshotsverify.outcome == 'failure' && github.event_name == 'pull_request' +# uses: reactivecircus/android-emulator-runner@v2 +# with: +# api-level: ${{ matrix.api-level }} +# arch: x86_64 +# disable-animations: true +# disk-size: 6000M +# heap-size: 600M +# profile: pixel_5 +# force-avd-creation: false +# emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none +# script: adb shell rm -rf /storage/emulated/0/Download/screenshots && ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --stacktrace - name: Push new device screenshots if available uses: stefanzweifel/git-auto-commit-action@4b8a201e31cadd9829df349894b28c54e6c19fe6 - if: steps.screenshotsrecordinstrumented.outcome == 'success' + if: steps.dropshotsverify.outcome == 'failure' with: - file_pattern: '*/*.png' + file_pattern: 'app/src/androidTest/screenshots/*.png' disable_globbing: true commit_message: "🤖 Updates instrumented screenshots" From 79aaf62f4e94cf02fcadee147e6a77ca839e5e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 23 May 2024 10:55:43 +0000 Subject: [PATCH 10/80] trying random stuff at this point Change-Id: Iec9c47ffcc69b6bbf86a2fb01ffe70909884261f --- .github/workflows/Build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 0b938e21d..0d2b11afc 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -200,9 +200,9 @@ jobs: disk-size: 6000M heap-size: 600M profile: pixel_5 - emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure - script: ./gradlew connectedDemoDebugAndroidTest --daemon || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --stacktrace + script: ./gradlew connectedDemoDebugAndroidTest --daemon || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --daemon --stacktrace - name: Prevent pushing new screenshots if this is a fork (instrumented) id: checkfork_screenshots_instrumented From 751a276bf6fbe375954c64205ef1dc52236316a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 23 May 2024 13:38:53 +0000 Subject: [PATCH 11/80] Now exit with a failure if there are new screenshots Change-Id: I441577bf92bab3e5a3606b87da30b5d8c8674ab4 --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 0d2b11afc..8df65466f 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -202,7 +202,7 @@ jobs: profile: pixel_5 emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure - script: ./gradlew connectedDemoDebugAndroidTest --daemon || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --daemon --stacktrace + script: ./gradlew connectedDemoDebugAndroidTest --daemon || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --daemon --stacktrace ; exit $? - name: Prevent pushing new screenshots if this is a fork (instrumented) id: checkfork_screenshots_instrumented From 82f79d386a7560eece157454ceea37c30385bb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 23 May 2024 14:03:19 +0000 Subject: [PATCH 12/80] Trying harder to exit with a failure Change-Id: I88b9da75b741ae90909d997d7f49c50ee1945533 --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 8df65466f..ad579dc33 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -202,7 +202,7 @@ jobs: profile: pixel_5 emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure - script: ./gradlew connectedDemoDebugAndroidTest --daemon || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --daemon --stacktrace ; exit $? + script: ./gradlew connectedDemoDebugAndroidTest --daemon || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --daemon --stacktrace ; echo "Done recording new screenshots, exiting with failure" ; exit 5 - name: Prevent pushing new screenshots if this is a fork (instrumented) id: checkfork_screenshots_instrumented From 4508e8fa0efaaafaab41f43f26b5919f30700933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 23 May 2024 14:54:49 +0000 Subject: [PATCH 13/80] Pulls before pushing Change-Id: Ie376aa0cd2a4494de3b41a152cdacaf85ba9714a --- .github/workflows/Build.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index ad579dc33..a76a95c7b 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -227,13 +227,17 @@ jobs: # emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # script: adb shell rm -rf /storage/emulated/0/Download/screenshots && ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --stacktrace + - name: Pull Remote Changes (in case another job already uploaded screenshots) + if: steps.dropshotsverify.outcome == 'failure' + run: git pull + - name: Push new device screenshots if available uses: stefanzweifel/git-auto-commit-action@4b8a201e31cadd9829df349894b28c54e6c19fe6 if: steps.dropshotsverify.outcome == 'failure' with: file_pattern: 'app/src/androidTest/screenshots/*.png' disable_globbing: true - commit_message: "🤖 Updates instrumented screenshots" + commit_message: "🤖 Updates instrumented screenshots. API ${{ matrix.api-level }}" - name: Run local tests (including Roborazzi) for the combined coverage report (only API 30) if: matrix.api-level == 30 From 23077477c838292e2e82cdfb07645d4cd4180770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 23 May 2024 15:23:32 +0000 Subject: [PATCH 14/80] Not sure if this is going to do what I want to do Change-Id: Ic0e31e8faecbaefe085b1e87aec1b4447e9333fc --- .github/workflows/Build.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index a76a95c7b..97274dc7e 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -227,9 +227,10 @@ jobs: # emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # script: adb shell rm -rf /storage/emulated/0/Download/screenshots && ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --stacktrace - - name: Pull Remote Changes (in case another job already uploaded screenshots) - if: steps.dropshotsverify.outcome == 'failure' - run: git pull + - name: Checkout new changes (in case another job already uploaded screenshots) + uses: actions/checkout@v4 + with: + clean: false - name: Push new device screenshots if available uses: stefanzweifel/git-auto-commit-action@4b8a201e31cadd9829df349894b28c54e6c19fe6 From b2d0e0db8808437ffd3872337ec744083f727124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Fri, 24 May 2024 13:10:49 +0000 Subject: [PATCH 15/80] Adds foldable tests and CI changes Change-Id: Ie0a37f53046a3219f6ea9ae4deccacb48e531fe9 --- .github/workflows/Build.yaml | 135 ++++++++++++------ app/build.gradle.kts | 4 + .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 122 +++++++++++++--- .../ui/InstrumentedScreenshotTests.kt | 22 +++ app/src/debug/AndroidManifest.xml | 4 +- gradle.properties | 3 + gradle/libs.versions.toml | 2 +- 7 files changed, 230 insertions(+), 62 deletions(-) create mode 100644 app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/InstrumentedScreenshotTests.kt diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 97274dc7e..6abd444cd 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -153,7 +153,7 @@ jobs: timeout-minutes: 55 strategy: matrix: - api-level: [27, 31] + api-level: [26, 30] steps: - name: Delete unnecessary tools 🔧 @@ -189,9 +189,7 @@ jobs: - name: Setup Gradle uses: gradle/gradle-build-action@v3 - - name: Build projects and run instrumentation tests including screenshots - id: dropshotsverify - continue-on-error: true + - name: Build projects and run instrumentation tests uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} @@ -199,46 +197,7 @@ jobs: disable-animations: true disk-size: 6000M heap-size: 600M - profile: pixel_5 - emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - # Run tests, if they fail, record screenshots and exit with a failure - script: ./gradlew connectedDemoDebugAndroidTest --daemon || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --daemon --stacktrace ; echo "Done recording new screenshots, exiting with failure" ; exit 5 - - - name: Prevent pushing new screenshots if this is a fork (instrumented) - id: checkfork_screenshots_instrumented - continue-on-error: false - if: steps.dropshotsverify.outcome == 'failure' && github.event.pull_request.head.repo.full_name != github.repository - run: | - echo "::error::Instrumented screenshot tests failed, please create a PR in your fork first." && exit 1 - -# -# - name: Record new instrumented screenshots -# id: screenshotsrecordinstrumented -# if: steps.dropshotsverify.outcome == 'failure' && github.event_name == 'pull_request' -# uses: reactivecircus/android-emulator-runner@v2 -# with: -# api-level: ${{ matrix.api-level }} -# arch: x86_64 -# disable-animations: true -# disk-size: 6000M -# heap-size: 600M -# profile: pixel_5 -# force-avd-creation: false -# emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -# script: adb shell rm -rf /storage/emulated/0/Download/screenshots && ./gradlew connectedDemoDebugAndroidTest -Pdropshots.record --stacktrace - - - name: Checkout new changes (in case another job already uploaded screenshots) - uses: actions/checkout@v4 - with: - clean: false - - - name: Push new device screenshots if available - uses: stefanzweifel/git-auto-commit-action@4b8a201e31cadd9829df349894b28c54e6c19fe6 - if: steps.dropshotsverify.outcome == 'failure' - with: - file_pattern: 'app/src/androidTest/screenshots/*.png' - disable_globbing: true - commit_message: "🤖 Updates instrumented screenshots. API ${{ matrix.api-level }}" + script: ./gradlew connectedDemoDebugAndroidTest --daemon - name: Run local tests (including Roborazzi) for the combined coverage report (only API 30) if: matrix.api-level == 30 @@ -278,3 +237,91 @@ jobs: compression-level: 1 overwrite: false path: '**/build/reports/jacoco/' + + + androidTestScreenshots: + runs-on: ubuntu-latest + timeout-minutes: 55 + strategy: + matrix: + include: + - api-level: 27 + profile: pixel_5 + - api-level: 33 + profile: pixel_fold + - api-level: "VanillaIceCream" + profile: pixel_fold + + steps: + - name: Delete unnecessary tools 🔧 + uses: jlumbroso/free-disk-space@v1.3.1 + with: + android: false # Don't remove Android tools + tool-cache: true # Remove image tool cache - rm -rf "$AGENT_TOOLSDIRECTORY" + dotnet: true # rm -rf /usr/share/dotnet + haskell: true # rm -rf /opt/ghc... + swap-storage: true # rm -f /mnt/swapfile (4GiB) + docker-images: false # Takes 16s, enable if needed in the future + large-packages: false # includes google-cloud-sdk and it's slow + + - name: Enable KVM group perms + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + ls /dev/kvm + + - name: Checkout + uses: actions/checkout@v4 + + - name: Copy CI gradle.properties + run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 17 + + - name: Setup Gradle + uses: gradle/gradle-build-action@v3 + + - name: Build projects and run instrumentation tests including screenshots + id: dropshotsverify + continue-on-error: true + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ matrix.api-level }} + arch: x86_64 + disable-animations: true + disk-size: 6000M + heap-size: 600M + profile: pixel_5 + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + # Run tests, if they fail, record screenshots and exit with a failure + script: | + ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon + || echo "Recording new screenshots" + ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace + ; echo "Done recording new screenshots, exiting with failure" + ; exit 5 + + - name: Prevent pushing new screenshots if this is a fork (instrumented) + id: checkfork_screenshots_instrumented + continue-on-error: false + if: steps.dropshotsverify.outcome == 'failure' && github.event.pull_request.head.repo.full_name != github.repository + run: | + echo "::error::Instrumented screenshot tests failed, please create a PR in your fork first." && exit 1 + + - name: Checkout new changes (in case another job already uploaded screenshots) + uses: actions/checkout@v4 + with: + clean: false + + - name: Push new device screenshots if available + uses: stefanzweifel/git-auto-commit-action@4b8a201e31cadd9829df349894b28c54e6c19fe6 + if: steps.dropshotsverify.outcome == 'failure' + with: + file_pattern: 'app/src/androidTest/screenshots/*.png' + disable_globbing: true + commit_message: "🤖 Updates instrumented screenshots. API ${{ matrix.api-level }}" diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e9919a368..75e1432c5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -67,6 +67,10 @@ android { unitTests { isIncludeAndroidResources = true } + // Espresso Device + emulatorControl { + enable = true + } } namespace = "com.google.samples.apps.nowinandroid" } diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index 4308796ce..8caa4e9a3 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -16,8 +16,16 @@ package com.google.samples.apps.nowinandroid.ui +import android.graphics.Bitmap +import android.view.WindowInsets import androidx.test.core.app.takeScreenshot +import androidx.test.espresso.device.DeviceInteraction.Companion.setClosedMode +import androidx.test.espresso.device.DeviceInteraction.Companion.setFlatMode +import androidx.test.espresso.device.EspressoDevice.Companion.onDevice import androidx.test.espresso.device.common.executeShellCommand +import androidx.test.espresso.device.controller.DeviceMode.CLOSED +import androidx.test.espresso.device.controller.DeviceMode.FLAT +import androidx.test.espresso.device.filter.RequiresDeviceMode import androidx.test.espresso.device.filter.RequiresDisplay import androidx.test.espresso.device.sizeclass.HeightSizeClass.Companion.HeightSizeClassEnum import androidx.test.espresso.device.sizeclass.WidthSizeClass.Companion.WidthSizeClassEnum @@ -31,13 +39,20 @@ import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPer import dagger.hilt.android.testing.BindValue import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest -import org.junit.After +import org.junit.AfterClass import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder +/** + * These tests must be run on the following devices: + * - A phone on API 27 (pixel_5) + * - A foldable on API 33 (pixel_fold) + * - A foldable on API 35 (pixel_fold) + */ @HiltAndroidTest +@InstrumentedScreenshotTests class EdgeToEdgeTest { /** * Manages the components' state and is used to perform injection on your test @@ -72,7 +87,6 @@ class EdgeToEdgeTest { @Before fun enableDemoMode() { UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { - executeShellCommand("cmd overlay enable-exclusive com.android.internal.systemui.navbar.threebutton") executeShellCommand("settings put global sysui_demo_allowed 1") executeShellCommand("am broadcast -a com.android.systemui.demo -e command enter") executeShellCommand("am broadcast -a com.android.systemui.demo -e command notifications -e visible false") @@ -82,33 +96,109 @@ class EdgeToEdgeTest { } } - @After - fun resetDemoMode() { - executeShellCommand("am broadcast -a com.android.systemui.demo -e command exit") + companion object { + @JvmStatic + @AfterClass + fun resetDemoMode(): Unit { + executeShellCommand("am broadcast -a com.android.systemui.demo -e command exit") + } } @RequiresDisplay(WidthSizeClassEnum.COMPACT, HeightSizeClassEnum.MEDIUM) @SdkSuppress(minSdkVersion = 27, maxSdkVersion = 27) @Test fun edgeToEdge_Phone_Api27() { - testEdgeToEdge("edgeToEdge_Phone_Api27") + screenshotSystemBar("edgeToEdge_Phone_systemBar_Api27") + screenshotNavigationBar("edgeToEdge_Phone_navBar_Api27") } - @RequiresDisplay(WidthSizeClassEnum.COMPACT, HeightSizeClassEnum.MEDIUM) - @SdkSuppress(minSdkVersion = 31, maxSdkVersion = 31) + @RequiresDeviceMode(mode = FLAT) + @RequiresDeviceMode(mode = CLOSED) + @SdkSuppress(minSdkVersion = 33, maxSdkVersion = 33) @Test - fun edgeToEdge_Phone_Api31() { - testEdgeToEdge("edgeToEdge_Phone_Api31") + fun edgeToEdge_Foldable_api33() { + runFoldableTests(apiName = "api33") } - @RequiresDisplay(WidthSizeClassEnum.EXPANDED, HeightSizeClassEnum.MEDIUM) - @SdkSuppress(minSdkVersion = 30, maxSdkVersion = 30) + @RequiresDeviceMode(mode = FLAT) + @RequiresDeviceMode(mode = CLOSED) + @SdkSuppress(minSdkVersion = 35, codeName = "VanillaIceCream") @Test - fun edgeToEdge_Tablet_Api30() { - testEdgeToEdge("edgeToEdge_Tablet_Api30") + fun edgeToEdge_Foldable_api35() { + runFoldableTests(apiName = "api35") + } + + private fun runFoldableTests(apiName: String) { + onDevice().setClosedMode() + screenshotSystemBar("edgeToEdge_Foldable_closed_system_${apiName}") + forceThreeButtonNavigation() + screenshotNavigationBar("edgeToEdge_Foldable_closed_nav3button_${apiName}") + forceGestureNavigation() + screenshotNavigationBar("edgeToEdge_Foldable_closed_navGesture_${apiName}") + + onDevice().setFlatMode() + enableDemoMode() // Flat mode resets demo mode! + screenshotSystemBar("edgeToEdge_Foldable_flat_system_${apiName}") + forceThreeButtonNavigation() + screenshotNavigationBar("edgeToEdge_Foldable_flat_nav3button_${apiName}") + forceGestureNavigation() + screenshotNavigationBar("edgeToEdge_Foldable_flat_navGesture_${apiName}") + } + + private fun screenshotSystemBar(screenshotFileName: String) { + var topInset: Int? = null + var width: Int? = null + waitForWindowUpdate() + activityScenarioRule.scenario.onActivity { activity -> + topInset = activity.windowManager.maximumWindowMetrics.windowInsets.getInsets( + WindowInsets.Type.systemBars()).top + width = activity.windowManager.maximumWindowMetrics.bounds.width() + } + // Crop the top, adding extra pixels to check continuity + val bitmap = takeScreenshot().let { + Bitmap.createBitmap(it, 0, 0, width!!, (topInset!! * 2)) + } + dropshots.assertSnapshot(bitmap, screenshotFileName) + } + + private fun screenshotNavigationBar(screenshotFileName: String) { + var bottomInset: Int? = null + var width: Int? = null + var height: Int? = null + waitForWindowUpdate() + activityScenarioRule.scenario.onActivity { activity -> + bottomInset = activity.windowManager.maximumWindowMetrics.windowInsets.getInsets( + WindowInsets.Type.navigationBars()).bottom + width = activity.windowManager.maximumWindowMetrics.bounds.width() + height = activity.windowManager.maximumWindowMetrics.bounds.height() + } + // Crop the top, adding extra pixels to check continuity + val bitmap = takeScreenshot().let { + Bitmap.createBitmap(it, 0, height!! - (bottomInset!! * 2), width!!, (bottomInset!! * 2)) + } + dropshots.assertSnapshot(bitmap, screenshotFileName) + } + + private fun forceThreeButtonNavigation() { + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { + executeShellCommand("cmd overlay enable-exclusive " + + "com.android.internal.systemui.navbar.threebutton") + } + } + + private fun forceGestureNavigation() { + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { + executeShellCommand("cmd overlay enable-exclusive " + + "com.android.internal.systemui.navbar.gestural") + } } - private fun testEdgeToEdge(screenshotFileName: String) { - dropshots.assertSnapshot(takeScreenshot(), screenshotFileName) + private fun waitForWindowUpdate() { + // TODO: This works but it's unclear if it's making it wait too long. Investigate. + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + .waitForWindowUpdate( + InstrumentationRegistry.getInstrumentation().targetContext.packageName, + 4000 + ); } } diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/InstrumentedScreenshotTests.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/InstrumentedScreenshotTests.kt new file mode 100644 index 000000000..c279130cb --- /dev/null +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/InstrumentedScreenshotTests.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.samples.apps.nowinandroid.ui + +/** + * TODO: Move to a test module. + */ +annotation class InstrumentedScreenshotTests diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index bc214c778..36313049e 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -19,5 +19,7 @@ - + + + diff --git a/gradle.properties b/gradle.properties index 16906e249..8e2896cd5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -42,3 +42,6 @@ android.defaults.buildfeatures.shaders=false # Run Roborazzi screenshot tests with the local tests roborazzi.test.verify=true + +# Espresso Device +android.experimental.androidTest.enableEmulatorControl=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0b44d9841..943fb52dd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -34,7 +34,7 @@ androidxWindowManager = "1.3.0-alpha03" androidxWork = "2.9.0" coil = "2.6.0" dependencyGuard = "0.5.0" -dropshots = "0.4.1" +dropshots = "0.4.2" firebaseBom = "32.4.0" firebaseCrashlyticsPlugin = "2.9.9" firebasePerfPlugin = "1.4.2" From 62b26ed5e1ccc144f38384af81bfda414806f7af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Fri, 24 May 2024 13:34:25 +0000 Subject: [PATCH 16/80] Spotless and disables V Change-Id: Iaf1b7968a5a1b3c169afe7ea54800b4fb23c78ec --- .github/workflows/Build.yaml | 11 +++--- .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 36 +++++++++++-------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 6abd444cd..3f3524112 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -249,8 +249,11 @@ jobs: profile: pixel_5 - api-level: 33 profile: pixel_fold - - api-level: "VanillaIceCream" - profile: pixel_fold + # Enable when a new version of the runner is released. Currently v2.30.1 + # https://github.com/ReactiveCircus/android-emulator-runner/releases/tag/v2.30.1 + # Also, change from VanillaIceCream to 35 when that image is available +# - api-level: VanillaIceCream +# profile: pixel_fold steps: - name: Delete unnecessary tools 🔧 @@ -286,7 +289,7 @@ jobs: - name: Setup Gradle uses: gradle/gradle-build-action@v3 - - name: Build projects and run instrumentation tests including screenshots + - name: Build projects and run instrumented screenshot tests id: dropshotsverify continue-on-error: true uses: reactivecircus/android-emulator-runner@v2 @@ -306,7 +309,7 @@ jobs: ; echo "Done recording new screenshots, exiting with failure" ; exit 5 - - name: Prevent pushing new screenshots if this is a fork (instrumented) + - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented continue-on-error: false if: steps.dropshotsverify.outcome == 'failure' && github.event.pull_request.head.repo.full_name != github.repository diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index 8caa4e9a3..d302c48cb 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -99,7 +99,7 @@ class EdgeToEdgeTest { companion object { @JvmStatic @AfterClass - fun resetDemoMode(): Unit { + fun resetDemoMode() { executeShellCommand("am broadcast -a com.android.systemui.demo -e command exit") } } @@ -130,19 +130,19 @@ class EdgeToEdgeTest { private fun runFoldableTests(apiName: String) { onDevice().setClosedMode() - screenshotSystemBar("edgeToEdge_Foldable_closed_system_${apiName}") + screenshotSystemBar("edgeToEdge_Foldable_closed_system_$apiName") forceThreeButtonNavigation() - screenshotNavigationBar("edgeToEdge_Foldable_closed_nav3button_${apiName}") + screenshotNavigationBar("edgeToEdge_Foldable_closed_nav3button_$apiName") forceGestureNavigation() - screenshotNavigationBar("edgeToEdge_Foldable_closed_navGesture_${apiName}") + screenshotNavigationBar("edgeToEdge_Foldable_closed_navGesture_$apiName") onDevice().setFlatMode() enableDemoMode() // Flat mode resets demo mode! - screenshotSystemBar("edgeToEdge_Foldable_flat_system_${apiName}") + screenshotSystemBar("edgeToEdge_Foldable_flat_system_$apiName") forceThreeButtonNavigation() - screenshotNavigationBar("edgeToEdge_Foldable_flat_nav3button_${apiName}") + screenshotNavigationBar("edgeToEdge_Foldable_flat_nav3button_$apiName") forceGestureNavigation() - screenshotNavigationBar("edgeToEdge_Foldable_flat_navGesture_${apiName}") + screenshotNavigationBar("edgeToEdge_Foldable_flat_navGesture_$apiName") } private fun screenshotSystemBar(screenshotFileName: String) { @@ -151,7 +151,8 @@ class EdgeToEdgeTest { waitForWindowUpdate() activityScenarioRule.scenario.onActivity { activity -> topInset = activity.windowManager.maximumWindowMetrics.windowInsets.getInsets( - WindowInsets.Type.systemBars()).top + WindowInsets.Type.systemBars(), + ).top width = activity.windowManager.maximumWindowMetrics.bounds.width() } // Crop the top, adding extra pixels to check continuity @@ -168,7 +169,8 @@ class EdgeToEdgeTest { waitForWindowUpdate() activityScenarioRule.scenario.onActivity { activity -> bottomInset = activity.windowManager.maximumWindowMetrics.windowInsets.getInsets( - WindowInsets.Type.navigationBars()).bottom + WindowInsets.Type.navigationBars(), + ).bottom width = activity.windowManager.maximumWindowMetrics.bounds.width() height = activity.windowManager.maximumWindowMetrics.bounds.height() } @@ -181,15 +183,19 @@ class EdgeToEdgeTest { private fun forceThreeButtonNavigation() { UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { - executeShellCommand("cmd overlay enable-exclusive " + - "com.android.internal.systemui.navbar.threebutton") + executeShellCommand( + "cmd overlay enable-exclusive " + + "com.android.internal.systemui.navbar.threebutton", + ) } } private fun forceGestureNavigation() { UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { - executeShellCommand("cmd overlay enable-exclusive " + - "com.android.internal.systemui.navbar.gestural") + executeShellCommand( + "cmd overlay enable-exclusive " + + "com.android.internal.systemui.navbar.gestural", + ) } } @@ -198,7 +204,7 @@ class EdgeToEdgeTest { UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) .waitForWindowUpdate( InstrumentationRegistry.getInstrumentation().targetContext.packageName, - 4000 - ); + 4000, + ) } } From 9531cfb561f06218c431f0d8b678c1f8b5974c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Fri, 24 May 2024 13:48:42 +0000 Subject: [PATCH 17/80] CI fixes Change-Id: I59026e019dd204fb1c11c279394b090d43fadd44 --- .github/workflows/Build.yaml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 3f3524112..7902c7f24 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -299,14 +299,14 @@ jobs: disable-animations: true disk-size: 6000M heap-size: 600M - profile: pixel_5 + profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure script: | - ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon - || echo "Recording new screenshots" - ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace - ; echo "Done recording new screenshots, exiting with failure" + ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon \ + || echo "Recording new screenshots" \ + ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace \ + ; echo "Done recording new screenshots, exiting with failure" \ ; exit 5 - name: Prevent pushing new screenshots if this is a fork @@ -328,3 +328,10 @@ jobs: file_pattern: 'app/src/androidTest/screenshots/*.png' disable_globbing: true commit_message: "🤖 Updates instrumented screenshots. API ${{ matrix.api-level }}" + + - name: Upload test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-reports-${{ matrix.profile }}-${{ matrix.api-level }} + path: '**/build/reports/androidTests' From d9b0489b6dd52d25eb94a1c3e40ac574375a6dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Fri, 24 May 2024 14:01:27 +0000 Subject: [PATCH 18/80] Force newest cmdline tools version on CI Change-Id: Ie915b3bf3d93804ab18915653b5d2b05745c6213 --- .github/workflows/Build.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 7902c7f24..ca6efa9df 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -289,6 +289,12 @@ jobs: - name: Setup Gradle uses: gradle/gradle-build-action@v3 + # TODO this workflow needs cmdline-tools 13.0 (for pixel_fold). Remove when not necessary. + - name: Setup Android SDK + uses: android-actions/setup-android@v3 + with: + cmdline-tools-version: 11076708 + - name: Build projects and run instrumented screenshot tests id: dropshotsverify continue-on-error: true From 84446764c92363ff5d4848ffaddad438d6bd41bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Fri, 24 May 2024 14:10:20 +0000 Subject: [PATCH 19/80] Trying > for multiple lines Change-Id: I89be8171ec81617cf7e5268d65a630c01c538c7b --- .github/workflows/Build.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index ca6efa9df..4002be03d 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -308,11 +308,11 @@ jobs: profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure - script: | - ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon \ - || echo "Recording new screenshots" \ - ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace \ - ; echo "Done recording new screenshots, exiting with failure" \ + script: > + ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon + || echo "Recording new screenshots" + ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace + ; echo "Done recording new screenshots, exiting with failure" ; exit 5 - name: Prevent pushing new screenshots if this is a fork From 194ed558871d7199e966f17c7d410b1209b710c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Fri, 24 May 2024 14:46:31 +0000 Subject: [PATCH 20/80] Adding build tools 35 RC before running emulator Change-Id: I23968bf2afa291d723e883b87797eefcc77d0b98 --- .github/workflows/Build.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 4002be03d..5192c44cf 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -295,6 +295,10 @@ jobs: with: cmdline-tools-version: 11076708 + - name: Download build-tools;35.0.0-rc4 + run: | + $ANDROID_HOME/tools/bin/sdkmanager --install "build-tools;35.0.0-rc4" + - name: Build projects and run instrumented screenshot tests id: dropshotsverify continue-on-error: true From ee98f10dc5b7e1d04f86059ed48996d7d256853f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Fri, 24 May 2024 14:49:09 +0000 Subject: [PATCH 21/80] Using old path Change-Id: If87533949c182ec65f4b39761c5b27d19f959aff --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 5192c44cf..f8a39b35f 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -297,7 +297,7 @@ jobs: - name: Download build-tools;35.0.0-rc4 run: | - $ANDROID_HOME/tools/bin/sdkmanager --install "build-tools;35.0.0-rc4" + $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --install "build-tools;35.0.0-rc4" - name: Build projects and run instrumented screenshot tests id: dropshotsverify From 2b19bd87bc7cf8955833e8c3148c2733d4963a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Fri, 24 May 2024 15:08:56 +0000 Subject: [PATCH 22/80] Adds emulator build to hopefully access pixel_fold Change-Id: I5a01983fb946158e193281b2737f66196943f843 --- .github/workflows/Build.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index f8a39b35f..0a01e4917 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -298,6 +298,10 @@ jobs: - name: Download build-tools;35.0.0-rc4 run: | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --install "build-tools;35.0.0-rc4" + $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --list_installed + + - name: Print debug + run: $ANDROID_HOME/cmdline-tools/latest/bin/avdmanager list - name: Build projects and run instrumented screenshot tests id: dropshotsverify @@ -308,6 +312,7 @@ jobs: arch: x86_64 disable-animations: true disk-size: 6000M + emulator-build: 11834374 # 34.2.14 heap-size: 600M profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From 9e9e7b4a02787764603560e5759d97c6fc469a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Fri, 24 May 2024 15:15:49 +0000 Subject: [PATCH 23/80] Trying canary channel with low hopes Change-Id: I9ba5599f15abdb1a07e8f9ff76dd0506fb56681d --- .github/workflows/Build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 0a01e4917..de0e6c439 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -313,6 +313,7 @@ jobs: disable-animations: true disk-size: 6000M emulator-build: 11834374 # 34.2.14 + channel: canary heap-size: 600M profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From 18ac89d73fe8fa61bb9999461d2bfc6dcb80308e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Sat, 25 May 2024 09:12:09 +0000 Subject: [PATCH 24/80] Trying without full path Change-Id: I5c8941333eef06d8ac93f4b8a13575b2127ddf2c --- .github/workflows/Build.yaml | 6 ++-- .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 31 ++++++++++++++----- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index de0e6c439..e7e0e047e 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -297,11 +297,11 @@ jobs: - name: Download build-tools;35.0.0-rc4 run: | - $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --install "build-tools;35.0.0-rc4" - $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --list_installed + sdkmanager --install "build-tools;35.0.0-rc4" + sdkmanager --list_installed - name: Print debug - run: $ANDROID_HOME/cmdline-tools/latest/bin/avdmanager list + run: avdmanager list - name: Build projects and run instrumented screenshot tests id: dropshotsverify diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index d302c48cb..1447dd716 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -17,7 +17,9 @@ package com.google.samples.apps.nowinandroid.ui import android.graphics.Bitmap +import android.util.Log import android.view.WindowInsets +import androidx.core.view.WindowInsetsCompat import androidx.test.core.app.takeScreenshot import androidx.test.espresso.device.DeviceInteraction.Companion.setClosedMode import androidx.test.espresso.device.DeviceInteraction.Companion.setFlatMode @@ -33,6 +35,8 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice +import androidx.window.core.ExperimentalWindowApi +import androidx.window.layout.WindowMetricsCalculator import com.dropbox.dropshots.Dropshots import com.google.samples.apps.nowinandroid.MainActivity import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPermissionRule @@ -51,6 +55,7 @@ import org.junit.rules.TemporaryFolder * - A foldable on API 33 (pixel_fold) * - A foldable on API 35 (pixel_fold) */ +@OptIn(ExperimentalWindowApi::class) @HiltAndroidTest @InstrumentedScreenshotTests class EdgeToEdgeTest { @@ -150,11 +155,15 @@ class EdgeToEdgeTest { var width: Int? = null waitForWindowUpdate() activityScenarioRule.scenario.onActivity { activity -> - topInset = activity.windowManager.maximumWindowMetrics.windowInsets.getInsets( - WindowInsets.Type.systemBars(), - ).top - width = activity.windowManager.maximumWindowMetrics.bounds.width() + val metrics = WindowMetricsCalculator.getOrCreate() + .computeCurrentWindowMetrics(activity) + topInset = metrics.getWindowInsets().getInsets( + WindowInsetsCompat.Type.systemBars(), + ).bottom + width = metrics.bounds.width() } + Log.d("jalc", "width: $width" ) + Log.d("jalc", "topInset: $topInset" ) // Crop the top, adding extra pixels to check continuity val bitmap = takeScreenshot().let { Bitmap.createBitmap(it, 0, 0, width!!, (topInset!! * 2)) @@ -168,12 +177,17 @@ class EdgeToEdgeTest { var height: Int? = null waitForWindowUpdate() activityScenarioRule.scenario.onActivity { activity -> - bottomInset = activity.windowManager.maximumWindowMetrics.windowInsets.getInsets( - WindowInsets.Type.navigationBars(), + val metrics = WindowMetricsCalculator.getOrCreate() + .computeCurrentWindowMetrics(activity) + bottomInset = metrics.getWindowInsets().getInsets( + WindowInsetsCompat.Type.navigationBars(), ).bottom - width = activity.windowManager.maximumWindowMetrics.bounds.width() - height = activity.windowManager.maximumWindowMetrics.bounds.height() + + width = metrics.bounds.width() + height = metrics.bounds.height() } + Log.d("jalc", "height: $height" ) + Log.d("jalc", "bottomInset: $bottomInset" ) // Crop the top, adding extra pixels to check continuity val bitmap = takeScreenshot().let { Bitmap.createBitmap(it, 0, height!! - (bottomInset!! * 2), width!!, (bottomInset!! * 2)) @@ -197,6 +211,7 @@ class EdgeToEdgeTest { "com.android.internal.systemui.navbar.gestural", ) } + waitForWindowUpdate() } private fun waitForWindowUpdate() { From c5e7809c1960da90183e0ef62cfdf5a163617c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Sat, 25 May 2024 09:16:30 +0000 Subject: [PATCH 25/80] CI Change-Id: Iceae042be0d19efb8f9bbd2f6993ae791b0eff48 --- .github/workflows/Build.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index e7e0e047e..f0e4e6829 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -303,6 +303,11 @@ jobs: - name: Print debug run: avdmanager list + - name: Print debug + run: | + sdkmanager --version + which sdkmanager + - name: Build projects and run instrumented screenshot tests id: dropshotsverify continue-on-error: true From 369671b0cb6d538c351a33de977bd2a5965c7553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Sat, 25 May 2024 09:37:11 +0000 Subject: [PATCH 26/80] Bump to cmdline tools 11479570 Change-Id: I9b35b64228d969c15329e8b25b502660d4fd50b4 --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index f0e4e6829..9c8ee1db0 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -293,7 +293,7 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@v3 with: - cmdline-tools-version: 11076708 + cmdline-tools-version: 11479570 - name: Download build-tools;35.0.0-rc4 run: | From 1c499e53add44b932b29191447f50f8bd818c9e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Sat, 25 May 2024 09:50:45 +0000 Subject: [PATCH 27/80] Replacing cmdline-tools/latest Change-Id: I1d4039c9dc4e840fd75f4bf2214f07688bdd6f48 --- .github/workflows/Build.yaml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 9c8ee1db0..9548a0f80 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -295,10 +295,9 @@ jobs: with: cmdline-tools-version: 11479570 - - name: Download build-tools;35.0.0-rc4 + - name: Replace cmdlinetools run: | - sdkmanager --install "build-tools;35.0.0-rc4" - sdkmanager --list_installed + mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest - name: Print debug run: avdmanager list @@ -330,6 +329,14 @@ jobs: ; echo "Done recording new screenshots, exiting with failure" ; exit 5 + - name: Print debug avdmanager list + run: avdmanager list + + - name: Print debug sdkmanager + run: | + sdkmanager --version + which sdkmanager + - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented continue-on-error: false From cb117c2c034f347ebaa17ccdf71c06b23f74c4f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Sat, 25 May 2024 09:56:55 +0000 Subject: [PATCH 28/80] Let android-emulator-runner install rest of the tools Change-Id: I7069f1743f68be24810bded72530666ee4bc2b55 --- .github/workflows/Build.yaml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 9548a0f80..862d93b98 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -299,14 +299,6 @@ jobs: run: | mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest - - name: Print debug - run: avdmanager list - - - name: Print debug - run: | - sdkmanager --version - which sdkmanager - - name: Build projects and run instrumented screenshot tests id: dropshotsverify continue-on-error: true From 917cfd2be2f2e70ef6564f2503acc3986bf2e9df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 08:34:38 +0000 Subject: [PATCH 29/80] More debug prints Change-Id: Ie863c3813d8f621b658d26d7050d4c29aa2b5151 --- .github/workflows/Build.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 862d93b98..ddac50bce 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -299,6 +299,11 @@ jobs: run: | mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest + - name: Print debug avdmanager list + run: | + avdmanager list + which avdmanager + - name: Build projects and run instrumented screenshot tests id: dropshotsverify continue-on-error: true @@ -309,7 +314,6 @@ jobs: disable-animations: true disk-size: 6000M emulator-build: 11834374 # 34.2.14 - channel: canary heap-size: 600M profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From ffcb0b9d248787ac7f7cd55e08c75c118fbdbaa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 08:42:26 +0000 Subject: [PATCH 30/80] More debug prints Change-Id: I1d077f7b677020fa0fd401dbc0aaab19d311d880 --- .github/workflows/Build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index ddac50bce..7da3bbac7 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -301,8 +301,8 @@ jobs: - name: Print debug avdmanager list run: | - avdmanager list - which avdmanager + echo ${{ env.PATH}} + ls -al ${{ env.ANDROID_HOME}}/cmdline-tools/which avdmanager - name: Build projects and run instrumented screenshot tests id: dropshotsverify From de56d8f9f1d77c5151b86eefbf72723ebc9c9ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 09:06:04 +0000 Subject: [PATCH 31/80] More debug prints Change-Id: Ia1a49c22f37cdcb568b58164b5d71e29a02d72cc --- .github/workflows/Build.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 7da3bbac7..bd63ea5e1 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -299,10 +299,11 @@ jobs: run: | mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest - - name: Print debug avdmanager list + - name: Debug Environment run: | - echo ${{ env.PATH}} - ls -al ${{ env.ANDROID_HOME}}/cmdline-tools/which avdmanager + echo "PATH: $PATH" + echo "SHELL: $SHELL" + shell: bash - name: Build projects and run instrumented screenshot tests id: dropshotsverify From e5fdcacd271eb5f0f5764bf6af7338baa76c0381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 09:13:23 +0000 Subject: [PATCH 32/80] Sets path to /latest Change-Id: Ieb76366e1543bde1066b7afd96f20568bef45cb3 --- .github/workflows/Build.yaml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index bd63ea5e1..ed73484c3 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -295,9 +295,11 @@ jobs: with: cmdline-tools-version: 11479570 - - name: Replace cmdlinetools + # android-emulator-runner uses /latest + - name: Replace cmdlinetools and set path run: | mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest + echo ${{ env.ANDROID_HOME}}/cmdline-tools/latest >> $GITHUB_PATH - name: Debug Environment run: | @@ -305,6 +307,15 @@ jobs: echo "SHELL: $SHELL" shell: bash + - name: Print debug avdmanager list + run: avdmanager list + + - name: Print debug sdkmanager + run: | + sdkmanager --version + which sdkmanager + which avdmanager + - name: Build projects and run instrumented screenshot tests id: dropshotsverify continue-on-error: true From a348f1ad45cea2a90860dc31596107df4c67c85f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 09:16:49 +0000 Subject: [PATCH 33/80] Sets path to /latest Change-Id: I23e182675ca300adaeb9f969c46bbf4a646dfb06 --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index ed73484c3..45b273ccc 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -299,7 +299,7 @@ jobs: - name: Replace cmdlinetools and set path run: | mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest - echo ${{ env.ANDROID_HOME}}/cmdline-tools/latest >> $GITHUB_PATH + echo ${{ env.ANDROID_HOME}}/cmdline-tools/latest/bin >> $GITHUB_PATH - name: Debug Environment run: | From 4c324f4b8b5c998edf70e3b22080e40350526c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 09:35:30 +0000 Subject: [PATCH 34/80] I don't understand halp Change-Id: I7bfcf8d5a23522cd975585456188952c179e7ba2 --- .github/workflows/Build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 45b273ccc..af137e9e6 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -298,6 +298,7 @@ jobs: # android-emulator-runner uses /latest - name: Replace cmdlinetools and set path run: | + rm -rf ${{ env.ANDROID_HOME}}/cmdline-tools/latest mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest echo ${{ env.ANDROID_HOME}}/cmdline-tools/latest/bin >> $GITHUB_PATH From b81ebd2f3ddcaadf7739e6af4cec706edb60741a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 10:14:44 +0000 Subject: [PATCH 35/80] Now using right sdkmanager but More debug Change-Id: If32a685aefebe5c3d18a3e6023b9a681452ab7fe --- .github/workflows/Build.yaml | 22 ++++++++----------- .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 9 ++++---- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index af137e9e6..59bd4487e 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -247,8 +247,10 @@ jobs: include: - api-level: 27 profile: pixel_5 + target: google_apis - api-level: 33 profile: pixel_fold + target: google_apis # Enable when a new version of the runner is released. Currently v2.30.1 # https://github.com/ReactiveCircus/android-emulator-runner/releases/tag/v2.30.1 # Also, change from VanillaIceCream to 35 when that image is available @@ -302,20 +304,9 @@ jobs: mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest echo ${{ env.ANDROID_HOME}}/cmdline-tools/latest/bin >> $GITHUB_PATH - - name: Debug Environment + - name: Print debug avd run: | - echo "PATH: $PATH" - echo "SHELL: $SHELL" - shell: bash - - - name: Print debug avdmanager list - run: avdmanager list - - - name: Print debug sdkmanager - run: | - sdkmanager --version - which sdkmanager - which avdmanager + ls -alR ~/.android/avd/ - name: Build projects and run instrumented screenshot tests id: dropshotsverify @@ -330,6 +321,11 @@ jobs: heap-size: 600M profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + # TODO DEBUG + pre-emulator-launch-script: | + which sdkmanager + sdkmanager --version + sdkmanager --install 'system-images;android-33;default;x86_64' --channel=0 # Run tests, if they fail, record screenshots and exit with a failure script: > ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index 1447dd716..6a5831b02 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -18,7 +18,6 @@ package com.google.samples.apps.nowinandroid.ui import android.graphics.Bitmap import android.util.Log -import android.view.WindowInsets import androidx.core.view.WindowInsetsCompat import androidx.test.core.app.takeScreenshot import androidx.test.espresso.device.DeviceInteraction.Companion.setClosedMode @@ -162,8 +161,8 @@ class EdgeToEdgeTest { ).bottom width = metrics.bounds.width() } - Log.d("jalc", "width: $width" ) - Log.d("jalc", "topInset: $topInset" ) + Log.d("jalc", "width: $width") + Log.d("jalc", "topInset: $topInset") // Crop the top, adding extra pixels to check continuity val bitmap = takeScreenshot().let { Bitmap.createBitmap(it, 0, 0, width!!, (topInset!! * 2)) @@ -186,8 +185,8 @@ class EdgeToEdgeTest { width = metrics.bounds.width() height = metrics.bounds.height() } - Log.d("jalc", "height: $height" ) - Log.d("jalc", "bottomInset: $bottomInset" ) + Log.d("jalc", "height: $height") + Log.d("jalc", "bottomInset: $bottomInset") // Crop the top, adding extra pixels to check continuity val bitmap = takeScreenshot().let { Bitmap.createBitmap(it, 0, height!! - (bottomInset!! * 2), width!!, (bottomInset!! * 2)) From 8e5153a24b0d6bf2cf40bc0398013b835524452a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 10:26:45 +0000 Subject: [PATCH 36/80] Creates avd directory before downloading stuff Change-Id: I407c7d7105fcb86de71cdb7e352761e9ae91da75 --- .github/workflows/Build.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 59bd4487e..f88b84a53 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -304,6 +304,10 @@ jobs: mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest echo ${{ env.ANDROID_HOME}}/cmdline-tools/latest/bin >> $GITHUB_PATH + # https://github.com/ReactiveCircus/android-emulator-runner/issues/197 + - name: Create directory for AVD + run: mkdir -p /home/runner/.android/avd + - name: Print debug avd run: | ls -alR ~/.android/avd/ From 94df4d93dfb8dd680b6301fcfe86327854a87b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 12:44:55 +0000 Subject: [PATCH 37/80] Fixes api 27 tests and removes debug stuff Change-Id: I1badc84c616c8eb571cb83e95472a813d273365f --- .github/workflows/Build.yaml | 17 ------ .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 60 +++++++++++++------ 2 files changed, 43 insertions(+), 34 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index f88b84a53..a0be24aa3 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -308,10 +308,6 @@ jobs: - name: Create directory for AVD run: mkdir -p /home/runner/.android/avd - - name: Print debug avd - run: | - ls -alR ~/.android/avd/ - - name: Build projects and run instrumented screenshot tests id: dropshotsverify continue-on-error: true @@ -325,11 +321,6 @@ jobs: heap-size: 600M profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - # TODO DEBUG - pre-emulator-launch-script: | - which sdkmanager - sdkmanager --version - sdkmanager --install 'system-images;android-33;default;x86_64' --channel=0 # Run tests, if they fail, record screenshots and exit with a failure script: > ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon @@ -338,14 +329,6 @@ jobs: ; echo "Done recording new screenshots, exiting with failure" ; exit 5 - - name: Print debug avdmanager list - run: avdmanager list - - - name: Print debug sdkmanager - run: | - sdkmanager --version - which sdkmanager - - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented continue-on-error: false diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index 6a5831b02..0ea56518f 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -17,6 +17,8 @@ package com.google.samples.apps.nowinandroid.ui import android.graphics.Bitmap +import android.os.Build +import android.os.Build.VERSION_CODES import android.util.Log import androidx.core.view.WindowInsetsCompat import androidx.test.core.app.takeScreenshot @@ -92,11 +94,26 @@ class EdgeToEdgeTest { fun enableDemoMode() { UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { executeShellCommand("settings put global sysui_demo_allowed 1") - executeShellCommand("am broadcast -a com.android.systemui.demo -e command enter") - executeShellCommand("am broadcast -a com.android.systemui.demo -e command notifications -e visible false") - executeShellCommand("am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1234") - executeShellCommand("am broadcast -a com.android.systemui.demo -e command network -e wifi hide") - executeShellCommand("am broadcast -a com.android.systemui.demo -e command network -e mobile hide") + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "enter", + ) + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "notifications -e visible false", + ) + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "clock -e hhmm 1234", + ) + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "network -e wifi hide", + ) + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "network -e mobile hide", + ) } } @@ -154,15 +171,20 @@ class EdgeToEdgeTest { var width: Int? = null waitForWindowUpdate() activityScenarioRule.scenario.onActivity { activity -> + val metrics = WindowMetricsCalculator.getOrCreate() - .computeCurrentWindowMetrics(activity) - topInset = metrics.getWindowInsets().getInsets( - WindowInsetsCompat.Type.systemBars(), - ).bottom + .computeMaximumWindowMetrics(activity) + // TODO: Get the real inset dimension in = VERSION_CODES.R) { + metrics.getWindowInsets().getInsets( + WindowInsetsCompat.Type.systemBars(), + ).bottom + } else { + 100 + } width = metrics.bounds.width() } - Log.d("jalc", "width: $width") - Log.d("jalc", "topInset: $topInset") + Log.d("EdgeToEdgeTests", "System bar inset height: $topInset") // Crop the top, adding extra pixels to check continuity val bitmap = takeScreenshot().let { Bitmap.createBitmap(it, 0, 0, width!!, (topInset!! * 2)) @@ -177,16 +199,20 @@ class EdgeToEdgeTest { waitForWindowUpdate() activityScenarioRule.scenario.onActivity { activity -> val metrics = WindowMetricsCalculator.getOrCreate() - .computeCurrentWindowMetrics(activity) - bottomInset = metrics.getWindowInsets().getInsets( - WindowInsetsCompat.Type.navigationBars(), - ).bottom + .computeMaximumWindowMetrics(activity) + // TODO: Get the real inset dimension in = VERSION_CODES.R) { + metrics.getWindowInsets().getInsets( + WindowInsetsCompat.Type.navigationBars(), + ).bottom + } else { + 100 + } width = metrics.bounds.width() height = metrics.bounds.height() } - Log.d("jalc", "height: $height") - Log.d("jalc", "bottomInset: $bottomInset") + Log.d("EdgeToEdgeTests", "Navigation bar inset height: $bottomInset") // Crop the top, adding extra pixels to check continuity val bitmap = takeScreenshot().let { Bitmap.createBitmap(it, 0, height!! - (bottomInset!! * 2), width!!, (bottomInset!! * 2)) From bf827656164193cf07c6d98f60f2f31504dce05c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 13:58:51 +0000 Subject: [PATCH 38/80] Simplifies edge to edge tests Change-Id: Ie03bb2f10b08f0c65c69693dd3151e913ef96415 --- .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 96 ++++++++++--------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index 0ea56518f..b17a16bac 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -17,14 +17,13 @@ package com.google.samples.apps.nowinandroid.ui import android.graphics.Bitmap -import android.os.Build -import android.os.Build.VERSION_CODES -import android.util.Log -import androidx.core.view.WindowInsetsCompat import androidx.test.core.app.takeScreenshot import androidx.test.espresso.device.DeviceInteraction.Companion.setClosedMode import androidx.test.espresso.device.DeviceInteraction.Companion.setFlatMode +import androidx.test.espresso.device.DeviceInteraction.Companion.setScreenOrientation import androidx.test.espresso.device.EspressoDevice.Companion.onDevice +import androidx.test.espresso.device.action.ScreenOrientation.LANDSCAPE +import androidx.test.espresso.device.action.ScreenOrientation.PORTRAIT import androidx.test.espresso.device.common.executeShellCommand import androidx.test.espresso.device.controller.DeviceMode.CLOSED import androidx.test.espresso.device.controller.DeviceMode.FLAT @@ -37,7 +36,6 @@ import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import androidx.window.core.ExperimentalWindowApi -import androidx.window.layout.WindowMetricsCalculator import com.dropbox.dropshots.Dropshots import com.google.samples.apps.nowinandroid.MainActivity import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPermissionRule @@ -129,6 +127,7 @@ class EdgeToEdgeTest { @SdkSuppress(minSdkVersion = 27, maxSdkVersion = 27) @Test fun edgeToEdge_Phone_Api27() { + onDevice().setScreenOrientation(PORTRAIT) screenshotSystemBar("edgeToEdge_Phone_systemBar_Api27") screenshotNavigationBar("edgeToEdge_Phone_navBar_Api27") } @@ -138,6 +137,7 @@ class EdgeToEdgeTest { @SdkSuppress(minSdkVersion = 33, maxSdkVersion = 33) @Test fun edgeToEdge_Foldable_api33() { + onDevice().setScreenOrientation(PORTRAIT) runFoldableTests(apiName = "api33") } @@ -146,9 +146,20 @@ class EdgeToEdgeTest { @SdkSuppress(minSdkVersion = 35, codeName = "VanillaIceCream") @Test fun edgeToEdge_Foldable_api35() { + onDevice().setScreenOrientation(PORTRAIT) runFoldableTests(apiName = "api35") } + @RequiresDeviceMode(mode = CLOSED) + @SdkSuppress(minSdkVersion = 35, codeName = "VanillaIceCream") + @Test + fun edgeToEdge_Foldable_api35_landscape() { + onDevice().setClosedMode() + onDevice().setScreenOrientation(LANDSCAPE) + forceThreeButtonNavigation() + screenshotSideNavigationBar("edgeToEdge_Foldable_landscape_sideNav3button_35") + } + private fun runFoldableTests(apiName: String) { onDevice().setClosedMode() screenshotSystemBar("edgeToEdge_Foldable_closed_system_$apiName") @@ -164,60 +175,39 @@ class EdgeToEdgeTest { screenshotNavigationBar("edgeToEdge_Foldable_flat_nav3button_$apiName") forceGestureNavigation() screenshotNavigationBar("edgeToEdge_Foldable_flat_navGesture_$apiName") + onDevice().setClosedMode() } private fun screenshotSystemBar(screenshotFileName: String) { - var topInset: Int? = null - var width: Int? = null waitForWindowUpdate() - activityScenarioRule.scenario.onActivity { activity -> - - val metrics = WindowMetricsCalculator.getOrCreate() - .computeMaximumWindowMetrics(activity) - // TODO: Get the real inset dimension in = VERSION_CODES.R) { - metrics.getWindowInsets().getInsets( - WindowInsetsCompat.Type.systemBars(), - ).bottom - } else { - 100 - } - width = metrics.bounds.width() - } - Log.d("EdgeToEdgeTests", "System bar inset height: $topInset") + // Crop the top, adding extra pixels to check continuity val bitmap = takeScreenshot().let { - Bitmap.createBitmap(it, 0, 0, width!!, (topInset!! * 2)) + val newHeight = 130 + Bitmap.createBitmap(it, 0, 0, it.width, newHeight) } - dropshots.assertSnapshot(bitmap, screenshotFileName) + assertSnapshot(bitmap, screenshotFileName) } private fun screenshotNavigationBar(screenshotFileName: String) { - var bottomInset: Int? = null - var width: Int? = null - var height: Int? = null waitForWindowUpdate() - activityScenarioRule.scenario.onActivity { activity -> - val metrics = WindowMetricsCalculator.getOrCreate() - .computeMaximumWindowMetrics(activity) - // TODO: Get the real inset dimension in = VERSION_CODES.R) { - metrics.getWindowInsets().getInsets( - WindowInsetsCompat.Type.navigationBars(), - ).bottom - } else { - 100 - } - width = metrics.bounds.width() - height = metrics.bounds.height() + // Crop the bottom, adding extra pixels to check continuity + val bitmap = takeScreenshot().let { + val newHeight = 200 + Bitmap.createBitmap(it, 0, it.height - newHeight, it.width, newHeight) } - Log.d("EdgeToEdgeTests", "Navigation bar inset height: $bottomInset") + assertSnapshot(bitmap, screenshotFileName) + } + + private fun screenshotSideNavigationBar(screenshotFileName: String) { + waitForWindowUpdate() + // Crop the top, adding extra pixels to check continuity val bitmap = takeScreenshot().let { - Bitmap.createBitmap(it, 0, height!! - (bottomInset!! * 2), width!!, (bottomInset!! * 2)) + Bitmap.createBitmap(it, it.width - 250, 0, 250, it.height) } - dropshots.assertSnapshot(bitmap, screenshotFileName) + assertSnapshot(bitmap, screenshotFileName) } private fun forceThreeButtonNavigation() { @@ -244,7 +234,25 @@ class EdgeToEdgeTest { UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) .waitForWindowUpdate( InstrumentationRegistry.getInstrumentation().targetContext.packageName, - 4000, + 8000, ) } + + fun assertSnapshot( + bitmap: Bitmap, + name: String, + filePath: String? = null, + ) { + // Try to assert 3 times + var count = 2 + while (true) { + try { + dropshots.assertSnapshot(bitmap, name, filePath) + } catch (e: AssertionError) { + if (count == 0) throw e + count -= 1 + waitForWindowUpdate() + } + } + } } From 9a436211b586e686a52440a60a6b921ce72c56b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 14:28:48 +0000 Subject: [PATCH 39/80] CI experiment Change-Id: I7e7657ab34832d5988ebbe6af0d5464e9b4364ff --- .github/workflows/Build.yaml | 8 +++++--- .../google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index a0be24aa3..f337522f0 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -310,7 +310,7 @@ jobs: - name: Build projects and run instrumented screenshot tests id: dropshotsverify - continue-on-error: true + continue-on-error: false uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} @@ -323,11 +323,12 @@ jobs: emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure script: > + set +o pipefail && ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; echo "Done recording new screenshots, exiting with failure" - ; exit 5 + ; echo ::set-output name=newgoldens::true - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented @@ -338,12 +339,13 @@ jobs: - name: Checkout new changes (in case another job already uploaded screenshots) uses: actions/checkout@v4 + if: steps.dropshotsverify.outputs.newgoldens == 'true' with: clean: false - name: Push new device screenshots if available uses: stefanzweifel/git-auto-commit-action@4b8a201e31cadd9829df349894b28c54e6c19fe6 - if: steps.dropshotsverify.outcome == 'failure' + if: steps.dropshotsverify.outputs.newgoldens == 'true' with: file_pattern: 'app/src/androidTest/screenshots/*.png' disable_globbing: true diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index b17a16bac..d6a4c87be 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -17,6 +17,7 @@ package com.google.samples.apps.nowinandroid.ui import android.graphics.Bitmap +import android.util.Log import androidx.test.core.app.takeScreenshot import androidx.test.espresso.device.DeviceInteraction.Companion.setClosedMode import androidx.test.espresso.device.DeviceInteraction.Companion.setFlatMode @@ -251,6 +252,7 @@ class EdgeToEdgeTest { } catch (e: AssertionError) { if (count == 0) throw e count -= 1 + Log.i("EdgeToEdgeTest", "Test failed, retrying (count=$count)") waitForWindowUpdate() } } From 62cf6ce39065c57358ea088299697ec4d35305fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 14:36:30 +0000 Subject: [PATCH 40/80] CI experiment Change-Id: I2628c43c7ede114ef7e6c6e6abfbf19a7092ce22 --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index f337522f0..a72ee4817 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -323,7 +323,7 @@ jobs: emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure script: > - set +o pipefail && + set +e ; # do not fail fast ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace From 13aedf415ee0527a3d25c2929744a4420f6af166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 14:42:50 +0000 Subject: [PATCH 41/80] CI experiment Change-Id: I0ec26daffaa4d411b20194600c60b050d392bb5c --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index a72ee4817..cb1b6a8d7 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -323,7 +323,7 @@ jobs: emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure script: > - set +e ; # do not fail fast + set +e ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace From 784f94c7de0ae0ff460878493431016fc0542093 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 15:07:18 +0000 Subject: [PATCH 42/80] CI experiment Change-Id: Ifcda417383bb7c9972de1c3e2efa4d641b32864f --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index cb1b6a8d7..8d148eff5 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -328,7 +328,7 @@ jobs: || echo "Recording new screenshots" ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; echo "Done recording new screenshots, exiting with failure" - ; echo ::set-output name=newgoldens::true + ; echo "newgoldens=true" >> $GITHUB_OUTPUT ; exit 5 - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented From ece23564cb262d32c55fd880b9e98eb807c02f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 15:28:59 +0000 Subject: [PATCH 43/80] CI experiment Change-Id: I5f11e19f53c66d3dd546f935c9ba74014e0cb2f3 --- .github/workflows/Build.yaml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 8d148eff5..b6f427d3f 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -324,11 +324,18 @@ jobs: # Run tests, if they fail, record screenshots and exit with a failure script: > set +e ; - ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon - || echo "Recording new screenshots" - ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace - ; echo "Done recording new screenshots, exiting with failure" - ; echo "newgoldens=true" >> $GITHUB_OUTPUT ; exit 5 + if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then + echo "All screenshot tests passed" + else + echo "Verification failed. Recording new reference images" + if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; then + echo "New goldens recorded, no issues" + ; echo "newgoldens=true" >> $GITHUB_OUTPUT + else + echo "Error while recording new goldens" + ; exit 5 + fi + fi - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented From 3abab2503cb4cbdd885f217f45c4a3c2468be176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 16:03:28 +0000 Subject: [PATCH 44/80] CI experiment Change-Id: I9178ce207eaca6e7f1f467fd29ac438b0ba70b0b --- .github/workflows/Build.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index b6f427d3f..b8cebc0a0 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -322,7 +322,7 @@ jobs: profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure - script: > + script: | set +e ; if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then echo "All screenshot tests passed" @@ -330,10 +330,10 @@ jobs: echo "Verification failed. Recording new reference images" if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; then echo "New goldens recorded, no issues" - ; echo "newgoldens=true" >> $GITHUB_OUTPUT + echo "newgoldens=true" >> $GITHUB_OUTPUT else echo "Error while recording new goldens" - ; exit 5 + exit 5 fi fi From 848ab7b40cefe6907185f498c109d2234cc0097b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 16:14:32 +0000 Subject: [PATCH 45/80] CI experiment Change-Id: I27499c0ba4e06586d41f589fc559a2032f5d9f3e --- .github/workflows/Build.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index b8cebc0a0..5e74356fe 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -324,11 +324,13 @@ jobs: # Run tests, if they fail, record screenshots and exit with a failure script: | set +e ; - if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then + if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; + then echo "All screenshot tests passed" else echo "Verification failed. Recording new reference images" - if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; then + if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; + then echo "New goldens recorded, no issues" echo "newgoldens=true" >> $GITHUB_OUTPUT else From 60242d12e9a0cfb02a3a52af9c7a655c1f5d91d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 27 May 2024 16:22:48 +0000 Subject: [PATCH 46/80] No idea what's going on Change-Id: I238105104799ee4e4328d177ad4569e1e447f990 --- .github/workflows/Build.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 5e74356fe..6037bf0d3 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -323,13 +323,13 @@ jobs: emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure script: | - set +e ; - if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; + set +e + if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon then echo "All screenshot tests passed" else echo "Verification failed. Recording new reference images" - if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; + if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace then echo "New goldens recorded, no issues" echo "newgoldens=true" >> $GITHUB_OUTPUT From d4093a5cc2530a71ae204c7edfdda2a3c3cef36d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 28 May 2024 07:44:07 +0000 Subject: [PATCH 47/80] Simplify if clause Change-Id: I52bd1c0755e56e7357a2b49952cf813b9d8fdf97 --- .github/workflows/Build.yaml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 6037bf0d3..635a00362 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -328,15 +328,9 @@ jobs: then echo "All screenshot tests passed" else - echo "Verification failed. Recording new reference images" - if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace - then - echo "New goldens recorded, no issues" - echo "newgoldens=true" >> $GITHUB_OUTPUT - else - echo "Error while recording new goldens" - exit 5 - fi + echo "Recording new goldens" + ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace + echo "newgoldens=true" >> $GITHUB_OUTPUT fi - name: Prevent pushing new screenshots if this is a fork From 4c7921322abbd9b18e65bbf6f5f27efb432185f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 28 May 2024 07:54:30 +0000 Subject: [PATCH 48/80] The action does some script parsing that is breaking the if clause, lets try single line Change-Id: Icfd4a6fd945393b434c3eb171ddaee376459b0e9 --- .github/workflows/Build.yaml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 635a00362..a3737a17d 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -322,15 +322,14 @@ jobs: profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure - script: | - set +e - if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon - then - echo "All screenshot tests passed" + script: > + set +e ; + if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then + echo "All screenshot tests passed" ; else - echo "Recording new goldens" - ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace - echo "newgoldens=true" >> $GITHUB_OUTPUT + echo "Recording new goldens" ; + ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; + echo "newgoldens=true" >> $GITHUB_OUTPUT ; fi - name: Prevent pushing new screenshots if this is a fork From ee7556fa9594e1630358015af15a43277404d257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 28 May 2024 08:19:15 +0000 Subject: [PATCH 49/80] Script in single line Change-Id: I41223f4d777747c55c586bb8d2aecd86db21d85f --- .github/workflows/Build.yaml | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index a3737a17d..054d7a64e 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -251,11 +251,9 @@ jobs: - api-level: 33 profile: pixel_fold target: google_apis - # Enable when a new version of the runner is released. Currently v2.30.1 - # https://github.com/ReactiveCircus/android-emulator-runner/releases/tag/v2.30.1 - # Also, change from VanillaIceCream to 35 when that image is available -# - api-level: VanillaIceCream -# profile: pixel_fold + # TODO: change from VanillaIceCream to 35 when that image is available + - api-level: VanillaIceCream + profile: pixel_fold steps: - name: Delete unnecessary tools 🔧 @@ -322,15 +320,8 @@ jobs: profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure - script: > - set +e ; - if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then - echo "All screenshot tests passed" ; - else - echo "Recording new goldens" ; - ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; - echo "newgoldens=true" >> $GITHUB_OUTPUT ; - fi + script: + set +e ; if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then echo "All screenshot tests passed" ; else echo "Recording new goldens" ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; echo "newgoldens=true" >> $GITHUB_OUTPUT ; fi - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented From ad5dc1b8fc5a15f22d77d8d37ce5911f952f75bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 28 May 2024 08:29:00 +0000 Subject: [PATCH 50/80] Pixel fold is google_apis Change-Id: I0840f2c8fac16d59bc42ed62a1033438c1b4b3b0 --- .github/workflows/Build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 054d7a64e..31c8ba8aa 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -254,6 +254,7 @@ jobs: # TODO: change from VanillaIceCream to 35 when that image is available - api-level: VanillaIceCream profile: pixel_fold + target: google_apis steps: - name: Delete unnecessary tools 🔧 From 1160b889927a3f336f4c49fef55b1cb8ce26a877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 28 May 2024 08:33:04 +0000 Subject: [PATCH 51/80] Adds target Change-Id: I225ce5b4e28564a05754b9230fb175b5c91c9e14 --- .github/workflows/Build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 31c8ba8aa..057fea179 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -313,6 +313,7 @@ jobs: uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} + target: ${{ matrix.target }} arch: x86_64 disable-animations: true disk-size: 6000M From 0005c1b93f455d9a1217ede3bcf77a2b158337dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 28 May 2024 08:44:14 +0000 Subject: [PATCH 52/80] no google_apis for api 27 Change-Id: I87df5cc139d25bee28070306983f16fbbd270fb4 --- .github/workflows/Build.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 057fea179..2ce16c92b 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -247,7 +247,7 @@ jobs: include: - api-level: 27 profile: pixel_5 - target: google_apis + target: default - api-level: 33 profile: pixel_fold target: google_apis @@ -322,6 +322,7 @@ jobs: profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # Run tests, if they fail, record screenshots and exit with a failure + #TODO: Split the script in multiple lines (note that the action does some parsing that breaks multiline) script: set +e ; if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then echo "All screenshot tests passed" ; else echo "Recording new goldens" ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; echo "newgoldens=true" >> $GITHUB_OUTPUT ; fi From fde23a4630ba198052cfd9789faaa3a08da22755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 28 May 2024 09:08:34 +0000 Subject: [PATCH 53/80] There is a flaky test but the step should not pass Change-Id: I0de92c500ecdf1029d0a11c505b41df7ea3ec042 --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 2ce16c92b..36197883f 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -324,7 +324,7 @@ jobs: # Run tests, if they fail, record screenshots and exit with a failure #TODO: Split the script in multiple lines (note that the action does some parsing that breaks multiline) script: - set +e ; if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then echo "All screenshot tests passed" ; else echo "Recording new goldens" ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace ; echo "newgoldens=true" >> $GITHUB_OUTPUT ; fi + set +e ; if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then echo "All screenshot tests passed" ; else echo "Recording new goldens" ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace && echo "newgoldens=true" >> $GITHUB_OUTPUT ; fi - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented From 8ff1ac5addaeb3339e1636d5b1fa13ddf762e7e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 28 May 2024 09:52:45 +0000 Subject: [PATCH 54/80] Now we can comment out the flaky test Change-Id: Ifc041931bcf47e8716dcbe1e8c13617c88c932ea --- .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index d6a4c87be..2479bdb38 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -23,7 +23,6 @@ import androidx.test.espresso.device.DeviceInteraction.Companion.setClosedMode import androidx.test.espresso.device.DeviceInteraction.Companion.setFlatMode import androidx.test.espresso.device.DeviceInteraction.Companion.setScreenOrientation import androidx.test.espresso.device.EspressoDevice.Companion.onDevice -import androidx.test.espresso.device.action.ScreenOrientation.LANDSCAPE import androidx.test.espresso.device.action.ScreenOrientation.PORTRAIT import androidx.test.espresso.device.common.executeShellCommand import androidx.test.espresso.device.controller.DeviceMode.CLOSED @@ -151,15 +150,18 @@ class EdgeToEdgeTest { runFoldableTests(apiName = "api35") } - @RequiresDeviceMode(mode = CLOSED) - @SdkSuppress(minSdkVersion = 35, codeName = "VanillaIceCream") - @Test - fun edgeToEdge_Foldable_api35_landscape() { - onDevice().setClosedMode() - onDevice().setScreenOrientation(LANDSCAPE) - forceThreeButtonNavigation() - screenshotSideNavigationBar("edgeToEdge_Foldable_landscape_sideNav3button_35") - } + // Very flaky:DeviceControllerOperationException: Device could not be set to the + // requested screen orientation. + +// @RequiresDeviceMode(mode = CLOSED) +// @SdkSuppress(minSdkVersion = 35, codeName = "VanillaIceCream") +// @Test +// fun edgeToEdge_Foldable_api35_landscape() { +// onDevice().setClosedMode() +// onDevice().setScreenOrientation(LANDSCAPE) +// forceThreeButtonNavigation() +// screenshotSideNavigationBar("edgeToEdge_Foldable_landscape_sideNav3button_35") +// } private fun runFoldableTests(apiName: String) { onDevice().setClosedMode() From d75d4f0d7a0da694ff0094c13e1b6e67caa63a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 28 May 2024 10:10:19 +0000 Subject: [PATCH 55/80] Removes espresso device Change-Id: I5c32f70dad7dc27c98c34733f3fd80c71ccb773a --- .../google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index 2479bdb38..9ef5e5554 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -21,9 +21,7 @@ import android.util.Log import androidx.test.core.app.takeScreenshot import androidx.test.espresso.device.DeviceInteraction.Companion.setClosedMode import androidx.test.espresso.device.DeviceInteraction.Companion.setFlatMode -import androidx.test.espresso.device.DeviceInteraction.Companion.setScreenOrientation import androidx.test.espresso.device.EspressoDevice.Companion.onDevice -import androidx.test.espresso.device.action.ScreenOrientation.PORTRAIT import androidx.test.espresso.device.common.executeShellCommand import androidx.test.espresso.device.controller.DeviceMode.CLOSED import androidx.test.espresso.device.controller.DeviceMode.FLAT @@ -127,7 +125,6 @@ class EdgeToEdgeTest { @SdkSuppress(minSdkVersion = 27, maxSdkVersion = 27) @Test fun edgeToEdge_Phone_Api27() { - onDevice().setScreenOrientation(PORTRAIT) screenshotSystemBar("edgeToEdge_Phone_systemBar_Api27") screenshotNavigationBar("edgeToEdge_Phone_navBar_Api27") } @@ -137,7 +134,6 @@ class EdgeToEdgeTest { @SdkSuppress(minSdkVersion = 33, maxSdkVersion = 33) @Test fun edgeToEdge_Foldable_api33() { - onDevice().setScreenOrientation(PORTRAIT) runFoldableTests(apiName = "api33") } @@ -146,7 +142,6 @@ class EdgeToEdgeTest { @SdkSuppress(minSdkVersion = 35, codeName = "VanillaIceCream") @Test fun edgeToEdge_Foldable_api35() { - onDevice().setScreenOrientation(PORTRAIT) runFoldableTests(apiName = "api35") } From 5ddcba591efc4ce43d99ad2a7dc2cc6dd03206ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Tue, 28 May 2024 10:40:44 +0000 Subject: [PATCH 56/80] Restrict screenshot tests to :app Change-Id: I96dc5df1fccac71c42fb0e87997969bdf7b2d5f3 --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 36197883f..adfedf5b1 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -324,7 +324,7 @@ jobs: # Run tests, if they fail, record screenshots and exit with a failure #TODO: Split the script in multiple lines (note that the action does some parsing that breaks multiline) script: - set +e ; if ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then echo "All screenshot tests passed" ; else echo "Recording new goldens" ; ./gradlew connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace && echo "newgoldens=true" >> $GITHUB_OUTPUT ; fi + set +e ; if ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then echo "All screenshot tests passed" ; else echo "Recording new goldens" ; ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace && echo "newgoldens=true" >> $GITHUB_OUTPUT ; fi - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented From 96dd9dc9407d21a1657107151f26f4b5ed429c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 30 May 2024 13:08:59 +0000 Subject: [PATCH 57/80] Weird emulator issues, joy Change-Id: Ie042a4ff74185279c4b42016261ce94757a5bee9 --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index adfedf5b1..d0822d533 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -324,7 +324,7 @@ jobs: # Run tests, if they fail, record screenshots and exit with a failure #TODO: Split the script in multiple lines (note that the action does some parsing that breaks multiline) script: - set +e ; if ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon ; then echo "All screenshot tests passed" ; else echo "Recording new goldens" ; ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace && echo "newgoldens=true" >> $GITHUB_OUTPUT ; fi + set +e ; if ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -i --daemon ; then echo "All screenshot tests passed" ; else echo "Recording new goldens" ; ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon -i --stacktrace && echo "newgoldens=true" >> $GITHUB_OUTPUT ; fi - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented From 175bb21fc8f7cd52a47734e7727ce0040ebc836e Mon Sep 17 00:00:00 2001 From: Jose Alcerreca Date: Fri, 31 May 2024 12:28:14 +0200 Subject: [PATCH 58/80] Trying again with two emulator steps --- .github/workflows/Build.yaml | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index d0822d533..ac51f2ac6 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -309,7 +309,7 @@ jobs: - name: Build projects and run instrumented screenshot tests id: dropshotsverify - continue-on-error: false + continue-on-error: true uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} @@ -324,7 +324,7 @@ jobs: # Run tests, if they fail, record screenshots and exit with a failure #TODO: Split the script in multiple lines (note that the action does some parsing that breaks multiline) script: - set +e ; if ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -i --daemon ; then echo "All screenshot tests passed" ; else echo "Recording new goldens" ; ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon -i --stacktrace && echo "newgoldens=true" >> $GITHUB_OUTPUT ; fi + ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -i --daemon - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented @@ -333,15 +333,35 @@ jobs: run: | echo "::error::Instrumented screenshot tests failed, please create a PR in your fork first." && exit 1 + - name: Record new screenshots if verification failed + id: dropshotsverify + continue-on-error: false + if: steps.dropshotsverify.outcome == 'failure' + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ matrix.api-level }} + target: ${{ matrix.target }} + arch: x86_64 + disable-animations: true + disk-size: 6000M + emulator-build: 11834374 # 34.2.14 + heap-size: 600M + profile: ${{ matrix.profile }} + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + # Run tests, if they fail, record screenshots and exit with a failure + #TODO: Split the script in multiple lines (note that the action does some parsing that breaks multiline) + script: + ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon -i --stacktrace + - name: Checkout new changes (in case another job already uploaded screenshots) uses: actions/checkout@v4 - if: steps.dropshotsverify.outputs.newgoldens == 'true' +# if: steps.dropshotsverify.outputs.newgoldens == 'true' with: clean: false - name: Push new device screenshots if available uses: stefanzweifel/git-auto-commit-action@4b8a201e31cadd9829df349894b28c54e6c19fe6 - if: steps.dropshotsverify.outputs.newgoldens == 'true' +# if: steps.dropshotsverify.outputs.newgoldens == 'true' with: file_pattern: 'app/src/androidTest/screenshots/*.png' disable_globbing: true From b4f9e0df785dab32a527e64856e918a7cbd2b5b0 Mon Sep 17 00:00:00 2001 From: Jose Alcerreca Date: Fri, 31 May 2024 12:32:46 +0200 Subject: [PATCH 59/80] Trying again with two emulator steps --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index ac51f2ac6..067043d92 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -334,7 +334,7 @@ jobs: echo "::error::Instrumented screenshot tests failed, please create a PR in your fork first." && exit 1 - name: Record new screenshots if verification failed - id: dropshotsverify + id: dropshotsrecord continue-on-error: false if: steps.dropshotsverify.outcome == 'failure' uses: reactivecircus/android-emulator-runner@v2 From 39c1bb4098ce9c81f80ef8b86550c0c7fc32547d Mon Sep 17 00:00:00 2001 From: Jose Alcerreca Date: Fri, 31 May 2024 13:19:20 +0200 Subject: [PATCH 60/80] Debug hell --- .github/workflows/Build.yaml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 067043d92..84d2ea9b8 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -309,7 +309,6 @@ jobs: - name: Build projects and run instrumented screenshot tests id: dropshotsverify - continue-on-error: true uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} @@ -321,10 +320,8 @@ jobs: heap-size: 600M profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - # Run tests, if they fail, record screenshots and exit with a failure - #TODO: Split the script in multiple lines (note that the action does some parsing that breaks multiline) script: - ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -i --daemon + ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented @@ -348,10 +345,14 @@ jobs: heap-size: 600M profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - # Run tests, if they fail, record screenshots and exit with a failure - #TODO: Split the script in multiple lines (note that the action does some parsing that breaks multiline) script: - ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon -i --stacktrace + ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace + + - name: Breakpoint if tests failed + uses: namespacelabs/breakpoint-action@v0 + with: + duration: 30m + authorized-users: jack123, alice321 - name: Checkout new changes (in case another job already uploaded screenshots) uses: actions/checkout@v4 From dee3bdb035009c2f3d359cb5241d20fc432053bd Mon Sep 17 00:00:00 2001 From: Jose Alcerreca Date: Fri, 31 May 2024 13:28:08 +0200 Subject: [PATCH 61/80] Debug hell --- .github/workflows/Build.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 84d2ea9b8..f01ad930a 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -323,6 +323,12 @@ jobs: script: ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon + - name: Breakpoint if tests failed + uses: namespacelabs/breakpoint-action@v0 + with: + duration: 30m + authorized-users: jack123, alice321 + - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented continue-on-error: false @@ -348,11 +354,6 @@ jobs: script: ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests -Pdropshots.record --daemon --stacktrace - - name: Breakpoint if tests failed - uses: namespacelabs/breakpoint-action@v0 - with: - duration: 30m - authorized-users: jack123, alice321 - name: Checkout new changes (in case another job already uploaded screenshots) uses: actions/checkout@v4 From f8f80e8ff2935c3bb5989858ee6de7a01f1ef941 Mon Sep 17 00:00:00 2001 From: Jose Alcerreca Date: Fri, 31 May 2024 13:48:53 +0200 Subject: [PATCH 62/80] Debug hell --- .github/workflows/Build.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index f01ad930a..949625578 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -309,6 +309,7 @@ jobs: - name: Build projects and run instrumented screenshot tests id: dropshotsverify + continue-on-error: true uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} @@ -325,6 +326,7 @@ jobs: - name: Breakpoint if tests failed uses: namespacelabs/breakpoint-action@v0 + if: steps.dropshotsverify.outcome == 'failure' with: duration: 30m authorized-users: jack123, alice321 From b2ad870c0800a4d88a39b438db1da51762057e59 Mon Sep 17 00:00:00 2001 From: Jose Alcerreca Date: Fri, 31 May 2024 14:36:38 +0200 Subject: [PATCH 63/80] Debug hell --- .github/workflows/Build.yaml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 949625578..5af043b83 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -278,8 +278,6 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Copy CI gradle.properties - run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties - name: Set up JDK 17 uses: actions/setup-java@v4 @@ -307,6 +305,11 @@ jobs: - name: Create directory for AVD run: mkdir -p /home/runner/.android/avd + - name: Collect Workflow Telemetry + uses: catchpoint/workflow-telemetry-action@v2 + with: + comment_on_pr: false + - name: Build projects and run instrumented screenshot tests id: dropshotsverify continue-on-error: true @@ -325,11 +328,7 @@ jobs: ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon - name: Breakpoint if tests failed - uses: namespacelabs/breakpoint-action@v0 - if: steps.dropshotsverify.outcome == 'failure' - with: - duration: 30m - authorized-users: jack123, alice321 + run: top - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented From d16ed17497f72e05129222d484a9b8dbd872aa52 Mon Sep 17 00:00:00 2001 From: Jose Alcerreca Date: Fri, 31 May 2024 15:00:08 +0200 Subject: [PATCH 64/80] Debug hell --- .github/workflows/Build.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 5af043b83..228a5cc4f 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -327,8 +327,6 @@ jobs: script: ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon - - name: Breakpoint if tests failed - run: top - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented From 2b281277b73a1472471adb0a4c10757fbe9a1672 Mon Sep 17 00:00:00 2001 From: Jose Alcerreca Date: Mon, 3 Jun 2024 10:13:26 +0200 Subject: [PATCH 65/80] Runner hangs when launching emulator for the second time, trying new memory args --- .github/ci-gradle.properties | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/ci-gradle.properties b/.github/ci-gradle.properties index dbafa68cd..2c8213166 100644 --- a/.github/ci-gradle.properties +++ b/.github/ci-gradle.properties @@ -15,9 +15,7 @@ # org.gradle.daemon=false -org.gradle.parallel=true -org.gradle.workers.max=2 - +org.gradle.jvmargs=-Xmx8g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g kotlin.incremental=false # Controls KotlinOptions.allWarningsAsErrors. From 19edb84da9814b2d107b7aef98467ec3a7567fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Wed, 5 Jun 2024 07:28:07 +0000 Subject: [PATCH 66/80] SHAME! I added an infinite loop Change-Id: I60a019523ff703dfdda3ea0c16b052525412eb8d --- .../com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index 9ef5e5554..b0543edfc 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -52,7 +52,6 @@ import org.junit.rules.TemporaryFolder * - A foldable on API 33 (pixel_fold) * - A foldable on API 35 (pixel_fold) */ -@OptIn(ExperimentalWindowApi::class) @HiltAndroidTest @InstrumentedScreenshotTests class EdgeToEdgeTest { @@ -251,7 +250,9 @@ class EdgeToEdgeTest { count -= 1 Log.i("EdgeToEdgeTest", "Test failed, retrying (count=$count)") waitForWindowUpdate() + continue } + break } } } From 2323822d5338b9fa655d20444948b724c302d9df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Wed, 5 Jun 2024 09:00:54 +0000 Subject: [PATCH 67/80] Fixed! Except for API 35, uploading logcat Change-Id: I689a9a6b1204df6c297704b6214a7ebb280d2d57 --- .github/workflows/Build.yaml | 9 ++++++++- .../samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 228a5cc4f..b61342531 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -325,8 +325,14 @@ jobs: profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none script: - ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon + adb logcat > logcat.log & ./gradlew :app:connectedDemoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.google.samples.apps.nowinandroid.ui.InstrumentedScreenshotTests --daemon + - name: Upload logcat + if: always() + uses: actions/upload-artifact@v4 + with: + name: logcat-${{ matrix.profile }}-${{ matrix.api-level }} + path: logcat.log - name: Prevent pushing new screenshots if this is a fork id: checkfork_screenshots_instrumented @@ -374,3 +380,4 @@ jobs: with: name: test-reports-${{ matrix.profile }}-${{ matrix.api-level }} path: '**/build/reports/androidTests' + diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index b0543edfc..defc07398 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -33,7 +33,6 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice -import androidx.window.core.ExperimentalWindowApi import com.dropbox.dropshots.Dropshots import com.google.samples.apps.nowinandroid.MainActivity import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPermissionRule From e26492a0c1e0fc9f0b9d8cd865efe8b611c4338b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Wed, 5 Jun 2024 14:40:12 +0000 Subject: [PATCH 68/80] Cutout tests, working locally. Need to rebase Change-Id: Ib3e4dc2c62bbdd89bfd6380a33310e3033a58966 --- .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 60 +++++++++++++++---- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index defc07398..48511600c 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -21,7 +21,10 @@ import android.util.Log import androidx.test.core.app.takeScreenshot import androidx.test.espresso.device.DeviceInteraction.Companion.setClosedMode import androidx.test.espresso.device.DeviceInteraction.Companion.setFlatMode +import androidx.test.espresso.device.DeviceInteraction.Companion.setScreenOrientation import androidx.test.espresso.device.EspressoDevice.Companion.onDevice +import androidx.test.espresso.device.action.ScreenOrientation.LANDSCAPE +import androidx.test.espresso.device.action.ScreenOrientation.PORTRAIT import androidx.test.espresso.device.common.executeShellCommand import androidx.test.espresso.device.controller.DeviceMode.CLOSED import androidx.test.espresso.device.controller.DeviceMode.FLAT @@ -143,18 +146,36 @@ class EdgeToEdgeTest { runFoldableTests(apiName = "api35") } + @RequiresDeviceMode(mode = FLAT) + @RequiresDeviceMode(mode = CLOSED) + @SdkSuppress(minSdkVersion = 35, codeName = "VanillaIceCream") + @Test + fun edgeToEdge_Foldable_api35_tallCutout() { + forceTallCutout() + onDevice().setClosedMode() + screenshotSystemBar("edgeToEdge_Foldable_closed_system_tallCutout_api35") + + onDevice().setFlatMode() + enableDemoMode() // Flat mode resets demo mode! + screenshotSystemBar("edgeToEdge_Foldable_flat_system_tallCutout_api35") + forceThreeButtonNavigation() + onDevice().setClosedMode() + resetCutout() + } + // Very flaky:DeviceControllerOperationException: Device could not be set to the // requested screen orientation. -// @RequiresDeviceMode(mode = CLOSED) -// @SdkSuppress(minSdkVersion = 35, codeName = "VanillaIceCream") -// @Test -// fun edgeToEdge_Foldable_api35_landscape() { -// onDevice().setClosedMode() -// onDevice().setScreenOrientation(LANDSCAPE) -// forceThreeButtonNavigation() -// screenshotSideNavigationBar("edgeToEdge_Foldable_landscape_sideNav3button_35") -// } + @RequiresDeviceMode(mode = CLOSED) + @SdkSuppress(minSdkVersion = 35, codeName = "VanillaIceCream") + @Test + fun edgeToEdge_Foldable_api35_landscape() { + onDevice().setClosedMode() + onDevice().setScreenOrientation(LANDSCAPE) + forceThreeButtonNavigation() + screenshotSideNavigationBar("edgeToEdge_Foldable_landscape_sideNav3button_35") + onDevice().setScreenOrientation(PORTRAIT) + } private fun runFoldableTests(apiName: String) { onDevice().setClosedMode() @@ -225,6 +246,25 @@ class EdgeToEdgeTest { waitForWindowUpdate() } + private fun forceTallCutout() { + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { + executeShellCommand( + "cmd overlay enable-exclusive " + + "--category com.android.internal.display.cutout.emulation.tall ", + ) + } + waitForWindowUpdate() + } + private fun resetCutout() { + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { + executeShellCommand( + "cmd overlay enable-exclusive " + + "--category com.android.internal.display.cutout.emulation.noCutout ", + ) + } + waitForWindowUpdate() + } + private fun waitForWindowUpdate() { // TODO: This works but it's unclear if it's making it wait too long. Investigate. UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) @@ -234,7 +274,7 @@ class EdgeToEdgeTest { ) } - fun assertSnapshot( + private fun assertSnapshot( bitmap: Bitmap, name: String, filePath: String? = null, From 0191ba0b84a13022fa80bd9bc9315880c38443e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 6 Jun 2024 13:04:30 +0000 Subject: [PATCH 69/80] Some more sync points, api 35 emulator crashing Change-Id: I90422a13aaba689b035095307446d7d343a59aed --- .../samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index 48511600c..b8b958ba5 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -153,12 +153,13 @@ class EdgeToEdgeTest { fun edgeToEdge_Foldable_api35_tallCutout() { forceTallCutout() onDevice().setClosedMode() + enableDemoMode() // Mode change resets demo mode! screenshotSystemBar("edgeToEdge_Foldable_closed_system_tallCutout_api35") onDevice().setFlatMode() - enableDemoMode() // Flat mode resets demo mode! + enableDemoMode() // Mode change resets demo mode! screenshotSystemBar("edgeToEdge_Foldable_flat_system_tallCutout_api35") - forceThreeButtonNavigation() + onDevice().setClosedMode() resetCutout() } @@ -178,6 +179,7 @@ class EdgeToEdgeTest { } private fun runFoldableTests(apiName: String) { + resetCutout() onDevice().setClosedMode() screenshotSystemBar("edgeToEdge_Foldable_closed_system_$apiName") forceThreeButtonNavigation() @@ -200,7 +202,7 @@ class EdgeToEdgeTest { // Crop the top, adding extra pixels to check continuity val bitmap = takeScreenshot().let { - val newHeight = 130 + val newHeight = 200 Bitmap.createBitmap(it, 0, 0, it.width, newHeight) } assertSnapshot(bitmap, screenshotFileName) @@ -234,6 +236,7 @@ class EdgeToEdgeTest { "com.android.internal.systemui.navbar.threebutton", ) } + waitForWindowUpdate() } private fun forceGestureNavigation() { From a61e467a39367e2d1db791fcfc7a1b32d2fe714c Mon Sep 17 00:00:00 2001 From: JoseAlcerreca Date: Thu, 6 Jun 2024 13:22:34 +0000 Subject: [PATCH 70/80] =?UTF-8?q?=F0=9F=A4=96=20Updates=20instrumented=20s?= =?UTF-8?q?creenshots.=20API=2027?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edgeToEdge_Phone_navBar_Api27.png | Bin 0 -> 10178 bytes .../edgeToEdge_Phone_systemBar_Api27.png | Bin 0 -> 20362 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/src/androidTest/screenshots/edgeToEdge_Phone_navBar_Api27.png create mode 100644 app/src/androidTest/screenshots/edgeToEdge_Phone_systemBar_Api27.png diff --git a/app/src/androidTest/screenshots/edgeToEdge_Phone_navBar_Api27.png b/app/src/androidTest/screenshots/edgeToEdge_Phone_navBar_Api27.png new file mode 100644 index 0000000000000000000000000000000000000000..ec52601ebadbefe3d09083a39f12405cd7e1c56b GIT binary patch literal 10178 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 literal 0 HcmV?d00001 diff --git a/app/src/androidTest/screenshots/edgeToEdge_Phone_systemBar_Api27.png b/app/src/androidTest/screenshots/edgeToEdge_Phone_systemBar_Api27.png new file mode 100644 index 0000000000000000000000000000000000000000..9466cfca1b444a309249566567b31166ab07181c GIT binary patch literal 20362 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 ILeDY$|1J$ILI3~& literal 0 HcmV?d00001 From 8fe9142290e534e10a038907338a40e7328c3f2e Mon Sep 17 00:00:00 2001 From: JoseAlcerreca Date: Thu, 6 Jun 2024 13:23:43 +0000 Subject: [PATCH 71/80] =?UTF-8?q?=F0=9F=A4=96=20Updates=20instrumented=20s?= =?UTF-8?q?creenshots.=20API=2033?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...eToEdge_Foldable_closed_nav3button_api33.png | Bin 0 -> 10462 bytes ...eToEdge_Foldable_closed_navGesture_api33.png | Bin 0 -> 10462 bytes .../edgeToEdge_Foldable_closed_system_api33.png | Bin 0 -> 32310 bytes ...dgeToEdge_Foldable_flat_nav3button_api33.png | Bin 0 -> 30365 bytes ...dgeToEdge_Foldable_flat_navGesture_api33.png | Bin 0 -> 33712 bytes .../edgeToEdge_Foldable_flat_system_api33.png | Bin 0 -> 52511 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/src/androidTest/screenshots/edgeToEdge_Foldable_closed_nav3button_api33.png create mode 100644 app/src/androidTest/screenshots/edgeToEdge_Foldable_closed_navGesture_api33.png create mode 100644 app/src/androidTest/screenshots/edgeToEdge_Foldable_closed_system_api33.png create mode 100644 app/src/androidTest/screenshots/edgeToEdge_Foldable_flat_nav3button_api33.png create mode 100644 app/src/androidTest/screenshots/edgeToEdge_Foldable_flat_navGesture_api33.png create mode 100644 app/src/androidTest/screenshots/edgeToEdge_Foldable_flat_system_api33.png diff --git a/app/src/androidTest/screenshots/edgeToEdge_Foldable_closed_nav3button_api33.png b/app/src/androidTest/screenshots/edgeToEdge_Foldable_closed_nav3button_api33.png new file mode 100644 index 0000000000000000000000000000000000000000..1a61f84f5cdfb57338fb8f214773001cda3c8bc9 GIT binary patch literal 10462 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 JQr`UI{{RwXA-ezo literal 0 HcmV?d00001 diff --git a/app/src/androidTest/screenshots/edgeToEdge_Foldable_closed_navGesture_api33.png b/app/src/androidTest/screenshots/edgeToEdge_Foldable_closed_navGesture_api33.png new file mode 100644 index 0000000000000000000000000000000000000000..1a61f84f5cdfb57338fb8f214773001cda3c8bc9 GIT binary patch literal 10462 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 JQr`UI{{RwXA-ezo literal 0 HcmV?d00001 diff --git a/app/src/androidTest/screenshots/edgeToEdge_Foldable_closed_system_api33.png b/app/src/androidTest/screenshots/edgeToEdge_Foldable_closed_system_api33.png new file mode 100644 index 0000000000000000000000000000000000000000..82c3106acbffa4ff22dec9f3a043a8606876417e GIT binary patch literal 32310 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ⅈcTnC^b;uV+p;Y1l~-s-SBS0Q5j24F5X3Bu6 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�A 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 Date: Mon, 20 Jan 2025 15:41:55 +0000 Subject: [PATCH 72/80] Adds more sync to EdgeToEdgeTests Change-Id: I592e5fb2ee460c69ec88db414f21bdc00e27c15f --- .github/workflows/Build.yaml | 1 - .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 43 ++++++++++++++++++- .../AndroidApplicationConventionPlugin.kt | 2 +- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index a3c21f11f..ac7897fa9 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -280,7 +280,6 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Set up JDK 17 uses: actions/setup-java@v4 with: diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index b8b958ba5..c434106a9 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -34,6 +34,7 @@ import androidx.test.espresso.device.sizeclass.HeightSizeClass.Companion.HeightS import androidx.test.espresso.device.sizeclass.WidthSizeClass.Companion.WidthSizeClassEnum import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.filters.SdkSuppress +import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice import com.dropbox.dropshots.Dropshots @@ -42,6 +43,7 @@ import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPer import dagger.hilt.android.testing.BindValue import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest +import org.junit.After import org.junit.AfterClass import org.junit.Before import org.junit.Rule @@ -90,6 +92,10 @@ class EdgeToEdgeTest { @Before fun enableDemoMode() { UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { + + executeShellCommand( + "settings put global development_settings_enabled 1" + ) executeShellCommand("settings put global sysui_demo_allowed 1") executeShellCommand( "am broadcast -a com.android.systemui.demo -e command " + @@ -111,9 +117,30 @@ class EdgeToEdgeTest { "am broadcast -a com.android.systemui.demo -e command " + "network -e mobile hide", ) + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "network -e satellite hide", + ) } } + @After + fun disableDemoMode() { + exitDemoMode() + executeShellCommand( + "settings put global sysui_demo_allowed 0" + ) + executeShellCommand( + "settings put global development_settings_enabled 0" + ) + } + + private fun exitDemoMode() { + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command exit" + ) + } + companion object { @JvmStatic @AfterClass @@ -151,12 +178,15 @@ class EdgeToEdgeTest { @SdkSuppress(minSdkVersion = 35, codeName = "VanillaIceCream") @Test fun edgeToEdge_Foldable_api35_tallCutout() { - forceTallCutout() onDevice().setClosedMode() + forceTallCutout() + exitDemoMode() enableDemoMode() // Mode change resets demo mode! screenshotSystemBar("edgeToEdge_Foldable_closed_system_tallCutout_api35") onDevice().setFlatMode() + exitDemoMode() + forceTallCutout() enableDemoMode() // Mode change resets demo mode! screenshotSystemBar("edgeToEdge_Foldable_flat_system_tallCutout_api35") @@ -174,6 +204,8 @@ class EdgeToEdgeTest { onDevice().setClosedMode() onDevice().setScreenOrientation(LANDSCAPE) forceThreeButtonNavigation() + exitDemoMode() + enableDemoMode() // This fixes the satellite icon showing up uninvited. screenshotSideNavigationBar("edgeToEdge_Foldable_landscape_sideNav3button_35") onDevice().setScreenOrientation(PORTRAIT) } @@ -188,6 +220,7 @@ class EdgeToEdgeTest { screenshotNavigationBar("edgeToEdge_Foldable_closed_navGesture_$apiName") onDevice().setFlatMode() + exitDemoMode() enableDemoMode() // Flat mode resets demo mode! screenshotSystemBar("edgeToEdge_Foldable_flat_system_$apiName") forceThreeButtonNavigation() @@ -297,4 +330,12 @@ class EdgeToEdgeTest { break } } + + private fun executeShellCommand(command: String) { + runOnUiThread { + InstrumentationRegistry.getInstrumentation().uiAutomation.executeShellCommand(command) + } + // ADB commands are not synchronized. This sleep was found empirically. + Thread.sleep(20) + } } diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt index 02c78484f..287cc4e2f 100644 --- a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt @@ -34,7 +34,7 @@ class AndroidApplicationConventionPlugin : Plugin { apply(plugin = "org.jetbrains.kotlin.android") apply(plugin = "nowinandroid.android.lint") apply(plugin = "com.dropbox.dependency-guard") - apply("com.dropbox.dropshots") + apply(plugin = "com.dropbox.dropshots") extensions.configure { configureKotlinAndroid(this) From e9c80330af3ee3b00b222e0bea44ddcf9477ae78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 20 Jan 2025 15:53:05 +0000 Subject: [PATCH 73/80] Removes hardcoded version of cmdline-tools Change-Id: I7d5bbaeef396ebd425137ad03419efe26ccf6a4b --- .github/workflows/Build.yaml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index ac7897fa9..44aaa50a6 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -292,15 +292,13 @@ jobs: # TODO this workflow needs cmdline-tools 13.0 (for pixel_fold). Remove when not necessary. - name: Setup Android SDK uses: android-actions/setup-android@v3 - with: - cmdline-tools-version: 11479570 - # android-emulator-runner uses /latest - - name: Replace cmdlinetools and set path - run: | - rm -rf ${{ env.ANDROID_HOME}}/cmdline-tools/latest - mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest - echo ${{ env.ANDROID_HOME}}/cmdline-tools/latest/bin >> $GITHUB_PATH +# # android-emulator-runner uses /latest +# - name: Replace cmdlinetools and set path +# run: | +# rm -rf ${{ env.ANDROID_HOME}}/cmdline-tools/latest +# mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest +# echo ${{ env.ANDROID_HOME}}/cmdline-tools/latest/bin >> $GITHUB_PATH # https://github.com/ReactiveCircus/android-emulator-runner/issues/197 - name: Create directory for AVD From 3afbfa4aa9dfef6de02ee88935741fead78fb2c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 20 Jan 2025 15:57:20 +0000 Subject: [PATCH 74/80] VanillaIceCream -> 35 Change-Id: I66f493a050bd0d4fad80f22a7817adeb7124af45 --- .github/workflows/Build.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 44aaa50a6..53efcceae 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -253,8 +253,7 @@ jobs: - api-level: 33 profile: pixel_fold target: google_apis - # TODO: change from VanillaIceCream to 35 when that image is available - - api-level: VanillaIceCream + - api-level: 35 profile: pixel_fold target: google_apis From 16464b0f80ad1233e36ac8bb3be8343dbb528793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 20 Jan 2025 16:18:56 +0000 Subject: [PATCH 75/80] CI Change-Id: I7e638265ebc58132efe04a37efd27393a2545446 --- .github/workflows/Build.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 53efcceae..f65795fe8 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -292,10 +292,10 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@v3 -# # android-emulator-runner uses /latest -# - name: Replace cmdlinetools and set path -# run: | -# rm -rf ${{ env.ANDROID_HOME}}/cmdline-tools/latest + # android-emulator-runner uses /latest + - name: Remove old cmdlinetools + run: | + rm -rf ${{ env.ANDROID_HOME}}/cmdline-tools/latest # mv ${{ env.ANDROID_HOME}}/cmdline-tools/11479570 ${{ env.ANDROID_HOME}}/cmdline-tools/latest # echo ${{ env.ANDROID_HOME}}/cmdline-tools/latest/bin >> $GITHUB_PATH From 6fe0bcdd17cff440789eaad64afd4f9082aceb2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 20 Jan 2025 16:45:03 +0000 Subject: [PATCH 76/80] Change emulator build to 35.4.5 and spotless Change-Id: I0d18e6554667a32609512246fe84079b99aed2fc --- .github/workflows/Build.yaml | 8 ++++---- .../samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index f65795fe8..ee2b19a0b 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -250,9 +250,9 @@ jobs: - api-level: 27 profile: pixel_5 target: default - - api-level: 33 - profile: pixel_fold - target: google_apis +# - api-level: 33 +# profile: pixel_fold +# target: google_apis - api-level: 35 profile: pixel_fold target: google_apis @@ -350,7 +350,7 @@ jobs: arch: x86_64 disable-animations: true disk-size: 6000M - emulator-build: 11834374 # 34.2.14 + emulator-build: 12895296 # 35.4.5 - https://developer.android.com/studio/emulator_archive heap-size: 600M profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index c434106a9..6e40445be 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -92,9 +92,8 @@ class EdgeToEdgeTest { @Before fun enableDemoMode() { UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { - executeShellCommand( - "settings put global development_settings_enabled 1" + "settings put global development_settings_enabled 1", ) executeShellCommand("settings put global sysui_demo_allowed 1") executeShellCommand( @@ -128,16 +127,16 @@ class EdgeToEdgeTest { fun disableDemoMode() { exitDemoMode() executeShellCommand( - "settings put global sysui_demo_allowed 0" + "settings put global sysui_demo_allowed 0", ) executeShellCommand( - "settings put global development_settings_enabled 0" + "settings put global development_settings_enabled 0", ) } private fun exitDemoMode() { executeShellCommand( - "am broadcast -a com.android.systemui.demo -e command exit" + "am broadcast -a com.android.systemui.demo -e command exit", ) } From 0b10aa7ab57ea28862bc28becf196dc1fce89cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 20 Jan 2025 17:42:31 +0000 Subject: [PATCH 77/80] Change emulator build to 35.4.5 Change-Id: Ic6321f50c5303412914377f757201885a1a2e76d --- .github/workflows/Build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index ee2b19a0b..a72ae63d3 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -318,7 +318,7 @@ jobs: arch: x86_64 disable-animations: true disk-size: 6000M - emulator-build: 11834374 # 34.2.14 + emulator-build: 12895296 # 35.4.5 - https://developer.android.com/studio/emulator_archive heap-size: 600M profile: ${{ matrix.profile }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From ec53bddb9b33f37884644b28fc6b8dec0306a948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 20 Jan 2025 18:05:23 +0000 Subject: [PATCH 78/80] Adds emulator control to CI gradle properties Change-Id: Ie66194bb50b81e3445627b973a2d1331f4a22dd3 --- .github/ci-gradle.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ci-gradle.properties b/.github/ci-gradle.properties index a9abe496a..ca3a3f376 100644 --- a/.github/ci-gradle.properties +++ b/.github/ci-gradle.properties @@ -27,3 +27,5 @@ kotlin.incremental=false # If you want to treat warnings as errors locally, set this property to true # in your ~/.gradle/gradle.properties file. warningsAsErrors=false + +android.experimental.androidTest.enableEmulatorControl=true From 9c101f2224c78296f549de27cfd1ca4b1b6abbd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Mon, 20 Jan 2025 18:30:57 +0000 Subject: [PATCH 79/80] Enables emulatorControl from convention plugins Change-Id: I2d544e9605b7c24eb8cf6528425bd95ab9b1e51f --- app/build.gradle.kts | 9 --- .../apps/nowinandroid/ui/EdgeToEdgeTest.kt | 60 +++++++++---------- .../AndroidApplicationConventionPlugin.kt | 2 + .../kotlin/AndroidFeatureConventionPlugin.kt | 1 + .../kotlin/AndroidLibraryConventionPlugin.kt | 1 + 5 files changed, 33 insertions(+), 40 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0d1efc1d2..8ef401e01 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -61,15 +61,6 @@ android { excludes.add("/META-INF/{AL2.0,LGPL2.1}") } } - testOptions { - unitTests { - isIncludeAndroidResources = true - } - // Espresso Device - emulatorControl { - enable = true - } - } namespace = "com.google.samples.apps.nowinandroid" } diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt index 6e40445be..ee21fc322 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/EdgeToEdgeTest.kt @@ -91,36 +91,34 @@ class EdgeToEdgeTest { @Before fun enableDemoMode() { - UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { - executeShellCommand( - "settings put global development_settings_enabled 1", - ) - executeShellCommand("settings put global sysui_demo_allowed 1") - executeShellCommand( - "am broadcast -a com.android.systemui.demo -e command " + - "enter", - ) - executeShellCommand( - "am broadcast -a com.android.systemui.demo -e command " + - "notifications -e visible false", - ) - executeShellCommand( - "am broadcast -a com.android.systemui.demo -e command " + - "clock -e hhmm 1234", - ) - executeShellCommand( - "am broadcast -a com.android.systemui.demo -e command " + - "network -e wifi hide", - ) - executeShellCommand( - "am broadcast -a com.android.systemui.demo -e command " + - "network -e mobile hide", - ) - executeShellCommand( - "am broadcast -a com.android.systemui.demo -e command " + - "network -e satellite hide", - ) - } + executeShellCommand( + "settings put global development_settings_enabled 1", + ) + executeShellCommand("settings put global sysui_demo_allowed 1") + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "enter", + ) + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "notifications -e visible false", + ) + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "clock -e hhmm 1234", + ) + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "network -e wifi hide", + ) + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "network -e mobile hide", + ) + executeShellCommand( + "am broadcast -a com.android.systemui.demo -e command " + + "network -e satellite hide", + ) } @After @@ -332,7 +330,7 @@ class EdgeToEdgeTest { private fun executeShellCommand(command: String) { runOnUiThread { - InstrumentationRegistry.getInstrumentation().uiAutomation.executeShellCommand(command) + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).executeShellCommand(command) } // ADB commands are not synchronized. This sleep was found empirically. Thread.sleep(20) diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt index 287cc4e2f..d5de40b34 100644 --- a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt @@ -42,6 +42,8 @@ class AndroidApplicationConventionPlugin : Plugin { @Suppress("UnstableApiUsage") testOptions.animationsDisabled = true configureGradleManagedDevices(this) + testOptions.emulatorControl.enable = true +// testOptions.unitTests.isIncludeAndroidResources } extensions.configure { configurePrintApksTask(this) diff --git a/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt index 1af5523c5..e04635d02 100644 --- a/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt @@ -32,6 +32,7 @@ class AndroidFeatureConventionPlugin : Plugin { extensions.configure { testOptions.animationsDisabled = true + testOptions.emulatorControl.enable = true configureGradleManagedDevices(this) } diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt index 3fe727410..6dea352e4 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt @@ -40,6 +40,7 @@ class AndroidLibraryConventionPlugin : Plugin { defaultConfig.targetSdk = 35 defaultConfig.testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testOptions.animationsDisabled = true + testOptions.emulatorControl.enable = true configureFlavors(this) configureGradleManagedDevices(this) // The resource prefix is derived from the module name, From 2fb91c52b9fb9fda4ed0a98c8e640d1454328545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Alc=C3=A9rreca?= Date: Thu, 6 Mar 2025 20:54:43 +0100 Subject: [PATCH 80/80] Update Build.yaml Adds -show-kernel to emulator options to get more logs --- .github/workflows/Build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index a72ae63d3..b44a5a0b6 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -199,6 +199,7 @@ jobs: disable-animations: true disk-size: 6000M heap-size: 600M + emulator-options: -show-kernel -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim script: ./gradlew connectedDemoDebugAndroidTest --daemon - name: Run local tests (including Roborazzi) for the combined coverage report (only API 30)