diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/DayNightPreviews.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/DayNightPreviews.kt new file mode 100644 index 0000000000..201d6f7151 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/DayNightPreviews.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * 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 + * + * http://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 io.element.android.libraries.designsystem.preview + +import android.content.res.Configuration +import androidx.compose.ui.tooling.preview.Preview + +/** + * Marker for a night mode preview. + * + * Previews with such marker will be rendered in night mode during screenshot testing. + * + * NB: Length of this constant is kept to a minimum to avoid screenshot file names being too long. + */ +const val NIGHT_MODE_NAME = "N" + +/** + * Marker for a day mode preview. + * + * This marker is currently not used during screenshot testing, it mainly act as a counterpart to [NIGHT_MODE_NAME]. + * + * NB: Length of this constant is kept to a minimum to avoid screenshot file names being too long. + */ +const val DAY_MODE_NAME = "D" + +/** + * Generates 2 previews of the composable it is applied to: day and night mode. + * + * NB: Content should be wrapped into [ElementPreview] to apply proper theming. + */ +@Preview(name = DAY_MODE_NAME) +@Preview(name = NIGHT_MODE_NAME, uiMode = Configuration.UI_MODE_NIGHT_YES) +annotation class DayNightPreviews diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt index 84de5d58f1..3c2d61a76e 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt @@ -17,6 +17,7 @@ package io.element.android.libraries.designsystem.preview import androidx.compose.foundation.background +import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -28,8 +29,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.designsystem.theme.components.Surface +import io.element.android.libraries.theme.ElementTheme @Composable fun ElementPreviewLight( @@ -62,29 +63,35 @@ fun ElementThemedPreview( vertical: Boolean = true, content: @Composable () -> Unit, ) { - Box(modifier = Modifier - .background(Color.Gray) - .padding(4.dp)) { + Box( + modifier = Modifier + .background(Color.Gray) + .padding(4.dp) + ) { if (vertical) { Column { - ElementPreviewLight( + ElementPreview( + darkTheme = false, showBackground = showBackground, content = content, ) Spacer(modifier = Modifier.height(4.dp)) - ElementPreviewDark( + ElementPreview( + darkTheme = true, showBackground = showBackground, content = content ) } } else { Row { - ElementPreviewLight( + ElementPreview( + darkTheme = false, showBackground = showBackground, content = content, ) Spacer(modifier = Modifier.width(4.dp)) - ElementPreviewDark( + ElementPreview( + darkTheme = true, showBackground = showBackground, content = content ) @@ -95,18 +102,17 @@ fun ElementThemedPreview( @Composable @Suppress("ModifierMissing") -private fun ElementPreview( - darkTheme: Boolean, - showBackground: Boolean, +fun ElementPreview( + darkTheme: Boolean = isSystemInDarkTheme(), + showBackground: Boolean = true, content: @Composable () -> Unit ) { ElementTheme(darkTheme = darkTheme) { if (showBackground) { // If we have a proper contentColor applied we need a Surface instead of a Box - Surface { content() } + Surface(content = content) } else { content() } } } - diff --git a/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ColorTestPreview.kt b/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ColorTestPreview.kt index ae3722612b..97276e0987 100644 --- a/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ColorTestPreview.kt +++ b/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ColorTestPreview.kt @@ -38,5 +38,7 @@ class ColorTestPreview( ) } + override val name: String = showkaseBrowserColor.colorName + override fun toString(): String = "Color_${showkaseBrowserColor.colorGroup}_${showkaseBrowserColor.colorName}" } diff --git a/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ComponentTestPreview.kt b/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ComponentTestPreview.kt index d6c09608d4..8be21ba1ee 100644 --- a/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ComponentTestPreview.kt +++ b/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ComponentTestPreview.kt @@ -25,5 +25,7 @@ class ComponentTestPreview( @Composable override fun Content() = showkaseBrowserComponent.component() + override val name: String = showkaseBrowserComponent.componentName + override fun toString(): String = showkaseBrowserComponent.componentKey } diff --git a/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ScreenshotTest.kt b/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ScreenshotTest.kt index 1c8f1232d0..5feb9d02ae 100644 --- a/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ScreenshotTest.kt +++ b/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/ScreenshotTest.kt @@ -38,6 +38,7 @@ import com.airbnb.android.showkase.models.Showkase import com.android.ide.common.rendering.api.SessionParams import com.google.testing.junit.testparameterinjector.TestParameter import com.google.testing.junit.testparameterinjector.TestParameterInjector +import io.element.android.libraries.designsystem.preview.NIGHT_MODE_NAME import io.element.android.libraries.theme.ElementTheme import org.junit.Rule import org.junit.Test @@ -95,6 +96,10 @@ class ScreenshotTest { ), LocalConfiguration provides Configuration().apply { setLocales(LocaleList(localeStr.toLocale())) + // Dark mode previews have name "N" so their component name contains "- N" + if (componentTestPreview.name.contains("- $NIGHT_MODE_NAME")){ + uiMode = Configuration.UI_MODE_NIGHT_YES + } }, // Needed so that UI that uses it don't crash during screenshot tests LocalOnBackPressedDispatcherOwner provides object : OnBackPressedDispatcherOwner { diff --git a/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/TestPreview.kt b/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/TestPreview.kt index 6892665e1a..005002f3e6 100644 --- a/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/TestPreview.kt +++ b/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/TestPreview.kt @@ -21,4 +21,6 @@ import androidx.compose.runtime.Composable interface TestPreview { @Composable fun Content() + + val name: String } diff --git a/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/TypographyTestPreview.kt b/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/TypographyTestPreview.kt index 80f27c25a0..c723f990b1 100644 --- a/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/TypographyTestPreview.kt +++ b/tests/uitests/src/test/kotlin/io/element/android/tests/uitests/TypographyTestPreview.kt @@ -44,5 +44,7 @@ class TypographyTestPreview( ) } + override val name: String = showkaseBrowserTypography.typographyName + override fun toString(): String = "Typo_${showkaseBrowserTypography.typographyGroup}_${showkaseBrowserTypography.typographyName}" } diff --git a/tools/danger/dangerfile.js b/tools/danger/dangerfile.js index 16fbf4d31b..7270f334ae 100644 --- a/tools/danger/dangerfile.js +++ b/tools/danger/dangerfile.js @@ -132,7 +132,8 @@ if (allowList.includes(user)) { const previewAnnotations = [ 'androidx.compose.ui.tooling.preview.Preview', - 'io.element.android.libraries.designsystem.preview.LargeHeightPreview' + 'io.element.android.libraries.designsystem.preview.LargeHeightPreview', + 'io.element.android.libraries.designsystem.preview.DayNightPreviews' ] const filesWithPreviews = editedFiles.filter(file => file.endsWith(".kt")).filter(file => {