diff --git a/roborazzi-accessibility-check/src/main/java/com/github/takahirom/roborazzi/ATFAccessibilityChecker.kt b/roborazzi-accessibility-check/src/main/java/com/github/takahirom/roborazzi/RoborazziATFAccessibilityChecker.kt similarity index 83% rename from roborazzi-accessibility-check/src/main/java/com/github/takahirom/roborazzi/ATFAccessibilityChecker.kt rename to roborazzi-accessibility-check/src/main/java/com/github/takahirom/roborazzi/RoborazziATFAccessibilityChecker.kt index c899cd12..1647d9d6 100644 --- a/roborazzi-accessibility-check/src/main/java/com/github/takahirom/roborazzi/ATFAccessibilityChecker.kt +++ b/roborazzi-accessibility-check/src/main/java/com/github/takahirom/roborazzi/RoborazziATFAccessibilityChecker.kt @@ -25,31 +25,31 @@ import org.hamcrest.Matchers import org.robolectric.shadows.ShadowBuild fun SemanticsNodeInteraction.checkRoboAccessibility( - checker: ATFAccessibilityChecker = ATFAccessibilityChecker(), - failureLevel: CheckLevel = CheckLevel.Error, + checker: RoborazziATFAccessibilityChecker = RoborazziATFAccessibilityChecker(), + failureLevel: RoborazziATFAccessibilityChecker.CheckLevel = RoborazziATFAccessibilityChecker.CheckLevel.Error, roborazziOptions: RoborazziOptions = provideRoborazziContext().options, ) { checker.runAccessibilityChecks( - checkNode = ATFAccessibilityChecker.CheckNode.Compose(this), + checkNode = RoborazziATFAccessibilityChecker.CheckNode.Compose(this), roborazziOptions = roborazziOptions, failureLevel = failureLevel, ) } fun ViewInteraction.checkRoboAccessibility( - checker: ATFAccessibilityChecker = ATFAccessibilityChecker(), - failureLevel: CheckLevel = CheckLevel.Error, + checker: RoborazziATFAccessibilityChecker = RoborazziATFAccessibilityChecker(), + failureLevel: RoborazziATFAccessibilityChecker.CheckLevel = RoborazziATFAccessibilityChecker.CheckLevel.Error, roborazziOptions: RoborazziOptions = provideRoborazziContext().options, ) { checker.runAccessibilityChecks( - checkNode = ATFAccessibilityChecker.CheckNode.View(this), + checkNode = RoborazziATFAccessibilityChecker.CheckNode.View(this), roborazziOptions = roborazziOptions, failureLevel = failureLevel, ) } @ExperimentalRoborazziApi -data class ATFAccessibilityChecker( +data class RoborazziATFAccessibilityChecker( val checks: Set = AccessibilityCheckPreset.getAccessibilityHierarchyChecksForPreset( AccessibilityCheckPreset.LATEST ), @@ -63,37 +63,26 @@ data class ATFAccessibilityChecker( suppressions = suppressions, ) + internal sealed interface CheckNode { + data class View(val viewInteraction: ViewInteraction) : CheckNode + data class Compose(val semanticsNodeInteraction: SemanticsNodeInteraction) : CheckNode + } - @RequiresApi(34) - internal fun runAllChecks( - view: View, - screenshotBitmap: Bitmap?, - checks: Set, - suppressions: Matcher, - ): List { - val parameters = Parameters().apply { - if (screenshotBitmap != null) { - putScreenCapture(BitmapImage(screenshotBitmap)) - } - setSaveViewImages(true) - } - val viewChecker = ViewChecker().apply { - setObtainCharacterLocations(true) - } + @ExperimentalRoborazziApi + enum class CheckLevel(private vararg val failedTypes: AccessibilityCheckResultType) { + Error(AccessibilityCheckResultType.ERROR), - val results = viewChecker.runChecksOnView(ImmutableSet.copyOf(checks), view, parameters) + Warning( + AccessibilityCheckResultType.ERROR, AccessibilityCheckResultType.WARNING + ), - return results.filter { - !suppressions.matches(it) - } - } + LogOnly; - internal sealed interface CheckNode { - data class View(val viewInteraction: ViewInteraction) : CheckNode - data class Compose(val semanticsNodeInteraction: SemanticsNodeInteraction) : CheckNode + fun isFailure(type: AccessibilityCheckResultType): Boolean = failedTypes.contains(type) } + @SuppressLint("VisibleForTests") internal fun runAccessibilityChecks( checkNode: CheckNode, @@ -156,6 +145,32 @@ data class ATFAccessibilityChecker( } } + @RequiresApi(34) + internal fun runAllChecks( + view: View, + screenshotBitmap: Bitmap?, + checks: Set, + suppressions: Matcher, + ): List { + val parameters = Parameters().apply { + if (screenshotBitmap != null) { + putScreenCapture(BitmapImage(screenshotBitmap)) + } + setSaveViewImages(true) + } + + val viewChecker = ViewChecker().apply { + setObtainCharacterLocations(true) + } + + val results = viewChecker.runChecksOnView(ImmutableSet.copyOf(checks), view, parameters) + + return results.filter { + !suppressions.matches(it) + } + } + + private fun reportResults( results: List, failureLevel: CheckLevel ) { @@ -185,34 +200,21 @@ data class ATFAccessibilityChecker( } @ExperimentalRoborazziApi -enum class CheckLevel(private vararg val failedTypes: AccessibilityCheckResultType) { - Error(AccessibilityCheckResultType.ERROR), - - Warning( - AccessibilityCheckResultType.ERROR, AccessibilityCheckResultType.WARNING - ), - - LogOnly; - - fun isFailure(type: AccessibilityCheckResultType): Boolean = failedTypes.contains(type) -} - -@ExperimentalRoborazziApi -data class ValidateAfterTest( - val checker: ATFAccessibilityChecker = ATFAccessibilityChecker(), - val failureLevel: CheckLevel = CheckLevel.Error, +data class AccessibilityCheckAfterTest( + val checker: RoborazziATFAccessibilityChecker = RoborazziATFAccessibilityChecker(), + val failureLevel: RoborazziATFAccessibilityChecker.CheckLevel = RoborazziATFAccessibilityChecker.CheckLevel.Error, ) : RoborazziRule.AccessibilityChecks { override fun runAccessibilityChecks( captureRoot: CaptureRoot, roborazziOptions: RoborazziOptions ) { checker.runAccessibilityChecks( checkNode = when (captureRoot) { - is CaptureRoot.Compose -> ATFAccessibilityChecker.CheckNode.Compose( + is CaptureRoot.Compose -> RoborazziATFAccessibilityChecker.CheckNode.Compose( semanticsNodeInteraction = captureRoot.semanticsNodeInteraction ) CaptureRoot.None -> return - is CaptureRoot.View -> ATFAccessibilityChecker.CheckNode.View( + is CaptureRoot.View -> RoborazziATFAccessibilityChecker.CheckNode.View( viewInteraction = captureRoot.viewInteraction ) }, diff --git a/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ComposeA11yTest.kt b/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ComposeA11yTest.kt index b2ad16d0..dfdf13e3 100644 --- a/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ComposeA11yTest.kt +++ b/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ComposeA11yTest.kt @@ -22,12 +22,11 @@ import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onRoot import androidx.compose.ui.unit.dp import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.github.takahirom.roborazzi.ATFAccessibilityChecker -import com.github.takahirom.roborazzi.CheckLevel +import com.github.takahirom.roborazzi.AccessibilityCheckAfterTest import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers +import com.github.takahirom.roborazzi.RoborazziATFAccessibilityChecker import com.github.takahirom.roborazzi.RoborazziRule import com.github.takahirom.roborazzi.RoborazziRule.Options -import com.github.takahirom.roborazzi.ValidateAfterTest import com.github.takahirom.roborazzi.checkRoboAccessibility import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckPreset import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesElements @@ -55,12 +54,12 @@ class ComposeA11yTest { composeRule = composeTestRule, captureRoot = composeTestRule.onRoot(), options = Options( - accessibilityChecks = ValidateAfterTest( - checker = ATFAccessibilityChecker( + accessibilityChecks = AccessibilityCheckAfterTest( + checker = RoborazziATFAccessibilityChecker( preset = AccessibilityCheckPreset.LATEST, suppressions = matchesElements(withTestTag("suppress")) ), - failureLevel = CheckLevel.Warning, + failureLevel = RoborazziATFAccessibilityChecker.CheckLevel.Warning, ) ) ) @@ -209,10 +208,10 @@ class ComposeA11yTest { // Now run without suppressions // Run only against nothard, shouldn't fail because of the hard to read text composeTestRule.onNodeWithTag("nothard").checkRoboAccessibility( - ATFAccessibilityChecker( + RoborazziATFAccessibilityChecker( preset = AccessibilityCheckPreset.LATEST, ), - CheckLevel.Warning + RoborazziATFAccessibilityChecker.CheckLevel.Warning ) } } diff --git a/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ComposeA11yWithCustomCheckTest.kt b/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ComposeA11yWithCustomCheckTest.kt index 47800645..c252ca9c 100644 --- a/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ComposeA11yWithCustomCheckTest.kt +++ b/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ComposeA11yWithCustomCheckTest.kt @@ -14,12 +14,11 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onRoot import androidx.compose.ui.unit.dp import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.github.takahirom.roborazzi.ATFAccessibilityChecker -import com.github.takahirom.roborazzi.CheckLevel +import com.github.takahirom.roborazzi.RoborazziATFAccessibilityChecker import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers import com.github.takahirom.roborazzi.RoborazziRule import com.github.takahirom.roborazzi.RoborazziRule.Options -import com.github.takahirom.roborazzi.ValidateAfterTest +import com.github.takahirom.roborazzi.AccessibilityCheckAfterTest import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResult.AccessibilityCheckResultType import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResult.AccessibilityCheckResultType.ERROR import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResult.AccessibilityCheckResultType.INFO @@ -60,12 +59,12 @@ class ComposeA11yWithCustomCheckTest { composeRule = composeTestRule, captureRoot = composeTestRule.onRoot(), options = Options( - accessibilityChecks = ValidateAfterTest( - checker = ATFAccessibilityChecker( + accessibilityChecks = AccessibilityCheckAfterTest( + checker = RoborazziATFAccessibilityChecker( checks = setOf(NoRedTextCheck()), suppressions = matchesElements(withTestTag("suppress")) ), - failureLevel = CheckLevel.Warning, + failureLevel = RoborazziATFAccessibilityChecker.CheckLevel.Warning, ) ) ) diff --git a/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ViewA11yTest.kt b/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ViewA11yTest.kt index bb76a6c8..7cdc1983 100644 --- a/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ViewA11yTest.kt +++ b/sample-android/src/test/java/com/github/takahirom/roborazzi/sample/ViewA11yTest.kt @@ -11,9 +11,8 @@ import androidx.test.espresso.assertion.ViewAssertions import androidx.test.espresso.matcher.ViewMatchers import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.github.takahirom.roborazzi.ATFAccessibilityChecker -import com.github.takahirom.roborazzi.ValidateAfterTest -import com.github.takahirom.roborazzi.CheckLevel +import com.github.takahirom.roborazzi.RoborazziATFAccessibilityChecker +import com.github.takahirom.roborazzi.AccessibilityCheckAfterTest import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers import com.github.takahirom.roborazzi.RoborazziRule import com.github.takahirom.roborazzi.RoborazziRule.Options @@ -42,12 +41,12 @@ class ViewA11yTest { val roborazziRule = RoborazziRule( captureRoot = Espresso.onView(ViewMatchers.isRoot()), options = Options( - accessibilityChecks = ValidateAfterTest( - checker = ATFAccessibilityChecker( + accessibilityChecks = AccessibilityCheckAfterTest( + checker = RoborazziATFAccessibilityChecker( preset = AccessibilityCheckPreset.LATEST, suppressions = matchesElements(withTestTag("suppress")) ), - failureLevel = CheckLevel.Warning, + failureLevel = RoborazziATFAccessibilityChecker.CheckLevel.Warning, ) ) )