diff --git a/.github/workflows/android_emerge_snapshots.yml b/.github/workflows/android_emerge_snapshots.yml index 04db3390..0bf0044f 100644 --- a/.github/workflows/android_emerge_snapshots.yml +++ b/.github/workflows/android_emerge_snapshots.yml @@ -8,31 +8,7 @@ on: paths: [android/**] jobs: - emerge: - runs-on: ubuntu-latest - - defaults: - run: - working-directory: ./android - - steps: - - uses: actions/checkout@v6 - with: - ref: ${{ github.event.pull_request.head.sha }} - - name: Set up JDK 21 - uses: actions/setup-java@v5 - with: - java-version: "21" - distribution: "temurin" - - name: Setup Gradle build action - uses: gradle/actions/setup-gradle@v6 - - name: Emerge snapshots - run: ./gradlew :app:bundleDebug :app:emergeUploadSnapshotBundleDebug - env: - EMERGE_API_TOKEN: ${{ secrets.EMERGE_API_KEY }} - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_SENTRY_AUTH_TOKEN }} - - roborazzi: + paparazzi: runs-on: ubuntu-latest defaults: @@ -62,19 +38,21 @@ jobs: - name: Setup gems run: gem install emerge - - name: Generate Roborazzi snapshots - run: ./gradlew :app:recordRoborazziDebug :app:sentryUploadSnapshotsRelease + - name: Generate Paparazzi snapshots + run: ./gradlew :app:recordPaparazziDebug :app:sentryUploadSnapshotsDebug env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_SENTRY_AUTH_TOKEN }} + SENTRY_DONT_IGNORE_DEBUG: true - name: Upload snapshots env: EMERGE_API_TOKEN: ${{ secrets.EMERGE_API_KEY }} run: | emerge upload snapshots \ - --name "HackerNews Roborazzi" \ - --id "com.emerge.hackernews.roborazzi" \ + --name "Hacker News" \ + --id "com.emergetools.hackernews.debug" \ --repo-name "EmergeTools/hackernews" \ + --tag "snapshot" \ --debug \ - --client-library roborazzi \ + --client-library paparazzi \ --project-root . diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index ceda13f7..0638297f 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,5 +1,5 @@ -import io.github.takahirom.roborazzi.RoborazziExtension import io.sentry.android.gradle.tasks.SentryUploadSnapshotsTask +import org.gradle.api.tasks.testing.Test import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { @@ -10,7 +10,7 @@ plugins { alias(libs.plugins.kotlin.ksp) alias(libs.plugins.emerge) alias(libs.plugins.sentry) - alias(libs.plugins.roborazzi) + alias(libs.plugins.paparazzi) alias(libs.plugins.androidx.room) } @@ -56,6 +56,7 @@ android { getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) signingConfig = signingConfigs.getByName("debug") + enableUnitTestCoverage = false } create("playStoreRelease") { initWith(getByName("release")) @@ -99,10 +100,6 @@ ksp { } emerge { - snapshots { - tag.set("snapshot") - } - vcs { gitHub { // System.getenv override is for integration tests from the emerge-android repository @@ -127,16 +124,13 @@ sentry { updateSdkVariants.add("beta") } - debug = true -} - -afterEvaluate { - tasks.named("sentryUploadSnapshotsRelease") { - dependsOn(tasks.named("recordRoborazziDebug")) - snapshotsPath.set( - project.extensions.getByType().outputDir - ) + snapshots { + enabled = true + includePrivatePreviews = true + theme = "android:Theme.Transluscent.NoTitleBar" } + + debug = true } dependencies { @@ -171,18 +165,12 @@ dependencies { ksp(libs.androidx.room.compiler) testImplementation(libs.junit) - testImplementation(libs.robolectric) - testImplementation(libs.roborazzi) - testImplementation(libs.roborazzi.compose) - testImplementation(libs.roborazzi.rule) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(platform(libs.androidx.compose.bom)) androidTestImplementation(libs.androidx.ui.test.junit4) - androidTestImplementation(libs.emerge.snapshots) debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) - } diff --git a/android/app/src/test/kotlin/BookmarksScreenComposeTest.kt b/android/app/src/test/kotlin/BookmarksScreenComposeTest.kt deleted file mode 100644 index 655e76df..00000000 --- a/android/app/src/test/kotlin/BookmarksScreenComposeTest.kt +++ /dev/null @@ -1,71 +0,0 @@ -import androidx.compose.ui.test.junit4.createComposeRule -import androidx.compose.ui.test.onRoot -import com.emergetools.hackernews.features.bookmarks.BookmarksScreen -import com.emergetools.hackernews.features.bookmarks.BookmarksState -import com.emergetools.hackernews.features.stories.StoryItem -import com.emergetools.hackernews.ui.theme.HackerNewsTheme -import com.github.takahirom.roborazzi.captureRoboImage -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.GraphicsMode -import java.time.Instant - -@GraphicsMode(GraphicsMode.Mode.NATIVE) -@RunWith(RobolectricTestRunner::class) -class BookmarksScreenComposeTest { - - @get:Rule - val composeRule = createComposeRule() - - @Test - fun roborazziTest() { - composeRule.setContent { - HackerNewsTheme { - BookmarksScreen( - state = BookmarksState( - bookmarks = listOf( - StoryItem.Content( - id = 1L, - title = "Show HN: A new Android client", - author = "heyrikin", - score = 10, - commentCount = 45, - epochTimestamp = Instant.now().minusSeconds(60 * 60 * 3).epochSecond, - bookmarked = true, - url = "" - ), - StoryItem.Content( - id = 2L, - title = "Can we stop the decline of monarch butterflies and other pollinators?", - author = "rbro112", - score = 40, - commentCount = 23, - epochTimestamp = Instant.now().minusSeconds(60 * 60 * 2).epochSecond, - bookmarked = true, - url = "" - ), - StoryItem.Content( - id = 3L, - title = "Andy Warhol's lost Amiga art found", - author = "telkins", - score = 332, - commentCount = 103, - epochTimestamp = Instant.now().minusSeconds(60 * 60 * 7).epochSecond, - bookmarked = true, - url = "" - ), - ) - ), - actions = {}, - navigator = {} - ) - } - } - - composeRule - .onRoot() - .captureRoboImage() - } -} diff --git a/android/app/src/test/kotlin/StoryRowComposeTest.kt b/android/app/src/test/kotlin/StoryRowComposeTest.kt deleted file mode 100644 index 19c0e17f..00000000 --- a/android/app/src/test/kotlin/StoryRowComposeTest.kt +++ /dev/null @@ -1,37 +0,0 @@ -import androidx.compose.ui.test.junit4.createComposeRule -import androidx.compose.ui.test.onRoot -import com.emergetools.hackernews.features.stories.StoryItem -import com.emergetools.hackernews.ui.components.StoryRow -import com.emergetools.hackernews.ui.theme.HackerNewsTheme -import com.github.takahirom.roborazzi.captureRoboImage -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.GraphicsMode - -@GraphicsMode(GraphicsMode.Mode.NATIVE) -@RunWith(RobolectricTestRunner::class) -class StoryRowComposeTest { - - @get:Rule - val composeRule = createComposeRule() - - @Test - fun roborazziTest() { - composeRule.setContent { - HackerNewsTheme { - StoryRow( - item = StoryItem.Loading(id = 1L), - onClick = {}, - onBookmark = {}, - onCommentClicked = {}, - ) - } - } - - composeRule - .onRoot() - .captureRoboImage() - } -} diff --git a/android/build.gradle.kts b/android/build.gradle.kts index 00cff7e5..f12a76f9 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -5,7 +5,7 @@ plugins { alias(libs.plugins.compose.compiler) apply false alias(libs.plugins.kotlin.serialization) apply false alias(libs.plugins.kotlin.ksp) apply false - alias(libs.plugins.roborazzi) apply false + alias(libs.plugins.paparazzi) apply false alias(libs.plugins.androidx.room) apply false alias(libs.plugins.sentry) apply false alias(libs.plugins.android.test) apply false diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index cecf014c..a894a1a7 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -5,8 +5,6 @@ ksp = "2.3.6" coreKtx = "1.18.0" junit = "4.13.2" junitVersion = "1.1.5" # This is to match Compose's version -robolectric = "4.16.1" -roborazzi = "1.59.0" espressoCore = "3.5.0" # This is to match Compose's version lifecycleRuntimeKtx = "2.10.0" activityCompose = "1.13.0" @@ -17,8 +15,7 @@ viewmodel = "2.10.0" navigation = "2.9.7" browser = "1.9.0" emergePlugin = "4.4.0" -emergeSnapshots = "1.5.1" -sentry = "6.3.0" +sentry = "6.4.0" shapes = "1.1.0" datastore = "1.2.1" room = "2.8.4" @@ -61,14 +58,9 @@ retrofit-kotlinx-serialization = { group = "com.squareup.retrofit2", name = "con kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" } jsoup = { group = "org.jsoup", name = "jsoup", version.ref = "jsoup" } -emerge-snapshots = { group = "com.emergetools.snapshots", name = "snapshots", version.ref = "emergeSnapshots" } -emerge-snapshots-runtime = { group = "com.emergetools.snapshots", name = "snapshots-runtime", version.ref = "emergeSnapshots" } +emerge-snapshots-runtime = { group = "com.emergetools.snapshots", name = "snapshots-runtime", version = "1.5.1" } junit = { group = "junit", name = "junit", version.ref = "junit" } -robolectric = { group = "org.robolectric", name = "robolectric", version.ref = "robolectric" } -roborazzi = { group = "io.github.takahirom.roborazzi", name = "roborazzi", version.ref = "roborazzi" } -roborazzi-compose = { group = "io.github.takahirom.roborazzi", name = "roborazzi-compose", version.ref = "roborazzi" } -roborazzi-rule = { group = "io.github.takahirom.roborazzi", name = "roborazzi-junit-rule", version.ref = "roborazzi" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } androidx-ui-test-junit4-android = { group = "androidx.compose.ui", name = "ui-test-junit4-android", version.ref = "uiTestJunit4Android" } @@ -82,8 +74,8 @@ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = " kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } kotlin-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } emerge = { id = "com.emergetools.android", version.ref = "emergePlugin" } +paparazzi = { id = "app.cash.paparazzi", version = "2.0.0-alpha04" } sentry = { id = "io.sentry.android.gradle", version.ref = "sentry" } -roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } androidx-room = { id = "androidx.room", version.ref = "room" } android-test = { id = "com.android.test", version.ref = "agp" } diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar index 1b33c55b..8bdaf60c 100644 Binary files a/android/gradle/wrapper/gradle-wrapper.jar and b/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index aaaabb3c..2e111328 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/android/gradlew b/android/gradlew index 23d15a93..adff685a 100755 --- a/android/gradlew +++ b/android/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat index 5eed7ee8..e509b2dd 100644 --- a/android/gradlew.bat +++ b/android/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell