diff --git a/.gitattributes b/.gitattributes index 5f13ff4efb..0a1fc8653d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ screenshots/**/*.png filter=lfs diff=lfs merge=lfs -text +libraries/compound/screenshots/** filter=lfs diff=lfs merge=lfs -text **/snapshots/**/*.png filter=lfs diff=lfs merge=lfs -text **/docs/images-lfs/*.png filter=lfs diff=lfs merge=lfs -text libraries/mediaupload/impl/src/test/assets/* filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/scripts/recordScreenshots.sh b/.github/workflows/scripts/recordScreenshots.sh index a610c6cc69..963a3c908b 100755 --- a/.github/workflows/scripts/recordScreenshots.sh +++ b/.github/workflows/scripts/recordScreenshots.sh @@ -56,6 +56,9 @@ echo "Deleting previous screenshots" echo "Record screenshots" ./gradlew recordPaparazziDebug --stacktrace $GRADLE_ARGS +echo "Record screenshots (Compound)" +./gradlew :libraries:compound:recordRoborazziDebug --stacktrace -PpreDexEnable=false --max-workers 4 --warn $GRADLE_ARGS + echo "Committing changes" git config http.sslVerify false diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c0249642f4..22c302cbb3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -78,6 +78,7 @@ jobs: name: tests-and-screenshot-tests-results path: | **/build/paparazzi/failures/ + **/build/roborazzi/failures/ **/build/reports/tests/*UnitTest/ # https://github.com/codecov/codecov-action diff --git a/build.gradle.kts b/build.gradle.kts index 7171d5b079..484d43a929 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,6 +15,7 @@ plugins { alias(libs.plugins.compose.compiler) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.dependencycheck) apply false + alias(libs.plugins.roborazzi) apply false alias(libs.plugins.dependencyanalysis) alias(libs.plugins.detekt) alias(libs.plugins.ktlint) @@ -180,16 +181,22 @@ tasks.register("runQualityChecks") { // Make sure to delete old screenshots before recording new ones subprojects { val snapshotsDir = File("${project.projectDir}/src/test/snapshots") + val snapshotsDir2 = File("${project.projectDir}/screenshots") val removeOldScreenshotsTask = tasks.register("removeOldSnapshots") { - onlyIf { snapshotsDir.exists() } + onlyIf { snapshotsDir.exists() || snapshotsDir2.exists() } doFirst { println("Delete previous screenshots located at $snapshotsDir\n") snapshotsDir.deleteRecursively() + println("Delete previous screenshots located at $snapshotsDir2\n") + snapshotsDir2.deleteRecursively() } } tasks.findByName("recordPaparazzi")?.dependsOn(removeOldScreenshotsTask) tasks.findByName("recordPaparazziDebug")?.dependsOn(removeOldScreenshotsTask) tasks.findByName("recordPaparazziRelease")?.dependsOn(removeOldScreenshotsTask) + tasks.findByName("recordRoborazzi")?.dependsOn(removeOldScreenshotsTask) + tasks.findByName("recordRoborazziDebug")?.dependsOn(removeOldScreenshotsTask) + tasks.findByName("recordRoborazziRelease")?.dependsOn(removeOldScreenshotsTask) } subprojects { diff --git a/gradle.properties b/gradle.properties index 18399ccf06..a2c7228ed2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -54,3 +54,7 @@ ksp.allow.all.target.configuration=false # Used to prevent detekt from reusing invalid cached rules detekt.use.worker.api=true + +# Let test include roborazzi verification +# https://github.com/takahirom/roborazzi?tab=readme-ov-file#roborazzitest +roborazzi.test.verify=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 78b085fd41..f837a1e55b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,6 +32,7 @@ accompanist = "0.37.3" # Test test_core = "1.7.0" +roborazzi = "1.46.1" # Jetbrain datetime = "0.7.1" @@ -226,6 +227,11 @@ google_autoservice_annotations = { module = "com.google.auto.service:auto-servic # Miscellaneous androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" } +# Test +test_roborazzi = { module = "io.github.takahirom.roborazzi:roborazzi", version.ref = "roborazzi" } +test_roborazzi_compose = { module = "io.github.takahirom.roborazzi:roborazzi-compose", version.ref = "roborazzi" } +test_roborazzi_junit = { module = "io.github.takahirom.roborazzi:roborazzi-junit-rule", version.ref = "roborazzi" } + [bundles] [plugins] @@ -243,6 +249,7 @@ dependencygraph = "com.savvasdalkitsis.module-dependency-graph:0.12" dependencycheck = "org.owasp.dependencycheck:12.1.6" dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyAnalysis" } paparazzi = "app.cash.paparazzi:2.0.0-alpha02" +roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } firebaseAppDistribution = { id = "com.google.firebase.appdistribution", version.ref = "firebaseAppDistribution" } knit = { id = "org.jetbrains.kotlinx.knit", version = "0.5.0" } diff --git a/libraries/compound/build.gradle.kts b/libraries/compound/build.gradle.kts index 9ec6ce0e58..cbdb09d451 100644 --- a/libraries/compound/build.gradle.kts +++ b/libraries/compound/build.gradle.kts @@ -1,3 +1,5 @@ +import extension.testCommonDependencies + /* * Copyright 2022, 2025 New Vector Ltd. * @@ -7,12 +9,21 @@ plugins { id("io.element.android-compose-library") + alias(libs.plugins.roborazzi) } android { namespace = "io.element.android.compound" + testOptions { + unitTests.isIncludeAndroidResources = true + } + dependencies { implementation(libs.showkase) + testCommonDependencies(libs) + testImplementation(libs.test.roborazzi) + testImplementation(libs.test.roborazzi.compose) + testImplementation(libs.test.roborazzi.junit) } } diff --git a/libraries/compound/screenshots/Avatar Colors - Dark.png b/libraries/compound/screenshots/Avatar Colors - Dark.png new file mode 100644 index 0000000000..5cf6cbda89 --- /dev/null +++ b/libraries/compound/screenshots/Avatar Colors - Dark.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:caf2de32caf0fa5368da899297e2eabd5a0c6891dd94f81295ef8a933d79ce16 +size 10751 diff --git a/libraries/compound/screenshots/Avatar Colors - Light.png b/libraries/compound/screenshots/Avatar Colors - Light.png new file mode 100644 index 0000000000..7069762082 --- /dev/null +++ b/libraries/compound/screenshots/Avatar Colors - Light.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80e44e94d7b23af2ec4fd1c5a871851ae2567b40e478b30145de199076f20e95 +size 11296 diff --git a/libraries/compound/screenshots/Compound Icons - Dark.png b/libraries/compound/screenshots/Compound Icons - Dark.png new file mode 100644 index 0000000000..acac494f89 --- /dev/null +++ b/libraries/compound/screenshots/Compound Icons - Dark.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6bc48b9f792da838f9fc2c2a630cbbbb906de851a138cc1ac8b7bf67b801ad84 +size 211300 diff --git a/libraries/compound/screenshots/Compound Icons - Light.png b/libraries/compound/screenshots/Compound Icons - Light.png new file mode 100644 index 0000000000..c6b76c46bb --- /dev/null +++ b/libraries/compound/screenshots/Compound Icons - Light.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e85fd2c67ff42829b8580ab5c0c2af1fee40973f5c0b34ef7de00e3663cee8e4 +size 223041 diff --git a/libraries/compound/screenshots/Compound Icons - Rtl.png b/libraries/compound/screenshots/Compound Icons - Rtl.png new file mode 100644 index 0000000000..ce2ffe2e88 --- /dev/null +++ b/libraries/compound/screenshots/Compound Icons - Rtl.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:406b62991171a146e891f95bcad0321ebc60cf1fe2cabc9caedbb17fb062af13 +size 224320 diff --git a/libraries/compound/screenshots/Compound Semantic Colors - Dark HC.png b/libraries/compound/screenshots/Compound Semantic Colors - Dark HC.png new file mode 100644 index 0000000000..4890b91886 --- /dev/null +++ b/libraries/compound/screenshots/Compound Semantic Colors - Dark HC.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:578e9b5a38791e2686a7b9ba5c461eb1d1fb29dfbe950bf46c113ad75ceac175 +size 327758 diff --git a/libraries/compound/screenshots/Compound Semantic Colors - Dark.png b/libraries/compound/screenshots/Compound Semantic Colors - Dark.png new file mode 100644 index 0000000000..4cc125b4c8 --- /dev/null +++ b/libraries/compound/screenshots/Compound Semantic Colors - Dark.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4cab40fc0506c8f2a2efafb1199e85f1da3ebacb49b176e9105e3f95175f85ee +size 325565 diff --git a/libraries/compound/screenshots/Compound Semantic Colors - Light HC.png b/libraries/compound/screenshots/Compound Semantic Colors - Light HC.png new file mode 100644 index 0000000000..5a8f5a6b32 --- /dev/null +++ b/libraries/compound/screenshots/Compound Semantic Colors - Light HC.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:174f9d4ee70a29c0c8c2a01a15daeb14281530678ff7d7fb19a208bfd789533a +size 309210 diff --git a/libraries/compound/screenshots/Compound Semantic Colors - Light.png b/libraries/compound/screenshots/Compound Semantic Colors - Light.png new file mode 100644 index 0000000000..f010626dda --- /dev/null +++ b/libraries/compound/screenshots/Compound Semantic Colors - Light.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7598b98462c015f2bf74b3ea3ad95fc0220b2efb9bb81ac56025cf6a158e3f8a +size 308976 diff --git a/libraries/compound/screenshots/Compound Typography.png b/libraries/compound/screenshots/Compound Typography.png new file mode 100644 index 0000000000..095ad6c71d --- /dev/null +++ b/libraries/compound/screenshots/Compound Typography.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac84a7175c4a4897aa28eddcf722b7997c6576f612eb38fa09ffabcf7be11e00 +size 119496 diff --git a/libraries/compound/screenshots/Compound Vector Icons - Dark.png b/libraries/compound/screenshots/Compound Vector Icons - Dark.png new file mode 100644 index 0000000000..2b535c348b --- /dev/null +++ b/libraries/compound/screenshots/Compound Vector Icons - Dark.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ff6dfdfab51332cad3bdfa351a4d0e305de5f899853575a8514858cc871e904 +size 83609 diff --git a/libraries/compound/screenshots/Compound Vector Icons - Light.png b/libraries/compound/screenshots/Compound Vector Icons - Light.png new file mode 100644 index 0000000000..bc29dcd24d --- /dev/null +++ b/libraries/compound/screenshots/Compound Vector Icons - Light.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca38f5f23c282a6dc4c01a54705f71bf8c927aeac9c1df0a1f3abe50c10b1b85 +size 89336 diff --git a/libraries/compound/screenshots/ForcedDarkElementTheme.png b/libraries/compound/screenshots/ForcedDarkElementTheme.png new file mode 100644 index 0000000000..d7182aa47c --- /dev/null +++ b/libraries/compound/screenshots/ForcedDarkElementTheme.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:03bdb2f3de01d40b8f85ba87b395cdab2e5225aded2f40a0892077798bca6066 +size 22328 diff --git a/libraries/compound/screenshots/Legacy Colors.png b/libraries/compound/screenshots/Legacy Colors.png new file mode 100644 index 0000000000..2ecdda2ed7 --- /dev/null +++ b/libraries/compound/screenshots/Legacy Colors.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e9d676a1ef20a7228e985f62d346265ff9c31d1860a219540f012c063c9345e +size 33652 diff --git a/libraries/compound/screenshots/Material Typography.png b/libraries/compound/screenshots/Material Typography.png new file mode 100644 index 0000000000..6c22c364b9 --- /dev/null +++ b/libraries/compound/screenshots/Material Typography.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d27f813acc9e8dc3960f5205809c8c0d2ba0fa51fd9e3ca07964b866b125e87d +size 110171 diff --git a/libraries/compound/screenshots/Material3 Colors - Dark HC.png b/libraries/compound/screenshots/Material3 Colors - Dark HC.png new file mode 100644 index 0000000000..4cc7609c89 --- /dev/null +++ b/libraries/compound/screenshots/Material3 Colors - Dark HC.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85969829577e158bdd1d0f21c8b3a2334dcde79cb50d5e2331d06d5423332be2 +size 160754 diff --git a/libraries/compound/screenshots/Material3 Colors - Dark.png b/libraries/compound/screenshots/Material3 Colors - Dark.png new file mode 100644 index 0000000000..3738cf6a79 --- /dev/null +++ b/libraries/compound/screenshots/Material3 Colors - Dark.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca64da1dc373dc49503ee525ae3331e73d0ab12053993a1ef19dcab1e67b08c4 +size 159123 diff --git a/libraries/compound/screenshots/Material3 Colors - Light HC.png b/libraries/compound/screenshots/Material3 Colors - Light HC.png new file mode 100644 index 0000000000..8d64857d13 --- /dev/null +++ b/libraries/compound/screenshots/Material3 Colors - Light HC.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01622bca20a132ec5a874fc1a2d0ffd45e7ce6d7849c4d607d79c7bc51d6c6a9 +size 163322 diff --git a/libraries/compound/screenshots/Material3 Colors - Light.png b/libraries/compound/screenshots/Material3 Colors - Light.png new file mode 100644 index 0000000000..a1d5d1f2ce --- /dev/null +++ b/libraries/compound/screenshots/Material3 Colors - Light.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87c0c4ff42d17137d554708ce33f40f214ec608eca4ca87af0b2adab63de6bb7 +size 162891 diff --git a/libraries/compound/screenshots/MaterialText Colors.png b/libraries/compound/screenshots/MaterialText Colors.png new file mode 100644 index 0000000000..f8f77ccca2 --- /dev/null +++ b/libraries/compound/screenshots/MaterialText Colors.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4be10c3bb9900d27a3b406eca0cb902b0ff9cdf90e8e3cf1ae7760aa7c5d47d9 +size 377446 diff --git a/libraries/compound/screenshots/MaterialYou Theme - Dark.png b/libraries/compound/screenshots/MaterialYou Theme - Dark.png new file mode 100644 index 0000000000..8c5bc9d1ef --- /dev/null +++ b/libraries/compound/screenshots/MaterialYou Theme - Dark.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c166e5371bb1922a9c016438a3cdfd0d68197237969d53a04f92baf6d53c4ac0 +size 164925 diff --git a/libraries/compound/screenshots/MaterialYou Theme - Light.png b/libraries/compound/screenshots/MaterialYou Theme - Light.png new file mode 100644 index 0000000000..70cccac69b --- /dev/null +++ b/libraries/compound/screenshots/MaterialYou Theme - Light.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d936948cbad69d6935f2d2738d33682a55f044dfb1af8b5c9b8323c5f4318971 +size 163558 diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/AvatarColorsTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/AvatarColorsTest.kt new file mode 100644 index 0000000000..015cd5341c --- /dev/null +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/AvatarColorsTest.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2023, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.compound.screenshot + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.captureRoboImage +import io.element.android.compound.screenshot.utils.screenshotFile +import io.element.android.compound.theme.AvatarColorsPreviewDark +import io.element.android.compound.theme.AvatarColorsPreviewLight +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class AvatarColorsTest { + @Test + @Config(sdk = [35], qualifiers = "xxhdpi") + fun screenshots() { + captureRoboImage(file = screenshotFile("Avatar Colors - Light.png")) { + AvatarColorsPreviewLight() + } + captureRoboImage(file = screenshotFile("Avatar Colors - Dark.png")) { + AvatarColorsPreviewDark() + } + } +} diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/CompoundIconTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/CompoundIconTest.kt new file mode 100644 index 0000000000..9ae73a6205 --- /dev/null +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/CompoundIconTest.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2023, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.compound.screenshot + +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.captureRoboImage +import io.element.android.compound.previews.IconsCompoundPreviewDark +import io.element.android.compound.previews.IconsCompoundPreviewLight +import io.element.android.compound.previews.IconsCompoundPreviewRtl +import io.element.android.compound.previews.IconsPreview +import io.element.android.compound.screenshot.utils.screenshotFile +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.CompoundIcons +import kotlinx.collections.immutable.toImmutableList +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class CompoundIconTest { + @Test + @Config(sdk = [35], qualifiers = "w1024dp-h2048dp") + fun screenshots() { + captureRoboImage(file = screenshotFile("Compound Icons - Light.png")) { + IconsCompoundPreviewLight() + } + captureRoboImage(file = screenshotFile("Compound Icons - Rtl.png")) { + IconsCompoundPreviewRtl() + } + captureRoboImage(file = screenshotFile("Compound Icons - Dark.png")) { + IconsCompoundPreviewDark() + } + captureRoboImage(file = screenshotFile("Compound Vector Icons - Light.png")) { + val content: List<@Composable ColumnScope.() -> Unit> = CompoundIcons.all.map { + @Composable { Icon(imageVector = it, contentDescription = null) } + } + ElementTheme { + IconsPreview( + title = "Compound Vector Icons", + content = content.toImmutableList() + ) + } + } + captureRoboImage(file = screenshotFile("Compound Vector Icons - Dark.png")) { + val content: List<@Composable ColumnScope.() -> Unit> = CompoundIcons.all.map { + @Composable { Icon(imageVector = it, contentDescription = null) } + } + ElementTheme(darkTheme = true) { + IconsPreview( + title = "Compound Vector Icons", + content = content.toImmutableList() + ) + } + } + } +} diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/CompoundTypographyTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/CompoundTypographyTest.kt new file mode 100644 index 0000000000..2d50e6287d --- /dev/null +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/CompoundTypographyTest.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2023, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.compound.screenshot + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.unit.dp +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.captureRoboImage +import io.element.android.compound.screenshot.utils.screenshotFile +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.TypographyTokens +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class CompoundTypographyTest { + @Test + @Config(sdk = [35], qualifiers = "h2048dp-xxhdpi") + fun screenshots() { + captureRoboImage(file = screenshotFile("Compound Typography.png")) { + ElementTheme { + Surface { + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + with(TypographyTokens) { + TypographyTokenPreview(fontHeadingXlBold, "Heading XL Bold") + TypographyTokenPreview(fontHeadingXlRegular, "Heading XL Regular") + TypographyTokenPreview(fontHeadingLgBold, "Heading LG Bold") + TypographyTokenPreview(fontHeadingLgRegular, "Heading LG Regular") + TypographyTokenPreview(fontHeadingMdBold, "Heading MD Bold") + TypographyTokenPreview(fontHeadingMdRegular, "Heading MD Regular") + TypographyTokenPreview(fontHeadingSmMedium, "Heading SM Medium") + TypographyTokenPreview(fontHeadingSmRegular, "Heading SM Regular") + TypographyTokenPreview(fontBodyLgMedium, "Body LG Medium") + TypographyTokenPreview(fontBodyLgRegular, "Body LG Regular") + TypographyTokenPreview(fontBodyMdMedium, "Body MD Medium") + TypographyTokenPreview(fontBodyMdRegular, "Body MD Regular") + TypographyTokenPreview(fontBodySmMedium, "Body SM Medium") + TypographyTokenPreview(fontBodySmRegular, "Body SM Regular") + TypographyTokenPreview(fontBodyXsMedium, "Body XS Medium") + TypographyTokenPreview(fontBodyXsRegular, "Body XS Regular") + } + } + } + } + } + } + + @Composable + private fun TypographyTokenPreview(style: TextStyle, text: String) { + Text(text = text, style = style) + } +} diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/ForcedDarkElementThemeTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/ForcedDarkElementThemeTest.kt new file mode 100644 index 0000000000..341b7cb650 --- /dev/null +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/ForcedDarkElementThemeTest.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2023, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.compound.screenshot + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.captureRoboImage +import io.element.android.compound.screenshot.utils.screenshotFile +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.theme.ForcedDarkElementTheme +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class ForcedDarkElementThemeTest { + @Test + @Config(sdk = [35], qualifiers = "xxhdpi") + fun screenshots() { + captureRoboImage(file = screenshotFile("ForcedDarkElementTheme.png")) { + ElementTheme { + Surface { + Column( + modifier = Modifier.padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Text(text = "Outside") + ForcedDarkElementTheme { + Surface { + Box(modifier = Modifier.fillMaxSize()) { + Text(text = "Inside ForcedDarkElementTheme", modifier = Modifier.align(Alignment.Center)) + } + } + } + } + } + } + } + } +} diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/LegacyColorsTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/LegacyColorsTest.kt new file mode 100644 index 0000000000..ecfbbe81cd --- /dev/null +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/LegacyColorsTest.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2023, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.compound.screenshot + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.captureRoboImage +import io.element.android.compound.previews.ColorPreview +import io.element.android.compound.screenshot.utils.screenshotFile +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.theme.LinkColor +import io.element.android.compound.theme.SnackBarLabelColorDark +import io.element.android.compound.theme.SnackBarLabelColorLight +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class LegacyColorsTest { + @Test + @Config(sdk = [35], qualifiers = "xxhdpi") + fun screenshots() { + captureRoboImage(file = screenshotFile("Legacy Colors.png")) { + ElementTheme { + Surface { + Column(modifier = Modifier.padding(16.dp)) { + Text(text = "Legacy Colors") + Spacer(modifier = Modifier.height(10.dp)) + LegacyColorPreview( + color = LinkColor, + name = "Link" + ) + LegacyColorPreview( + color = SnackBarLabelColorLight, + name = "SnackBar Label - Light" + ) + LegacyColorPreview( + color = SnackBarLabelColorDark, + name = "SnackBar Label - Dark" + ) + } + } + } + } + } + + @Composable + private fun LegacyColorPreview(color: Color, name: String) { + ColorPreview( + backgroundColor = Color.White, + foregroundColor = Color.Black, + name = name, + color = color + ) + } +} diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialColorSchemeTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialColorSchemeTest.kt new file mode 100644 index 0000000000..7542eaa4fc --- /dev/null +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialColorSchemeTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2023, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.compound.screenshot + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.captureRoboImage +import io.element.android.compound.screenshot.utils.screenshotFile +import io.element.android.compound.theme.ColorsSchemeDarkHcPreview +import io.element.android.compound.theme.ColorsSchemeDarkPreview +import io.element.android.compound.theme.ColorsSchemeLightHcPreview +import io.element.android.compound.theme.ColorsSchemeLightPreview +import io.element.android.compound.theme.ElementTheme +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class MaterialColorSchemeTest { + @Test + @Config(sdk = [35], qualifiers = "h2048dp-xhdpi") + fun screenshots() { + captureRoboImage(file = screenshotFile("Material3 Colors - Light.png")) { + ElementTheme { + Surface { + Column(modifier = Modifier.padding(16.dp)) { + Text( + text = "M3 Light colors", + style = TextStyle.Default.copy(fontSize = 18.sp), + ) + Spacer(modifier = Modifier.height(12.dp)) + ColorsSchemeLightPreview() + } + } + } + } + captureRoboImage(file = screenshotFile("Material3 Colors - Light HC.png")) { + ElementTheme { + Surface { + Column(modifier = Modifier.padding(16.dp)) { + Text( + text = "M3 Light HC colors", + style = TextStyle.Default.copy(fontSize = 18.sp), + ) + Spacer(modifier = Modifier.height(12.dp)) + ColorsSchemeLightHcPreview() + } + } + } + } + captureRoboImage(file = screenshotFile("Material3 Colors - Dark.png")) { + ElementTheme { + Surface { + Column(modifier = Modifier.padding(16.dp)) { + Text( + text = "M3 Dark colors", + style = TextStyle.Default.copy(fontSize = 18.sp), + ) + Spacer(modifier = Modifier.height(12.dp)) + ColorsSchemeDarkPreview() + } + } + } + } + captureRoboImage(file = screenshotFile("Material3 Colors - Dark HC.png")) { + ElementTheme { + Surface { + Column(modifier = Modifier.padding(16.dp)) { + Text( + text = "M3 Dark HC colors", + style = TextStyle.Default.copy(fontSize = 18.sp), + ) + Spacer(modifier = Modifier.height(12.dp)) + ColorsSchemeDarkHcPreview() + } + } + } + } + } +} diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialTextTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialTextTest.kt new file mode 100644 index 0000000000..764d4de77c --- /dev/null +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialTextTest.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.compound.screenshot + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.captureRoboImage +import io.element.android.compound.screenshot.utils.screenshotFile +import io.element.android.compound.theme.MaterialTextPreview +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class MaterialTextTest { + @Test + @Config(sdk = [35], qualifiers = "w480dp-h1200dp-xxhdpi") + fun screenshots() { + captureRoboImage(file = screenshotFile("MaterialText Colors.png")) { + MaterialTextPreview() + } + } +} diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialTypographyTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialTypographyTest.kt new file mode 100644 index 0000000000..4f77a070ed --- /dev/null +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialTypographyTest.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2023, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.compound.screenshot + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.captureRoboImage +import io.element.android.compound.previews.TypographyPreview +import io.element.android.compound.screenshot.utils.screenshotFile +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class MaterialTypographyTest { + @Test + @Config(sdk = [35], qualifiers = "h2048dp-xxhdpi") + fun screenshots() { + captureRoboImage(file = screenshotFile("Material Typography.png")) { + TypographyPreview() + } + } +} diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialYouThemeTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialYouThemeTest.kt new file mode 100644 index 0000000000..694d2c9fc6 --- /dev/null +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialYouThemeTest.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2023, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.compound.screenshot + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.captureRoboImage +import io.element.android.compound.previews.ColorsSchemePreview +import io.element.android.compound.screenshot.utils.screenshotFile +import io.element.android.compound.theme.ElementTheme +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class MaterialYouThemeTest { + @Test + @Config(sdk = [35], qualifiers = "h2048dp-xhdpi") + fun screenshots() { + captureRoboImage(file = screenshotFile("MaterialYou Theme - Light.png")) { + ElementTheme(dynamicColor = true) { + Surface { + Column( + modifier = Modifier.padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Text(text = "Material You Theme - Light") + Spacer(modifier = Modifier.height(12.dp)) + ColorsSchemePreview(Color.White, Color.Black, ElementTheme.materialColors) + } + } + } + } + captureRoboImage(file = screenshotFile("MaterialYou Theme - Dark.png")) { + ElementTheme(dynamicColor = true, darkTheme = true) { + Surface { + Column( + modifier = Modifier.padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Text(text = "Material You Theme - Dark") + Spacer(modifier = Modifier.height(12.dp)) + ColorsSchemePreview(Color.White, Color.Black, ElementTheme.materialColors) + } + } + } + } + } +} diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/SemanticColorsTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/SemanticColorsTest.kt new file mode 100644 index 0000000000..7e5fabd96a --- /dev/null +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/SemanticColorsTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2023, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.compound.screenshot + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.captureRoboImage +import io.element.android.compound.previews.CompoundSemanticColorsDark +import io.element.android.compound.previews.CompoundSemanticColorsDarkHc +import io.element.android.compound.previews.CompoundSemanticColorsLight +import io.element.android.compound.previews.CompoundSemanticColorsLightHc +import io.element.android.compound.screenshot.utils.screenshotFile +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class SemanticColorsTest { + @Config(sdk = [35], qualifiers = "h2000dp-xhdpi") + @Test + fun screenshots() { + captureRoboImage(file = screenshotFile("Compound Semantic Colors - Light.png")) { + CompoundSemanticColorsLight() + } + + captureRoboImage(file = screenshotFile("Compound Semantic Colors - Light HC.png")) { + CompoundSemanticColorsLightHc() + } + + captureRoboImage(file = screenshotFile("Compound Semantic Colors - Dark.png")) { + CompoundSemanticColorsDark() + } + + captureRoboImage(file = screenshotFile("Compound Semantic Colors - Dark HC.png")) { + CompoundSemanticColorsDarkHc() + } + } +} diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/utils/ScreenshotUtils.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/utils/ScreenshotUtils.kt new file mode 100644 index 0000000000..3d4c9b3824 --- /dev/null +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/utils/ScreenshotUtils.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2023, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.compound.screenshot.utils + +import java.io.File + +/** + * Returns a [File] object for a screenshot with the given [filename]. + * This is to ensure we have a consistent location for all screenshots. + */ +fun screenshotFile(filename: String): File { + return File("screenshots", filename) +}