diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
index 257b71e1..f2f7394e 100644
--- a/.github/workflows/pull_request.yml
+++ b/.github/workflows/pull_request.yml
@@ -21,16 +21,13 @@ jobs:
with:
arguments: test --stacktrace
-# - name: Run instrumentation tests
-# uses: reactivecircus/android-emulator-runner@08b092e904025fada32a01b711af1e7ff7b7a4a3
-# with:
-# api-level: 23
-# target: default
-# script: |
-# adb shell settings put global animator_duration_scale 0
-# adb shell settings put global transition_animation_scale 0
-# adb shell settings put global window_animation_scale 0
-# ./gradlew :app:connectedDebugAndroidTest
+ - name: Run instrumentation tests
+ uses: reactivecircus/android-emulator-runner@08b092e904025fada32a01b711af1e7ff7b7a4a3
+ with:
+ api-level: 30
+ target: google_apis
+ script: |
+ ./gradlew :app:connectedDebugAndroidTest
- name: (Fail-only) upload test report
if: failure()
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index a2743738..41aece73 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -3,6 +3,7 @@ plugins {
kotlin("android")
kotlin("kapt")
id("dagger.hilt.android.plugin")
+ id("shot")
`versioning-plugin`
`lobsters-plugin`
`core-library-desugaring`
@@ -18,7 +19,7 @@ repositories {
android {
defaultConfig {
applicationId = "dev.msfjarvis.lobsters"
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ testInstrumentationRunner = "com.karumi.shot.ShotTestRunner"
}
buildFeatures.compose = true
diff --git a/app/screenshots/debug/dev.msfjarvis.lobsters.ui.navigation.LobstersBottomNavTest_bottomNavIsRenderedCorrectlyOnScreen.png b/app/screenshots/debug/dev.msfjarvis.lobsters.ui.navigation.LobstersBottomNavTest_bottomNavIsRenderedCorrectlyOnScreen.png
new file mode 100644
index 00000000..a40d7ce0
Binary files /dev/null and b/app/screenshots/debug/dev.msfjarvis.lobsters.ui.navigation.LobstersBottomNavTest_bottomNavIsRenderedCorrectlyOnScreen.png differ
diff --git a/app/screenshots/debug/dev.msfjarvis.lobsters.ui.navigation.LobstersBottomNavTest_bottomNavUpdatesCorrectly.png b/app/screenshots/debug/dev.msfjarvis.lobsters.ui.navigation.LobstersBottomNavTest_bottomNavUpdatesCorrectly.png
new file mode 100644
index 00000000..64e78d3a
Binary files /dev/null and b/app/screenshots/debug/dev.msfjarvis.lobsters.ui.navigation.LobstersBottomNavTest_bottomNavUpdatesCorrectly.png differ
diff --git a/app/screenshots/debug/dev.msfjarvis.lobsters.ui.posts.LobstersItemTest_postsAreRenderedCorrectlyOnScreen.png b/app/screenshots/debug/dev.msfjarvis.lobsters.ui.posts.LobstersItemTest_postsAreRenderedCorrectlyOnScreen.png
new file mode 100644
index 00000000..bc13682e
Binary files /dev/null and b/app/screenshots/debug/dev.msfjarvis.lobsters.ui.posts.LobstersItemTest_postsAreRenderedCorrectlyOnScreen.png differ
diff --git a/app/src/androidTest/AndroidManifest.xml b/app/src/androidTest/AndroidManifest.xml
new file mode 100644
index 00000000..a82a05b3
--- /dev/null
+++ b/app/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/app/src/androidTest/java/dev/msfjarvis/lobsters/ui/Theme.kt b/app/src/androidTest/java/dev/msfjarvis/lobsters/ui/Theme.kt
new file mode 100644
index 00000000..304bb604
--- /dev/null
+++ b/app/src/androidTest/java/dev/msfjarvis/lobsters/ui/Theme.kt
@@ -0,0 +1,22 @@
+package dev.msfjarvis.lobsters.ui
+
+import androidx.compose.material.MaterialTheme
+import androidx.compose.runtime.Composable
+import dev.msfjarvis.lobsters.ui.theme.darkColors
+import dev.msfjarvis.lobsters.ui.theme.lightColors
+
+@Composable
+fun LightTestTheme(children: @Composable () -> Unit) {
+ MaterialTheme(
+ colors = lightColors,
+ content = children,
+ )
+}
+
+@Composable
+fun DarkTestTheme(children: @Composable () -> Unit) {
+ MaterialTheme(
+ colors = darkColors,
+ content = children,
+ )
+}
diff --git a/app/src/androidTest/java/dev/msfjarvis/lobsters/ui/navigation/LobstersBottomNavTest.kt b/app/src/androidTest/java/dev/msfjarvis/lobsters/ui/navigation/LobstersBottomNavTest.kt
new file mode 100644
index 00000000..6860b3db
--- /dev/null
+++ b/app/src/androidTest/java/dev/msfjarvis/lobsters/ui/navigation/LobstersBottomNavTest.kt
@@ -0,0 +1,64 @@
+package dev.msfjarvis.lobsters.ui.navigation
+
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.graphics.asAndroidBitmap
+import androidx.compose.ui.test.assertHasClickAction
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onRoot
+import androidx.compose.ui.test.performClick
+import com.karumi.shot.ScreenshotTest
+import dev.msfjarvis.lobsters.ui.DarkTestTheme
+import dev.msfjarvis.lobsters.ui.main.LobstersBottomNav
+import dev.msfjarvis.lobsters.ui.theme.LobstersTheme
+import org.junit.Rule
+import org.junit.Test
+
+class LobstersBottomNavTest : ScreenshotTest {
+
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ @Test
+ fun bottomNavIsRenderedCorrectlyOnScreen() {
+ composeTestRule.setContent {
+ DarkTestTheme {
+ LobstersBottomNav(
+ currentDestination = Destination.startDestination,
+ navigateToDestination = { /*TODO*/ },
+ jumpToIndex = { /*TODO*/ }
+ )
+ }
+ }
+
+ compareScreenshot(composeTestRule.onRoot().captureToImage().asAndroidBitmap())
+ }
+
+ @Test
+ fun bottomNavUpdatesCorrectly() {
+ composeTestRule.setContent {
+ DarkTestTheme {
+ var destination by remember { mutableStateOf(Destination.startDestination) }
+
+ LobstersBottomNav(
+ currentDestination = destination,
+ navigateToDestination = { newDestination -> destination = newDestination },
+ jumpToIndex = { /*TODO*/ }
+ )
+ }
+ }
+
+ selectNode(Destination.Saved.name)
+
+ compareScreenshot(composeTestRule.onRoot().captureToImage().asAndroidBitmap())
+ }
+
+ private fun selectNode(testTag: String) = composeTestRule
+ .onNodeWithTag(testTag)
+ .assertHasClickAction()
+ .performClick()
+}
diff --git a/app/src/androidTest/java/dev/msfjarvis/lobsters/ui/posts/LobstersItemTest.kt b/app/src/androidTest/java/dev/msfjarvis/lobsters/ui/posts/LobstersItemTest.kt
new file mode 100644
index 00000000..f14380eb
--- /dev/null
+++ b/app/src/androidTest/java/dev/msfjarvis/lobsters/ui/posts/LobstersItemTest.kt
@@ -0,0 +1,32 @@
+package dev.msfjarvis.lobsters.ui.posts
+
+import androidx.compose.ui.graphics.asAndroidBitmap
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onRoot
+import com.karumi.shot.ScreenshotTest
+import dev.msfjarvis.lobsters.ui.DarkTestTheme
+import org.junit.Rule
+import org.junit.Test
+
+class LobstersItemTest : ScreenshotTest {
+
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ @Test
+ fun postsAreRenderedCorrectlyOnScreen() {
+ composeTestRule.setContent {
+ DarkTestTheme {
+ LobstersItem(
+ post = TEST_POST,
+ onClick = { /*TODO*/ },
+ onLongClick = { /*TODO*/ },
+ onSaveButtonClick = { /*TODO*/ },
+ isSaved = true,
+ )
+ }
+ }
+ compareScreenshot(composeTestRule.onRoot().captureToImage().asAndroidBitmap())
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 53f2e72d..0e9e7dbf 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,6 +1,7 @@
+ package="dev.msfjarvis.lobsters"
+ android:sharedUserId="${applicationId}.uid">
diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/main/LobstersApp.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/main/LobstersApp.kt
index 5453ee0a..958108ab 100644
--- a/app/src/main/java/dev/msfjarvis/lobsters/ui/main/LobstersApp.kt
+++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/main/LobstersApp.kt
@@ -100,6 +100,7 @@ fun LobstersBottomNav(
},
label = { Text(stringResource(id = screen.labelRes)) },
selected = currentDestination == screen,
+ modifier = Modifier.testTag(screen.name),
alwaysShowLabel = false,
onClick = {
if (screen != currentDestination) {
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index ac32817f..fcf191cd 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -34,5 +34,6 @@ dependencies {
implementation(Plugins.jsemver)
implementation(Plugins.lintModel)
implementation(Plugins.kotlin)
+ implementation(Plugins.shot)
implementation(Plugins.sqldelight)
}
diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt
index 6849d32a..d2127563 100644
--- a/buildSrc/src/main/java/Dependencies.kt
+++ b/buildSrc/src/main/java/Dependencies.kt
@@ -11,6 +11,7 @@ object Plugins {
const val hilt = "com.google.dagger:hilt-android-gradle-plugin:${DAGGER_HILT_VERSION}"
const val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.30"
const val jsemver = "com.github.zafarkhaja:java-semver:0.9.0"
+ const val shot = "com.karumi:shot:5.8.0"
const val sqldelight = "com.squareup.sqldelight:gradle-plugin:1.4.4"
}