From 823c4db2013a27616b9d88aaca3349d87c13160d Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Wed, 24 May 2023 20:11:36 +0200 Subject: [PATCH 1/3] Grant `POST_NOTIFICATIONS` permission in more instrumented tests Continues the work initiated in #738. Extract the SDK version check inside a `GrantPostNotificationPermissionRule` class that delegates to a regular `GrantPermissionRule`. --- .../apps/nowinandroid/ui/NavigationTest.kt | 9 +++++- .../apps/nowinandroid/ui/NavigationUiTest.kt | 9 +++++- .../GrantPostNotificationsPermissionRule.kt | 29 +++++++++++++++++++ .../feature/foryou/ForYouScreenTest.kt | 17 +++-------- 4 files changed, 49 insertions(+), 15 deletions(-) create mode 100644 core/testing/src/main/java/com/google/samples/apps/nowinandroid/core/rules/GrantPostNotificationsPermissionRule.kt diff --git a/app/src/androidTest/java/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt b/app/src/androidTest/java/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt index 5aa3ab02e..036a2955c 100644 --- a/app/src/androidTest/java/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt +++ b/app/src/androidTest/java/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt @@ -33,6 +33,7 @@ import androidx.test.espresso.Espresso import androidx.test.espresso.NoActivityResumedException import com.google.samples.apps.nowinandroid.MainActivity import com.google.samples.apps.nowinandroid.R +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 @@ -66,9 +67,15 @@ class NavigationTest { val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build() /** - * Use the primary activity to initialize the app normally. + * Grant [android.Manifest.permission.POST_NOTIFICATIONS] permission. */ @get:Rule(order = 2) + val postNotificationsPermission = GrantPostNotificationsPermissionRule() + + /** + * Use the primary activity to initialize the app normally. + */ + @get:Rule(order = 3) val composeTestRule = createAndroidComposeRule() private fun AndroidComposeTestRule<*, *>.stringResource(@StringRes resId: Int) = diff --git a/app/src/androidTest/java/com/google/samples/apps/nowinandroid/ui/NavigationUiTest.kt b/app/src/androidTest/java/com/google/samples/apps/nowinandroid/ui/NavigationUiTest.kt index cd4b40a50..d92390918 100644 --- a/app/src/androidTest/java/com/google/samples/apps/nowinandroid/ui/NavigationUiTest.kt +++ b/app/src/androidTest/java/com/google/samples/apps/nowinandroid/ui/NavigationUiTest.kt @@ -27,6 +27,7 @@ import androidx.compose.ui.unit.dp import com.google.accompanist.testharness.TestHarness import com.google.samples.apps.nowinandroid.core.data.repository.CompositeUserNewsResourceRepository import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor +import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPermissionRule import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepository import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository import com.google.samples.apps.nowinandroid.uitesthiltmanifest.HiltComponentActivity @@ -61,9 +62,15 @@ class NavigationUiTest { val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build() /** - * Use a test activity to set the content on. + * Grant [android.Manifest.permission.POST_NOTIFICATIONS] permission. */ @get:Rule(order = 2) + val postNotificationsPermission = GrantPostNotificationsPermissionRule() + + /** + * Use a test activity to set the content on. + */ + @get:Rule(order = 3) val composeTestRule = createAndroidComposeRule() val userNewsResourceRepository = CompositeUserNewsResourceRepository( diff --git a/core/testing/src/main/java/com/google/samples/apps/nowinandroid/core/rules/GrantPostNotificationsPermissionRule.kt b/core/testing/src/main/java/com/google/samples/apps/nowinandroid/core/rules/GrantPostNotificationsPermissionRule.kt new file mode 100644 index 000000000..512399d85 --- /dev/null +++ b/core/testing/src/main/java/com/google/samples/apps/nowinandroid/core/rules/GrantPostNotificationsPermissionRule.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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.core.rules + +import android.Manifest.permission.POST_NOTIFICATIONS +import android.os.Build.VERSION.SDK_INT +import android.os.Build.VERSION_CODES.TIRAMISU +import androidx.test.rule.GrantPermissionRule.grant +import org.junit.rules.TestRule + +/** + * [TestRule] granting [POST_NOTIFICATIONS] permission if running on [SDK_INT] greater than [TIRAMISU]. + */ +class GrantPostNotificationsPermissionRule : + TestRule by if (SDK_INT >= TIRAMISU) grant(POST_NOTIFICATIONS) else grant() diff --git a/feature/foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt b/feature/foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt index b138cba06..8dcdef6be 100644 --- a/feature/foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt +++ b/feature/foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt @@ -16,9 +16,6 @@ package com.google.samples.apps.nowinandroid.feature.foryou -import android.Manifest -import android.os.Build.VERSION.SDK_INT -import android.os.Build.VERSION_CODES.TIRAMISU import androidx.activity.ComponentActivity import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.ui.test.assertHasClickAction @@ -31,8 +28,7 @@ import androidx.compose.ui.test.onFirst import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performScrollToNode -import androidx.test.rule.GrantPermissionRule -import androidx.test.rule.GrantPermissionRule.grant +import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPermissionRule import com.google.samples.apps.nowinandroid.core.testing.data.followableTopicTestData import com.google.samples.apps.nowinandroid.core.testing.data.userNewsResourcesTestData import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState @@ -41,15 +37,10 @@ import org.junit.Test class ForYouScreenTest { - @get:Rule - val permissionTestRule: GrantPermissionRule = - if (SDK_INT >= TIRAMISU) { - grant(Manifest.permission.POST_NOTIFICATIONS) - } else { - grant() - } + @get:Rule(order = 0) + val postNotificationsPermission = GrantPostNotificationsPermissionRule() - @get:Rule + @get:Rule(order = 1) val composeTestRule = createAndroidComposeRule() private val doneButtonMatcher by lazy { From 8c8c7611ce9461ca0df994d5ec81fcd18b3b2ee0 Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Sat, 27 May 2023 12:07:36 +0200 Subject: [PATCH 2/3] Update KotlinX Serialization to version 1.5.1 https://github.com/Kotlin/kotlinx.serialization/releases/tag/v1.5.1 > ### Bugfixes > - KeyValueSerializer: Fix missing call to endStructure() (#2272) > - ObjectSerializer: Respect sequential decoding (#2273) > - Fix value class encoding in various corner cases (#2242) > - Fix incorrect json decoding iterator's .hasNext() behavior on array-wrapped inputs (#2268) > - Fix memory leak caused by invalid KTypeWrapper's equals method (#2274) > - Fixed NoSuchMethodError when parsing a JSON stream on Java 8 (#2219) > - Fix MissingFieldException duplication (#2213) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0be000440..f2d071b56 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -42,7 +42,7 @@ junit4 = "4.13.2" kotlin = "1.8.20" kotlinxCoroutines = "1.6.4" kotlinxDatetime = "0.4.0" -kotlinxSerializationJson = "1.5.0" +kotlinxSerializationJson = "1.5.1" ksp = "1.8.20-1.0.11" lint = "30.3.1" okhttp = "4.10.0" From 97a55c9dd52168a6c352e19e4cdbcff1b860a31f Mon Sep 17 00:00:00 2001 From: Simon Marquis Date: Sat, 27 May 2023 20:51:41 +0200 Subject: [PATCH 3/3] Merge `AndroidCIWithGmd.yaml` into `Build.yaml` Add dependency on the `build` job, and add the same timeout of 55 minutes. Closes #761 --- .github/workflows/AndroidCIWithGmd.yaml | 49 ------------------------- .github/workflows/Build.yaml | 40 ++++++++++++++++++++ 2 files changed, 40 insertions(+), 49 deletions(-) delete mode 100644 .github/workflows/AndroidCIWithGmd.yaml diff --git a/.github/workflows/AndroidCIWithGmd.yaml b/.github/workflows/AndroidCIWithGmd.yaml deleted file mode 100644 index e10c49f9e..000000000 --- a/.github/workflows/AndroidCIWithGmd.yaml +++ /dev/null @@ -1,49 +0,0 @@ -name: Android CI with GMD - -on: - push: - branches: - - main - pull_request: - -jobs: - - android-ci: - runs-on: macos-12 - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Validate Gradle Wrapper - uses: gradle/wrapper-validation-action@v1 - - - 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@v3 - with: - distribution: 'zulu' - java-version: 17 - - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - - name: Setup Android SDK - uses: android-actions/setup-android@v2 - - - name: Build AndroidTest apps - run: ./gradlew packageDemoDebug packageDemoDebugAndroidTest - - - name: Run instrumented tests with GMD - run: ./gradlew cleanManagedDevices --unused-only && - ./gradlew ciDemoDebugAndroidTest -Dorg.gradle.workers.max=1 - -Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" -Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true - - - name: Upload test reports - if: success() || failure() - uses: actions/upload-artifact@v3 - with: - name: test-reports - path: '**/build/reports/androidTests' diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index a3b328dcb..f28a9a89c 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -5,6 +5,7 @@ on: branches: - main pull_request: + concurrency: group: build-${{ github.ref }} cancel-in-progress: true @@ -108,3 +109,42 @@ jobs: with: name: test-reports-${{ matrix.api-level }} path: '**/build/reports/androidTests' + + androidTest-GMD: + needs: build + runs-on: macOS-latest # enables hardware acceleration in the virtual machine + timeout-minutes: 55 + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - 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@v3 + with: + distribution: 'zulu' + java-version: 17 + + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 + + - name: Setup Android SDK + uses: android-actions/setup-android@v2 + + - name: Build AndroidTest apps + run: ./gradlew packageDemoDebug packageDemoDebugAndroidTest + + - name: Run instrumented tests with GMD + run: ./gradlew cleanManagedDevices --unused-only && + ./gradlew ciDemoDebugAndroidTest -Dorg.gradle.workers.max=1 + -Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" -Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true + + - name: Upload test reports + if: success() || failure() + uses: actions/upload-artifact@v3 + with: + name: test-reports + path: '**/build/reports/androidTests'