Skip to content

Commit f71febf

Browse files
authored
Add roborazzi snapshots (#231)
1 parent 4b0f6f9 commit f71febf

File tree

7 files changed

+181
-4
lines changed

7 files changed

+181
-4
lines changed

.github/workflows/android_emerge_snapshots.yml

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
paths: [ android/** ]
99

1010
jobs:
11-
build:
11+
emerge:
1212
runs-on: ubuntu-latest
1313

1414
defaults:
@@ -30,3 +30,44 @@ jobs:
3030
EMERGE_API_TOKEN: ${{ secrets.EMERGE_API_KEY }}
3131
PR_SHA: ${{ github.event.pull_request.head.sha }}
3232
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
33+
34+
roborazzi:
35+
runs-on: ubuntu-latest
36+
37+
defaults:
38+
run:
39+
working-directory: ./android
40+
41+
steps:
42+
- uses: actions/checkout@v4
43+
with:
44+
ref: ${{ github.event.pull_request.head.sha }}
45+
46+
- name: Set up JDK 17
47+
uses: actions/setup-java@v4
48+
with:
49+
java-version: '17'
50+
distribution: 'adopt'
51+
52+
- name: Ruby setup
53+
uses: ruby/setup-ruby@v1
54+
with:
55+
ruby-version: 3.2.5
56+
bundler-cache: true
57+
58+
- name: Setup gems
59+
run: gem install emerge
60+
61+
- name: Generate Roborazzi snapshots
62+
run: ./gradlew :app:recordRoborazziDebug
63+
64+
- name: Upload snapshots
65+
env:
66+
EMERGE_API_TOKEN: ${{ secrets.EMERGE_API_KEY }}
67+
run: |
68+
emerge upload snapshots \
69+
--name "HackerNews Swift-Snapshot-Testing" \
70+
--id "com.emerge.hackernews.roborazzi" \
71+
--repo-name "EmergeTools/hackernews" \
72+
--debug \
73+
app/build/outputs/roborazzi

android/app/build.gradle.kts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ plugins {
66
alias(libs.plugins.kotlin.ksp)
77
alias(libs.plugins.emerge)
88
alias(libs.plugins.sentry)
9+
alias(libs.plugins.roborazzi)
910
}
1011

1112
val runningEnv: String? = System.getenv("RUNNING_ENV")
@@ -81,6 +82,11 @@ android {
8182
excludes += "/META-INF/{AL2.0,LGPL2.1}"
8283
}
8384
}
85+
testOptions {
86+
unitTests {
87+
isIncludeAndroidResources = true
88+
}
89+
}
8490
}
8591

8692
composeCompiler {
@@ -145,9 +151,15 @@ dependencies {
145151

146152
implementation(libs.androidx.room)
147153
implementation(libs.androidx.room.ktx)
154+
implementation(libs.androidx.ui.test.junit4.android)
148155
ksp(libs.androidx.room.compiler)
149156

150157
testImplementation(libs.junit)
158+
testImplementation(libs.robolectric)
159+
testImplementation(libs.roborazzi)
160+
testImplementation(libs.roborazzi.compose)
161+
testImplementation(libs.roborazzi.rule)
162+
151163
androidTestImplementation(libs.androidx.junit)
152164
androidTestImplementation(libs.androidx.espresso.core)
153165
androidTestImplementation(platform(libs.androidx.compose.bom))

android/app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
<category android:name="android.intent.category.LAUNCHER" />
3131
</intent-filter>
3232
</activity>
33+
34+
<activity android:name="androidx.activity.ComponentActivity" android:exported="true" />
3335
</application>
3436

35-
</manifest>
37+
</manifest>
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.github.takahirom.roborazzi.usage.examples
2+
3+
import androidx.compose.ui.test.junit4.createComposeRule
4+
import androidx.compose.ui.test.onRoot
5+
import com.emergetools.hackernews.features.bookmarks.BookmarksScreen
6+
import com.emergetools.hackernews.features.bookmarks.BookmarksState
7+
import com.emergetools.hackernews.features.stories.StoryItem
8+
import com.emergetools.hackernews.ui.theme.HackerNewsTheme
9+
import com.github.takahirom.roborazzi.captureRoboImage
10+
import org.junit.Rule
11+
import org.junit.Test
12+
import org.junit.runner.RunWith
13+
import org.robolectric.RobolectricTestRunner
14+
import org.robolectric.annotation.GraphicsMode
15+
import java.time.Instant
16+
17+
@GraphicsMode(GraphicsMode.Mode.NATIVE)
18+
@RunWith(RobolectricTestRunner::class)
19+
class BookmarksScreenComposeTest {
20+
21+
@get:Rule
22+
val composeRule = createComposeRule()
23+
24+
@Test
25+
fun roborazziTest() {
26+
composeRule.setContent {
27+
HackerNewsTheme {
28+
BookmarksScreen(
29+
state = BookmarksState(
30+
bookmarks = listOf(
31+
StoryItem.Content(
32+
id = 1L,
33+
title = "Show HN: A new Android client",
34+
author = "heyrikin",
35+
score = 10,
36+
commentCount = 45,
37+
epochTimestamp = Instant.now().minusSeconds(60 * 60 * 3).epochSecond,
38+
bookmarked = true,
39+
url = ""
40+
),
41+
StoryItem.Content(
42+
id = 2L,
43+
title = "Can we stop the decline of monarch butterflies and other pollinators?",
44+
author = "rbro112",
45+
score = 40,
46+
commentCount = 23,
47+
epochTimestamp = Instant.now().minusSeconds(60 * 60 * 2).epochSecond,
48+
bookmarked = true,
49+
url = ""
50+
),
51+
StoryItem.Content(
52+
id = 3L,
53+
title = "Andy Warhol's lost Amiga art found",
54+
author = "telkins",
55+
score = 332,
56+
commentCount = 103,
57+
epochTimestamp = Instant.now().minusSeconds(60 * 60 * 7).epochSecond,
58+
bookmarked = true,
59+
url = ""
60+
),
61+
)
62+
),
63+
actions = {},
64+
navigator = {}
65+
)
66+
}
67+
}
68+
69+
composeRule
70+
.onRoot()
71+
.captureRoboImage()
72+
}
73+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.github.takahirom.roborazzi.usage.examples
2+
3+
import androidx.compose.ui.test.junit4.createComposeRule
4+
import androidx.compose.ui.test.onRoot
5+
import com.emergetools.hackernews.features.stories.StoryItem
6+
import com.emergetools.hackernews.ui.components.StoryRow
7+
import com.emergetools.hackernews.ui.theme.HackerNewsTheme
8+
import com.github.takahirom.roborazzi.captureRoboImage
9+
import org.junit.Rule
10+
import org.junit.Test
11+
import org.junit.runner.RunWith
12+
import org.robolectric.RobolectricTestRunner
13+
import org.robolectric.annotation.GraphicsMode
14+
15+
@GraphicsMode(GraphicsMode.Mode.NATIVE)
16+
@RunWith(RobolectricTestRunner::class)
17+
class StoryRowComposeTest {
18+
19+
@get:Rule
20+
val composeRule = createComposeRule()
21+
22+
@Test
23+
fun roborazziTest() {
24+
composeRule.setContent {
25+
HackerNewsTheme {
26+
StoryRow(
27+
item = StoryItem.Loading(id = 1L),
28+
onClick = {},
29+
onBookmark = {},
30+
onCommentClicked = {},
31+
)
32+
}
33+
}
34+
35+
composeRule
36+
.onRoot()
37+
.captureRoboImage()
38+
}
39+
}

android/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ plugins {
55
alias(libs.plugins.compose.compiler) apply false
66
alias(libs.plugins.kotlin.serialization) apply false
77
alias(libs.plugins.kotlin.ksp) apply false
8+
alias(libs.plugins.roborazzi) apply false
89
}

android/gradle/libs.versions.toml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ kotlin = "2.0.21"
44
ksp = "2.0.21-1.0.28"
55
coreKtx = "1.13.1"
66
junit = "4.13.2"
7-
junitVersion = "1.2.1"
8-
espressoCore = "3.6.1"
7+
junitVersion = "1.1.5" # This is to match Compose's version
8+
robolectric = "4.14"
9+
roborazzi = "1.8.0-alpha-5"
10+
espressoCore = "3.5.0" # This is to match Compose's version
911
lifecycleRuntimeKtx = "2.8.7"
1012
activityCompose = "1.9.3"
1113
retrofit = "2.11.0"
@@ -25,6 +27,7 @@ room = "2.6.1"
2527
jsoup = "1.18.1"
2628
extendedspans = "1.4.0"
2729
composeBom = "2024.11.00"
30+
uiTestJunit4Android = "1.7.5"
2831

2932
[libraries]
3033
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -62,8 +65,13 @@ emerge-reaper = { group = "com.emergetools.reaper", name = "reaper", version.ref
6265
emerge-distribution = { group = "com.emergetools.distribution", name = "distribution", version.ref = "emergeDistribution" }
6366

6467
junit = { group = "junit", name = "junit", version.ref = "junit" }
68+
robolectric = { group = "org.robolectric", name = "robolectric", version.ref = "robolectric" }
69+
roborazzi = { group = "io.github.takahirom.roborazzi", name = "roborazzi", version.ref = "roborazzi" }
70+
roborazzi-compose = { group = "io.github.takahirom.roborazzi", name = "roborazzi-compose", version.ref = "roborazzi" }
71+
roborazzi-rule = { group = "io.github.takahirom.roborazzi", name = "roborazzi-junit-rule", version.ref = "roborazzi" }
6572
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
6673
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
74+
androidx-ui-test-junit4-android = { group = "androidx.compose.ui", name = "ui-test-junit4-android", version.ref = "uiTestJunit4Android" }
6775

6876
[plugins]
6977
android-application = { id = "com.android.application", version.ref = "agp" }
@@ -73,5 +81,6 @@ kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", versi
7381
kotlin-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
7482
emerge = { id = "com.emergetools.android", version.ref = "emergePlugin" }
7583
sentry = { id = "io.sentry.android.gradle", version.ref = "sentry" }
84+
roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" }
7685

7786

0 commit comments

Comments
 (0)