1 package org.robolectric.android; 2 3 import static org.mockito.Mockito.mock; 4 import static org.robolectric.Shadows.shadowOf; 5 6 import android.graphics.Rect; 7 import android.text.SpannableString; 8 import android.text.Spanned; 9 import android.text.style.ClickableSpan; 10 import android.view.View; 11 import android.widget.LinearLayout; 12 import android.widget.TextView; 13 import com.google.android.apps.common.testing.accessibility.framework.integrations.AccessibilityViewCheckException; 14 import org.hamcrest.Matchers; 15 import org.junit.Before; 16 import org.junit.Test; 17 import org.junit.runner.RunWith; 18 import org.robolectric.RuntimeEnvironment; 19 import org.robolectric.annotation.AccessibilityChecks; 20 import org.robolectric.annotation.AccessibilityChecks.ForRobolectricVersion; 21 import org.robolectric.util.TestRunnerWithManifest; 22 23 /** 24 * Tests for accessibility checking. The checking relies on the Accessibility Test Framework for 25 * Android, which has support-v4 as a dependency, so these tests are included where the presence 26 * of that library is guaranteed. 27 */ 28 @RunWith(TestRunnerWithManifest.class) 29 public class AccessibilityUtilTest { 30 private static final String DUPLICATE_STRING = "Duplicate"; 31 private TextView textViewWithClickableSpan; 32 private LinearLayout parentLayout; 33 private View labeledView; 34 private View unlabeledView; 35 36 @Before setUp()37 public void setUp() throws Exception { 38 Rect validViewBounds = new Rect(100, 100, 200, 200); 39 40 // Set the statics back to their default values 41 AccessibilityUtil.setRunChecksForRobolectricVersion(null); 42 AccessibilityUtil.setSuppressingResultMatcher(null); 43 AccessibilityUtil.setRunChecksFromRootView(false); 44 AccessibilityUtil.setThrowExceptionForErrors(true); 45 46 labeledView = new View(RuntimeEnvironment.application); 47 labeledView.setContentDescription("Something"); 48 labeledView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); 49 labeledView.setClickable(true); 50 // Force the views on the screen so they'll be seen as visible even though they aren't 51 // part of a valid view hierarchy 52 shadowOf(labeledView).setGlobalVisibleRect(validViewBounds); 53 54 unlabeledView = new View(RuntimeEnvironment.application); 55 unlabeledView.setContentDescription(null); 56 unlabeledView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); 57 unlabeledView.setClickable(true); 58 shadowOf(unlabeledView).setGlobalVisibleRect(validViewBounds); 59 60 parentLayout = new LinearLayout(RuntimeEnvironment.application); 61 parentLayout.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); 62 parentLayout.addView(labeledView); 63 shadowOf(parentLayout).setGlobalVisibleRect(validViewBounds); 64 65 textViewWithClickableSpan = new TextView(RuntimeEnvironment.application); 66 SpannableString spannableString = new SpannableString("Some text"); 67 ClickableSpan mockClickableSpan = mock(ClickableSpan.class); 68 spannableString.setSpan(mockClickableSpan, 0, 1, Spanned.SPAN_COMPOSING); 69 textViewWithClickableSpan.setText(spannableString); 70 shadowOf(textViewWithClickableSpan).setGlobalVisibleRect(validViewBounds); 71 } 72 73 @Test(expected = AccessibilityViewCheckException.class) checkUnlabeledView_shouldThrow()74 public void checkUnlabeledView_shouldThrow() throws Exception { 75 AccessibilityUtil.checkView(unlabeledView); 76 } 77 78 @Test checkOKView_shouldNotThrow()79 public void checkOKView_shouldNotThrow() throws Exception { 80 AccessibilityUtil.checkView(labeledView); 81 } 82 83 @Test default_viewWithSiblingIssue_shouldNotThrow()84 public void default_viewWithSiblingIssue_shouldNotThrow() throws Exception { 85 parentLayout.addView(unlabeledView); 86 AccessibilityUtil.checkView(labeledView); 87 } 88 89 @Test(expected = AccessibilityViewCheckException.class) whenCheckingFromRoot_viewWithSiblingIssue_shouldThrow()90 public void whenCheckingFromRoot_viewWithSiblingIssue_shouldThrow() throws Exception { 91 parentLayout.addView(unlabeledView); 92 AccessibilityUtil.setRunChecksFromRootView(true); 93 AccessibilityUtil.checkView(labeledView); 94 } 95 96 @Test(expected = AccessibilityViewCheckException.class) 97 @AccessibilityChecks whenAnnotationPresent_conditionalCheckRun()98 public void whenAnnotationPresent_conditionalCheckRun() { 99 AccessibilityUtil.checkViewIfCheckingEnabled(unlabeledView); 100 } 101 102 @Test whenAnnotationNotPresent_conditionalCheckNotRun()103 public void whenAnnotationNotPresent_conditionalCheckNotRun() { 104 AccessibilityUtil.checkViewIfCheckingEnabled(unlabeledView); 105 } 106 107 @Test(expected = AccessibilityViewCheckException.class) framework2pt0Error_byDefault_shouldThrow()108 public void framework2pt0Error_byDefault_shouldThrow() throws Exception { 109 AccessibilityUtil.checkView(textViewWithClickableSpan); 110 } 111 112 @Test framework2pt0Error_whenCheckingForRL3pt0_shouldNotThrow()113 public void framework2pt0Error_whenCheckingForRL3pt0_shouldNotThrow() throws Exception { 114 AccessibilityUtil.setRunChecksForRobolectricVersion(ForRobolectricVersion.VERSION_3_0); 115 AccessibilityUtil.checkView(textViewWithClickableSpan); 116 } 117 118 @Test 119 @AccessibilityChecks(forRobolectricVersion = ForRobolectricVersion.VERSION_3_0) framework2pt0Error_annotationForRL3pt0_shouldNotThrow()120 public void framework2pt0Error_annotationForRL3pt0_shouldNotThrow() throws Exception { 121 AccessibilityUtil.checkView(textViewWithClickableSpan); 122 } 123 124 @Test(expected = AccessibilityViewCheckException.class) 125 @AccessibilityChecks(forRobolectricVersion = ForRobolectricVersion.VERSION_3_0) framework2pt0Error_codeForcesRL3pt1_shouldThrow()126 public void framework2pt0Error_codeForcesRL3pt1_shouldThrow() throws Exception { 127 AccessibilityUtil.setRunChecksForRobolectricVersion(ForRobolectricVersion.VERSION_3_1); 128 AccessibilityUtil.checkView(textViewWithClickableSpan); 129 } 130 131 @Test whenSuppressingResults_shouldNotThrow()132 public void whenSuppressingResults_shouldNotThrow() throws Exception { 133 AccessibilityUtil.setSuppressingResultMatcher(Matchers.anything()); 134 AccessibilityUtil.checkView(unlabeledView); 135 } 136 137 @Test whenOnlyPrintingResults_shouldNotThrow()138 public void whenOnlyPrintingResults_shouldNotThrow() throws Exception { 139 AccessibilityUtil.setThrowExceptionForErrors(false); 140 AccessibilityUtil.checkView(unlabeledView); 141 } 142 143 @Test warningIssue_shouldNotThrow()144 public void warningIssue_shouldNotThrow() throws Exception { 145 labeledView.setContentDescription(DUPLICATE_STRING); 146 parentLayout.setContentDescription(DUPLICATE_STRING); 147 parentLayout.setClickable(true); 148 AccessibilityUtil.checkView(parentLayout); 149 } 150 151 } 152 153