pull/1367/merge
yongsuk 1 year ago committed by GitHub
commit a24d6db161
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -41,6 +41,8 @@ class AndroidFeatureConventionPlugin : Plugin<Project> {
dependencies {
add("implementation", project(":core:ui"))
add("implementation", project(":core:designsystem"))
add("testImplementation", project(":core:testing"))
add("androidTestImplementation", project(":core:testing"))
add("implementation", libs.findLibrary("androidx.hilt.navigation.compose").get())
add("implementation", libs.findLibrary("androidx.lifecycle.runtimeCompose").get())

@ -45,8 +45,6 @@ dependencies {
testImplementation(libs.androidx.compose.ui.testManifest)
testImplementation(libs.hilt.android.testing)
testImplementation(libs.robolectric)
testImplementation(libs.roborazzi)
testImplementation(projects.core.screenshotTesting)
testImplementation(projects.core.testing)

@ -25,10 +25,9 @@ android {
dependencies {
api(libs.roborazzi)
implementation(libs.androidx.compose.ui.test)
api(libs.robolectric)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.compose.ui.test)
implementation(libs.robolectric)
implementation(projects.core.common)
implementation(projects.core.designsystem)
}

@ -28,6 +28,7 @@ import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.test.DarkMode
import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onRoot
import androidx.test.ext.junit.rules.ActivityScenarioRule
import com.github.takahirom.roborazzi.RoborazziOptions
@ -50,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 <A : ComponentActivity> AndroidComposeTestRule<ActivityScenarioRule<A>, A>.captureMultiDevice(
screenshotName: String,
body: @Composable () -> Unit,
@ -90,6 +92,27 @@ fun <A : ComponentActivity> AndroidComposeTestRule<ActivityScenarioRule<A>, A>.c
)
}
fun <A : ComponentActivity> AndroidComposeTestRule<ActivityScenarioRule<A>, A>.captureDialog(
screenshotName: String,
nodeTag: String,
roborazziOptions: RoborazziOptions = DefaultRoborazziOptions,
body: @Composable () -> Unit,
) {
this.activity.setContent {
CompositionLocalProvider(
LocalInspectionMode provides true,
) {
body()
}
}
this.onNodeWithTag(nodeTag)
.captureRoboImage(
filePath = "src/test/screenshots/$screenshotName.png",
roborazziOptions = roborazziOptions,
)
}
/**
* Takes six screenshots combining light/dark and default/Android themes and whether dynamic color
* is enabled.

@ -26,8 +26,4 @@ android {
dependencies {
implementation(projects.core.data)
testImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
}

@ -31,10 +31,7 @@ dependencies {
implementation(projects.core.domain)
testImplementation(libs.hilt.android.testing)
testImplementation(libs.robolectric)
testImplementation(projects.core.testing)
testImplementation(projects.core.screenshotTesting)
testDemoImplementation(libs.roborazzi)
androidTestImplementation(projects.core.testing)
testImplementation(projects.core.screenshotTesting)
}

@ -26,8 +26,4 @@ android {
dependencies {
implementation(projects.core.data)
implementation(projects.core.domain)
testImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
}

@ -28,9 +28,5 @@ dependencies {
implementation(projects.core.data)
implementation(projects.core.domain)
implementation(projects.core.ui)
testImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
}

@ -18,6 +18,7 @@ plugins {
alias(libs.plugins.nowinandroid.android.feature)
alias(libs.plugins.nowinandroid.android.library.compose)
alias(libs.plugins.nowinandroid.android.library.jacoco)
alias(libs.plugins.roborazzi)
}
android {
@ -29,7 +30,8 @@ dependencies {
implementation(libs.google.oss.licenses)
implementation(projects.core.data)
testImplementation(projects.core.testing)
testImplementation(libs.hilt.android.testing)
testDemoImplementation(libs.roborazzi)
androidTestImplementation(projects.core.testing)
testImplementation(projects.core.screenshotTesting)
}

@ -89,11 +89,12 @@ fun SettingsDialog(
@Composable
fun SettingsDialog(
settingsUiState: SettingsUiState,
supportDynamicColor: Boolean = supportsDynamicTheming(),
onDismiss: () -> Unit,
onChangeThemeBrand: (themeBrand: ThemeBrand) -> Unit,
onChangeDynamicColorPreference: (useDynamicColor: Boolean) -> Unit,
onChangeDarkThemeConfig: (darkThemeConfig: DarkThemeConfig) -> Unit,
modifier: Modifier = Modifier,
supportDynamicColor: Boolean = supportsDynamicTheming(),
) {
val configuration = LocalConfiguration.current
@ -106,7 +107,7 @@ fun SettingsDialog(
*/
AlertDialog(
properties = DialogProperties(usePlatformDefaultWidth = false),
modifier = Modifier.widthIn(max = configuration.screenWidthDp.dp - 80.dp),
modifier = modifier.widthIn(max = configuration.screenWidthDp.dp - 80.dp),
onDismissRequest = { onDismiss() },
title = {
Text(

@ -0,0 +1,202 @@
/*
* 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.Modifier
import androidx.compose.ui.platform.testTag
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 = "w480dp-h960dp-480dpi")
class SettingsDialogScreenshotTests {
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
private val defaultSettingsUiState = Success(
UserEditableSettings(
brand = DEFAULT,
darkThemeConfig = LIGHT,
useDynamicColor = false,
),
)
@Test
fun settingsDialogLoading() {
composeTestRule.captureDialog(
screenshotName = "SettingsDialogLoading",
nodeTag = "SettingsDialog",
) {
SettingsDialogDefaultTheme(
settingsUiState = SettingsUiState.Loading,
)
}
}
@Test
fun settingsDialogLoadingDark() {
composeTestRule.captureDialog(
screenshotName = "SettingsDialogLoadingDark",
nodeTag = "SettingsDialog",
) {
SettingsDialogDefaultTheme(
darkMode = true,
settingsUiState = SettingsUiState.Loading,
)
}
}
@Test
fun settingsDialogDefaultTheme() {
composeTestRule.captureDialog(
screenshotName = "SettingsDialogDefaultTheme",
nodeTag = "SettingsDialog",
) {
SettingsDialogDefaultTheme()
}
}
@Test
fun settingsDialogDefaultThemeDark() {
composeTestRule.captureDialog(
screenshotName = "SettingsDialogDefaultThemeDark",
nodeTag = "SettingsDialog",
) {
SettingsDialogDefaultTheme(
darkMode = true,
settingsUiState = Success(
defaultSettingsUiState.settings.copy(
darkThemeConfig = DARK,
),
),
)
}
}
@Test
fun settingsDialogDynamicColor() {
composeTestRule.captureDialog(
screenshotName = "SettingsDialogDynamicColor",
nodeTag = "SettingsDialog",
) {
SettingsDialogDefaultTheme(
disableDynamicTheming = false,
settingsUiState = Success(
defaultSettingsUiState.settings.copy(
useDynamicColor = true,
),
),
)
}
}
@Test
fun settingsDialogDynamicColorDark() {
composeTestRule.captureDialog(
screenshotName = "SettingsDialogDynamicColorDark",
nodeTag = "SettingsDialog",
) {
SettingsDialogDefaultTheme(
darkMode = true,
disableDynamicTheming = false,
settingsUiState = Success(
defaultSettingsUiState.settings.copy(
darkThemeConfig = DARK,
useDynamicColor = true,
),
),
)
}
}
@Test
fun settingsDialogAndroidTheme() {
composeTestRule.captureDialog(
screenshotName = "SettingsDialogAndroidTheme",
nodeTag = "SettingsDialog",
) {
SettingsDialogDefaultTheme(
androidTheme = true,
settingsUiState = Success(
defaultSettingsUiState.settings.copy(
brand = ANDROID,
),
),
)
}
}
@Test
fun settingsDialogAndroidThemeDark() {
composeTestRule.captureDialog(
screenshotName = "SettingsDialogAndroidThemeDark",
nodeTag = "SettingsDialog",
) {
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(
modifier = Modifier.testTag("SettingsDialog"),
onDismiss = {},
settingsUiState = settingsUiState,
onChangeThemeBrand = {},
onChangeDynamicColorPreference = {},
onChangeDarkThemeConfig = {},
)
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@ -26,8 +26,4 @@ android {
dependencies {
implementation(projects.core.data)
testImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
}
}

@ -55,7 +55,7 @@ protobufPlugin = "0.9.4"
retrofit = "2.9.0"
retrofitKotlinxSerializationJson = "1.0.0"
robolectric = "4.11.1"
roborazzi = "1.7.0"
roborazzi = "1.12.0"
room = "2.6.1"
secrets = "2.0.1"
truth = "1.4.2"

Loading…
Cancel
Save