diff --git a/core/screenshot-testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/ScreenshotHelper.kt b/core/screenshot-testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/ScreenshotHelper.kt index 468fff8df..0715f6337 100644 --- a/core/screenshot-testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/ScreenshotHelper.kt +++ b/core/screenshot-testing/src/main/kotlin/com/google/samples/apps/nowinandroid/core/testing/util/ScreenshotHelper.kt @@ -28,10 +28,12 @@ import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.onRoot import androidx.test.ext.junit.rules.ActivityScenarioRule +import com.github.takahirom.roborazzi.ExperimentalRoborazziApi import com.github.takahirom.roborazzi.RoborazziOptions import com.github.takahirom.roborazzi.RoborazziOptions.CompareOptions import com.github.takahirom.roborazzi.RoborazziOptions.RecordOptions import com.github.takahirom.roborazzi.captureRoboImage +import com.github.takahirom.roborazzi.captureScreenRoboImage import com.google.accompanist.testharness.TestHarness import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme import org.robolectric.RuntimeEnvironment @@ -49,6 +51,7 @@ enum class DefaultTestDevices(val description: String, val spec: String) { FOLDABLE("foldable", "spec:shape=Normal,width=673,height=841,unit=dp,dpi=480"), TABLET("tablet", "spec:shape=Normal,width=1280,height=800,unit=dp,dpi=480"), } + fun AndroidComposeTestRule, A>.captureMultiDevice( screenshotName: String, body: @Composable () -> Unit, @@ -87,6 +90,25 @@ fun AndroidComposeTestRule, A>.c ) } +@OptIn(ExperimentalRoborazziApi::class) +fun AndroidComposeTestRule, A>.captureDialog( + screenshotName: String, + body: @Composable () -> Unit, +) { + this.activity.setContent { + CompositionLocalProvider( + LocalInspectionMode provides true, + ) { + body() + } + } + + captureScreenRoboImage( + "src/test/screenshots/$screenshotName.png", + roborazziOptions = DefaultRoborazziOptions, + ) +} + /** * Takes six screenshots combining light/dark and default/Android themes and whether dynamic color * is enabled. diff --git a/feature/settings/src/test/kotlin/com/google/samples/apps/nowinandroid/feature/settings/SettingsDialogScreenshotTests.kt b/feature/settings/src/test/kotlin/com/google/samples/apps/nowinandroid/feature/settings/SettingsDialogScreenshotTests.kt new file mode 100644 index 000000000..7cedeebef --- /dev/null +++ b/feature/settings/src/test/kotlin/com/google/samples/apps/nowinandroid/feature/settings/SettingsDialogScreenshotTests.kt @@ -0,0 +1,175 @@ +/* + * 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.feature.settings + +import androidx.activity.ComponentActivity +import androidx.compose.runtime.Composable +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme +import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.DARK +import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.LIGHT +import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID +import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.DEFAULT +import com.google.samples.apps.nowinandroid.core.testing.util.captureDialog +import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Success +import dagger.hilt.android.testing.HiltTestApplication +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode +import org.robolectric.annotation.LooperMode +@RunWith(RobolectricTestRunner::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +@LooperMode(LooperMode.Mode.PAUSED) +@Config(application = HiltTestApplication::class, qualifiers = "w360dp-h640dp-xhdpi") +class SettingsDialogScreenshotTests { + + @get:Rule + val composeTestRule = createAndroidComposeRule() + + private val defaultSettingsUiState = Success( + UserEditableSettings( + brand = DEFAULT, + darkThemeConfig = LIGHT, + useDynamicColor = false, + ), + ) + + @Test + fun settingsDialogLoading() { + composeTestRule.captureDialog("SettingsDialogLoading") { + SettingsDialogDefaultTheme( + settingsUiState = SettingsUiState.Loading, + ) + } + } + + @Test + fun settingsDialogLoadingDark() { + composeTestRule.captureDialog("SettingsDialogLoadingDark") { + SettingsDialogDefaultTheme( + darkMode = true, + settingsUiState = SettingsUiState.Loading, + ) + } + } + + @Test + fun settingsDialogDefaultTheme() { + composeTestRule.captureDialog("SettingsDialogDefaultTheme") { + SettingsDialogDefaultTheme() + } + } + + @Test + fun settingsDialogDefaultThemeDark() { + composeTestRule.captureDialog("SettingsDialogDefaultThemeDark") { + SettingsDialogDefaultTheme( + darkMode = true, + settingsUiState = Success( + defaultSettingsUiState.settings.copy( + darkThemeConfig = DARK, + ), + ), + ) + } + } + + @Test + fun settingsDialogDynamicColor() { + composeTestRule.captureDialog("SettingsDialogDynamicColor") { + SettingsDialogDefaultTheme( + disableDynamicTheming = false, + settingsUiState = Success( + defaultSettingsUiState.settings.copy( + useDynamicColor = true, + ), + ), + ) + } + } + + @Test + fun settingsDialogDynamicColorDark() { + composeTestRule.captureDialog("SettingsDialogDynamicColorDark") { + SettingsDialogDefaultTheme( + darkMode = true, + disableDynamicTheming = false, + settingsUiState = Success( + defaultSettingsUiState.settings.copy( + darkThemeConfig = DARK, + useDynamicColor = true, + ), + ), + ) + } + } + + @Test + fun settingsDialogAndroidTheme() { + composeTestRule.captureDialog("SettingsDialogAndroidTheme") { + SettingsDialogDefaultTheme( + androidTheme = true, + settingsUiState = Success( + defaultSettingsUiState.settings.copy( + brand = ANDROID, + ), + ), + ) + } + } + + @Test + fun settingsDialogAndroidThemeDark() { + composeTestRule.captureDialog("SettingsDialogAndroidThemeDark") { + SettingsDialogDefaultTheme( + darkMode = true, + androidTheme = true, + settingsUiState = Success( + defaultSettingsUiState.settings.copy( + darkThemeConfig = DARK, + brand = ANDROID, + ), + ), + ) + } + } + + @Composable + private fun SettingsDialogDefaultTheme( + darkMode: Boolean = false, + androidTheme: Boolean = false, + disableDynamicTheming: Boolean = true, + settingsUiState: SettingsUiState = defaultSettingsUiState, + ) { + NiaTheme( + darkTheme = darkMode, + androidTheme = androidTheme, + disableDynamicTheming = disableDynamicTheming, + ) { + SettingsDialog( + onDismiss = {}, + settingsUiState = settingsUiState, + onChangeThemeBrand = {}, + onChangeDynamicColorPreference = {}, + onChangeDarkThemeConfig = {}, + ) + } + } +} diff --git a/feature/settings/src/test/screenshots/SettingsDialogAndroidTheme.png b/feature/settings/src/test/screenshots/SettingsDialogAndroidTheme.png new file mode 100644 index 000000000..9f55005a4 Binary files /dev/null and b/feature/settings/src/test/screenshots/SettingsDialogAndroidTheme.png differ diff --git a/feature/settings/src/test/screenshots/SettingsDialogAndroidThemeDark.png b/feature/settings/src/test/screenshots/SettingsDialogAndroidThemeDark.png new file mode 100644 index 000000000..ca1669974 Binary files /dev/null and b/feature/settings/src/test/screenshots/SettingsDialogAndroidThemeDark.png differ diff --git a/feature/settings/src/test/screenshots/SettingsDialogDefaultTheme.png b/feature/settings/src/test/screenshots/SettingsDialogDefaultTheme.png new file mode 100644 index 000000000..6b5ba36fc Binary files /dev/null and b/feature/settings/src/test/screenshots/SettingsDialogDefaultTheme.png differ diff --git a/feature/settings/src/test/screenshots/SettingsDialogDefaultThemeDark.png b/feature/settings/src/test/screenshots/SettingsDialogDefaultThemeDark.png new file mode 100644 index 000000000..3f11be3da Binary files /dev/null and b/feature/settings/src/test/screenshots/SettingsDialogDefaultThemeDark.png differ diff --git a/feature/settings/src/test/screenshots/SettingsDialogDynamicColor.png b/feature/settings/src/test/screenshots/SettingsDialogDynamicColor.png new file mode 100644 index 000000000..a6d4f5c9f Binary files /dev/null and b/feature/settings/src/test/screenshots/SettingsDialogDynamicColor.png differ diff --git a/feature/settings/src/test/screenshots/SettingsDialogDynamicColorDark.png b/feature/settings/src/test/screenshots/SettingsDialogDynamicColorDark.png new file mode 100644 index 000000000..9fbc8f6b7 Binary files /dev/null and b/feature/settings/src/test/screenshots/SettingsDialogDynamicColorDark.png differ diff --git a/feature/settings/src/test/screenshots/SettingsDialogLoading.png b/feature/settings/src/test/screenshots/SettingsDialogLoading.png new file mode 100644 index 000000000..8be44356c Binary files /dev/null and b/feature/settings/src/test/screenshots/SettingsDialogLoading.png differ diff --git a/feature/settings/src/test/screenshots/SettingsDialogLoadingDark.png b/feature/settings/src/test/screenshots/SettingsDialogLoadingDark.png new file mode 100644 index 000000000..ada3c6030 Binary files /dev/null and b/feature/settings/src/test/screenshots/SettingsDialogLoadingDark.png differ