1414 * limitations under the License.
1515 */
1616
17+ @file:OptIn(ExperimentalRoborazziApi ::class )
18+
1719package com.google.samples.apps.nowinandroid.core.testing.util
1820
21+ import android.graphics.Bitmap.CompressFormat.PNG
1922import androidx.activity.ComponentActivity
2023import androidx.activity.compose.setContent
2124import androidx.compose.runtime.Composable
@@ -30,12 +33,25 @@ import androidx.compose.ui.test.DeviceConfigurationOverride
3033import androidx.compose.ui.test.junit4.AndroidComposeTestRule
3134import androidx.compose.ui.test.onRoot
3235import androidx.test.ext.junit.rules.ActivityScenarioRule
36+ import com.github.takahirom.roborazzi.ExperimentalRoborazziApi
37+ import com.github.takahirom.roborazzi.RoborazziATFAccessibilityCheckOptions
38+ import com.github.takahirom.roborazzi.RoborazziATFAccessibilityChecker
39+ import com.github.takahirom.roborazzi.RoborazziATFAccessibilityChecker.CheckLevel
3340import com.github.takahirom.roborazzi.RoborazziOptions
3441import com.github.takahirom.roborazzi.RoborazziOptions.CompareOptions
3542import com.github.takahirom.roborazzi.RoborazziOptions.RecordOptions
3643import com.github.takahirom.roborazzi.captureRoboImage
44+ import com.github.takahirom.roborazzi.checkRoboAccessibility
45+ import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckPreset
46+ import com.google.android.apps.common.testing.accessibility.framework.AccessibilityViewCheckResult
47+ import com.google.android.apps.common.testing.accessibility.framework.integrations.espresso.AccessibilityViewCheckException
48+ import com.google.android.apps.common.testing.accessibility.framework.utils.contrast.BitmapImage
3749import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
50+ import org.hamcrest.Matcher
51+ import org.hamcrest.Matchers
3852import org.robolectric.RuntimeEnvironment
53+ import java.io.File
54+ import java.io.FileOutputStream
3955
4056val DefaultRoborazziOptions =
4157 RoborazziOptions (
@@ -52,10 +68,17 @@ enum class DefaultTestDevices(val description: String, val spec: String) {
5268}
5369fun <A : ComponentActivity > AndroidComposeTestRule <ActivityScenarioRule <A >, A>.captureMultiDevice (
5470 screenshotName : String ,
71+ accessibilitySuppressions : Matcher <in AccessibilityViewCheckResult > = Matchers .not(Matchers .anything()),
5572 body : @Composable () -> Unit ,
5673) {
5774 DefaultTestDevices .entries.forEach {
58- this .captureForDevice(it.description, it.spec, screenshotName, body = body)
75+ this .captureForDevice(
76+ deviceName = it.description,
77+ deviceSpec = it.spec,
78+ screenshotName = screenshotName,
79+ body = body,
80+ accessibilitySuppressions = accessibilitySuppressions,
81+ )
5982 }
6083}
6184
@@ -64,6 +87,7 @@ fun <A : ComponentActivity> AndroidComposeTestRule<ActivityScenarioRule<A>, A>.c
6487 deviceSpec : String ,
6588 screenshotName : String ,
6689 roborazziOptions : RoborazziOptions = DefaultRoborazziOptions ,
90+ accessibilitySuppressions : Matcher <in AccessibilityViewCheckResult > = Matchers .not(Matchers .anything()),
6791 darkMode : Boolean = false,
6892 body : @Composable () -> Unit ,
6993) {
@@ -83,11 +107,46 @@ fun <A : ComponentActivity> AndroidComposeTestRule<ActivityScenarioRule<A>, A>.c
83107 }
84108 }
85109 }
110+
111+ // Run Accessibility checks first so logging is included
112+ val accessibilityException = try {
113+ this .onRoot().checkRoboAccessibility(
114+ roborazziATFAccessibilityCheckOptions = RoborazziATFAccessibilityCheckOptions (
115+ failureLevel = CheckLevel .Error ,
116+ checker = RoborazziATFAccessibilityChecker (
117+ preset = AccessibilityCheckPreset .LATEST ,
118+ suppressions = accessibilitySuppressions,
119+ ),
120+ ),
121+ )
122+ null
123+ } catch (e: AccessibilityViewCheckException ) {
124+ e
125+ }
126+
86127 this .onRoot()
87128 .captureRoboImage(
88129 " src/test/screenshots/${screenshotName} _$deviceName .png" ,
89130 roborazziOptions = roborazziOptions,
90131 )
132+
133+ // Rethrow the Accessibility exception once screenshots have passed
134+ if (accessibilityException != null ) {
135+ accessibilityException.results.forEachIndexed { index, check ->
136+ val viewImage = check.viewImage
137+ if (viewImage is BitmapImage ) {
138+ val file = File (" build/outputs/roborazzi/${screenshotName} _${deviceName} _$index .png" )
139+ println (" Writing check.viewImage to $file " )
140+ FileOutputStream (
141+ file,
142+ ).use {
143+ viewImage.bitmap.compress(PNG , 100 , it)
144+ }
145+ }
146+ }
147+
148+ throw accessibilityException
149+ }
91150}
92151
93152/* *
0 commit comments