1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.setupwizardlib.test; 18 19import android.graphics.Rect; 20import android.os.Bundle; 21import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; 22import android.support.v4.widget.ExploreByTouchHelper; 23import android.test.AndroidTestCase; 24import android.test.suitebuilder.annotation.SmallTest; 25import android.text.SpannableStringBuilder; 26import android.util.DisplayMetrics; 27import android.util.TypedValue; 28import android.view.accessibility.AccessibilityEvent; 29import android.widget.TextView; 30 31import com.android.setupwizardlib.span.LinkSpan; 32import com.android.setupwizardlib.util.LinkAccessibilityHelper; 33 34import java.util.ArrayList; 35import java.util.Collections; 36import java.util.List; 37 38public class LinkAccessibilityHelperTest extends AndroidTestCase { 39 40 private TextView mTextView; 41 private TestLinkAccessibilityHelper mHelper; 42 private LinkSpan mSpan; 43 44 private DisplayMetrics mDisplayMetrics; 45 46 @Override 47 protected void setUp() throws Exception { 48 super.setUp(); 49 mSpan = new LinkSpan("foobar"); 50 SpannableStringBuilder ssb = new SpannableStringBuilder("Hello world"); 51 ssb.setSpan(mSpan, 1, 2, 0 /* flags */); 52 53 mTextView = new TextView(getContext()); 54 mTextView.setText(ssb); 55 mTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); 56 mHelper = new TestLinkAccessibilityHelper(mTextView); 57 58 mTextView.measure(dp2Px(500), dp2Px(500)); 59 mTextView.layout(dp2Px(0), dp2Px(0), dp2Px(500), dp2Px(500)); 60 } 61 62 @SmallTest 63 public void testGetVirtualViewAt() { 64 final int virtualViewId = mHelper.getVirtualViewAt(dp2Px(15), dp2Px(10)); 65 assertEquals("Virtual view ID should be 1", 1, virtualViewId); 66 } 67 68 @SmallTest 69 public void testGetVirtualViewAtHost() { 70 final int virtualViewId = mHelper.getVirtualViewAt(dp2Px(100), dp2Px(100)); 71 assertEquals("Virtual view ID should be INVALID_ID", 72 ExploreByTouchHelper.INVALID_ID, virtualViewId); 73 } 74 75 @SmallTest 76 public void testGetVisibleVirtualViews() { 77 List<Integer> virtualViewIds = new ArrayList<>(); 78 mHelper.getVisibleVirtualViews(virtualViewIds); 79 80 assertEquals("VisibleVirtualViews should be [1]", 81 Collections.singletonList(1), virtualViewIds); 82 } 83 84 @SmallTest 85 public void testOnPopulateEventForVirtualView() { 86 AccessibilityEvent event = AccessibilityEvent.obtain(); 87 mHelper.onPopulateEventForVirtualView(1, event); 88 89 // LinkSpan is set on substring(1, 2) of "Hello world" --> "e" 90 assertEquals("LinkSpan description should be \"e\"", 91 "e", event.getContentDescription().toString()); 92 93 event.recycle(); 94 } 95 96 @SmallTest 97 public void testOnPopulateEventForVirtualViewHost() { 98 AccessibilityEvent event = AccessibilityEvent.obtain(); 99 mHelper.onPopulateEventForVirtualView(ExploreByTouchHelper.INVALID_ID, event); 100 101 assertEquals("Host view description should be \"Hello world\"", "Hello world", 102 event.getContentDescription().toString()); 103 104 event.recycle(); 105 } 106 107 @SmallTest 108 public void testOnPopulateNodeForVirtualView() { 109 AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 110 mHelper.onPopulateNodeForVirtualView(1, info); 111 112 assertEquals("LinkSpan description should be \"e\"", 113 "e", info.getContentDescription().toString()); 114 assertTrue("LinkSpan should be focusable", info.isFocusable()); 115 assertTrue("LinkSpan should be clickable", info.isClickable()); 116 Rect bounds = new Rect(); 117 info.getBoundsInParent(bounds); 118 assertEquals("LinkSpan bounds should be (10.5dp, 0dp, 18.5dp, 20.5dp)", 119 new Rect(dp2Px(10.5f), dp2Px(0f), dp2Px(18.5f), dp2Px(20.5f)), bounds); 120 121 info.recycle(); 122 } 123 124 @SmallTest 125 public void testNullLayout() { 126 // Setting the padding will cause the layout to be null-ed out. 127 mTextView.setPadding(1, 1, 1, 1); 128 129 AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 130 mHelper.onPopulateNodeForVirtualView(0, info); 131 132 Rect bounds = new Rect(); 133 info.getBoundsInParent(bounds); 134 assertEquals("LinkSpan bounds should be (0, 0, 1, 1)", 135 new Rect(0, 0, 1, 1), bounds); 136 137 info.recycle(); 138 } 139 140 @SmallTest 141 public void testRtlLayout() { 142 // Redo setUp with a Hebrew (RTL) string. 143 mSpan = new LinkSpan("foobar"); 144 SpannableStringBuilder ssb = new SpannableStringBuilder("מכונה בתרגום"); 145 ssb.setSpan(mSpan, 1, 2, 0 /* flags */); 146 147 mTextView = new TextView(getContext()); 148 mTextView.setText(ssb); 149 mTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); 150 mHelper = new TestLinkAccessibilityHelper(mTextView); 151 152 mTextView.measure(dp2Px(500), dp2Px(500)); 153 mTextView.layout(dp2Px(0), dp2Px(0), dp2Px(500), dp2Px(500)); 154 // End redo setup 155 156 AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 157 mHelper.onPopulateNodeForVirtualView(1, info); 158 159 assertEquals("LinkSpan description should be \"כ\"", 160 "כ", info.getContentDescription().toString()); 161 assertTrue("LinkSpan should be focusable", info.isFocusable()); 162 assertTrue("LinkSpan should be clickable", info.isClickable()); 163 Rect bounds = new Rect(); 164 info.getBoundsInParent(bounds); 165 assertEquals("LinkSpan bounds should be (70.5dp, 0dp, 78.5dp, 20.5dp)", 166 new Rect(dp2Px(70.5f), dp2Px(0f), dp2Px(78.5f), dp2Px(20.5f)), bounds); 167 168 info.recycle(); 169 } 170 171 private int dp2Px(float dp) { 172 if (mDisplayMetrics == null) { 173 mDisplayMetrics = getContext().getResources().getDisplayMetrics(); 174 } 175 return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mDisplayMetrics); 176 } 177 178 private static class TestLinkAccessibilityHelper extends LinkAccessibilityHelper { 179 180 public TestLinkAccessibilityHelper(TextView view) { 181 super(view); 182 } 183 184 @Override 185 public int getVirtualViewAt(float x, float y) { 186 return super.getVirtualViewAt(x, y); 187 } 188 189 @Override 190 public void getVisibleVirtualViews(List<Integer> virtualViewIds) { 191 super.getVisibleVirtualViews(virtualViewIds); 192 } 193 194 @Override 195 public void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) { 196 super.onPopulateEventForVirtualView(virtualViewId, event); 197 } 198 199 @Override 200 public void onPopulateNodeForVirtualView(int virtualViewId, 201 AccessibilityNodeInfoCompat info) { 202 super.onPopulateNodeForVirtualView(virtualViewId, info); 203 } 204 205 @Override 206 public boolean onPerformActionForVirtualView(int virtualViewId, int action, 207 Bundle arguments) { 208 return super.onPerformActionForVirtualView(virtualViewId, action, arguments); 209 } 210 } 211} 212