TextViewActivityTest.java revision 4bc3c9c100901ea10c755d78c4dd496e021c9379
1/* 2 * Copyright (C) 2015 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 android.widget; 18 19import static android.widget.espresso.CustomViewActions.longPressAtRelativeCoordinates; 20import static android.support.test.espresso.action.ViewActions.longClick; 21import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles; 22import static android.widget.espresso.DragHandleUtils.onHandleView; 23import static android.widget.espresso.FloatingToolbarEspressoUtils.onFloatingToolBarItem; 24import static android.widget.espresso.TextViewActions.clickOnTextAtIndex; 25import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText; 26import static android.widget.espresso.TextViewActions.doubleClickOnTextAtIndex; 27import static android.widget.espresso.TextViewActions.dragHandle; 28import static android.widget.espresso.TextViewActions.Handle; 29import static android.widget.espresso.TextViewActions.longPressAndDragOnText; 30import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex; 31import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex; 32import static android.widget.espresso.TextViewAssertions.hasSelection; 33import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed; 34import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsNotDisplayed; 35import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup; 36import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem; 37import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarDoesNotContainItem; 38import static android.support.test.espresso.Espresso.onView; 39import static android.support.test.espresso.action.ViewActions.click; 40import static android.support.test.espresso.action.ViewActions.pressKey; 41import static android.support.test.espresso.action.ViewActions.replaceText; 42import static android.support.test.espresso.action.ViewActions.typeTextIntoFocusedView; 43import static android.support.test.espresso.assertion.ViewAssertions.matches; 44import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; 45import static android.support.test.espresso.matcher.ViewMatchers.withId; 46import static android.support.test.espresso.matcher.ViewMatchers.withText; 47 48import android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider; 49import com.android.frameworks.coretests.R; 50 51import android.support.test.espresso.action.EspressoKey; 52import android.test.ActivityInstrumentationTestCase2; 53import android.test.suitebuilder.annotation.SmallTest; 54import android.text.Selection; 55import android.text.Spannable; 56import android.text.InputType; 57import android.view.KeyEvent; 58 59import static org.hamcrest.Matchers.anyOf; 60import static org.hamcrest.Matchers.is; 61 62/** 63 * Tests the TextView widget from an Activity 64 */ 65public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextViewActivity>{ 66 67 public TextViewActivityTest() { 68 super(TextViewActivity.class); 69 } 70 71 @Override 72 public void setUp() { 73 getActivity(); 74 } 75 76 @SmallTest 77 public void testTypedTextIsOnScreen() throws Exception { 78 final String helloWorld = "Hello world!"; 79 onView(withId(R.id.textview)).perform(click()); 80 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); 81 82 onView(withId(R.id.textview)).check(matches(withText(helloWorld))); 83 } 84 85 @SmallTest 86 public void testPositionCursorAtTextAtIndex() throws Exception { 87 final String helloWorld = "Hello world!"; 88 onView(withId(R.id.textview)).perform(click()); 89 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); 90 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(helloWorld.indexOf("world"))); 91 92 // Delete text at specified index and see if we got the right one. 93 onView(withId(R.id.textview)).perform(pressKey(KeyEvent.KEYCODE_FORWARD_DEL)); 94 onView(withId(R.id.textview)).check(matches(withText("Hello orld!"))); 95 } 96 97 @SmallTest 98 public void testPositionCursorAtTextAtIndex_arabic() throws Exception { 99 // Arabic text. The expected cursorable boundary is 100 // | \u0623 \u064F | \u067A | \u0633 \u0652 | 101 final String text = "\u0623\u064F\u067A\u0633\u0652"; 102 onView(withId(R.id.textview)).perform(click()); 103 onView(withId(R.id.textview)).perform(replaceText(text)); 104 105 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0)); 106 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0)); 107 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(1)); 108 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(0), is(2)))); 109 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(2)); 110 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2)); 111 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(3)); 112 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(3)); 113 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(4)); 114 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(3), is(5)))); 115 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(5)); 116 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(5)); 117 } 118 119 @SmallTest 120 public void testPositionCursorAtTextAtIndex_devanagari() throws Exception { 121 // Devanagari text. The expected cursorable boundary is | \u0915 \u093E | 122 final String text = "\u0915\u093E"; 123 onView(withId(R.id.textview)).perform(click()); 124 onView(withId(R.id.textview)).perform(replaceText(text)); 125 126 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0)); 127 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0)); 128 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(1)); 129 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(0), is(2)))); 130 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(2)); 131 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2)); 132 } 133 134 @SmallTest 135 public void testLongPressToSelect() throws Exception { 136 final String helloWorld = "Hello Kirk!"; 137 onView(withId(R.id.textview)).perform(click()); 138 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); 139 onView(withId(R.id.textview)).perform( 140 longPressOnTextAtIndex(helloWorld.indexOf("Kirk"))); 141 142 onView(withId(R.id.textview)).check(hasSelection("Kirk")); 143 } 144 145 @SmallTest 146 public void testLongPressEmptySpace() throws Exception { 147 final String helloWorld = "Hello big round sun!"; 148 onView(withId(R.id.textview)).perform(click()); 149 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); 150 // Move cursor somewhere else 151 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(helloWorld.indexOf("big"))); 152 // Long-press at end of line. 153 onView(withId(R.id.textview)).perform(longPressAtRelativeCoordinates( 154 RelativeCoordinatesProvider.HorizontalReference.RIGHT, -5, 155 RelativeCoordinatesProvider.VerticalReference.CENTER, 0)); 156 157 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(helloWorld.length())); 158 } 159 160 @SmallTest 161 public void testLongPressAndDragToSelect() throws Exception { 162 final String helloWorld = "Hello little handsome boy!"; 163 onView(withId(R.id.textview)).perform(click()); 164 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); 165 onView(withId(R.id.textview)).perform( 166 longPressAndDragOnText(helloWorld.indexOf("little"), helloWorld.indexOf(" boy!"))); 167 168 onView(withId(R.id.textview)).check(hasSelection("little handsome")); 169 } 170 171 @SmallTest 172 public void testDragAndDrop() throws Exception { 173 final String text = "abc def ghi."; 174 onView(withId(R.id.textview)).perform(click()); 175 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 176 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf("e"))); 177 178 onView(withId(R.id.textview)).perform( 179 longPressAndDragOnText(text.indexOf("e"), text.length())); 180 181 onView(withId(R.id.textview)).check(matches(withText("abc ghi.def"))); 182 onView(withId(R.id.textview)).check(hasSelection("")); 183 assertNoSelectionHandles(); 184 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex("abc ghi.def".length())); 185 186 // Test undo returns to the original state. 187 onView(withId(R.id.textview)).perform(pressKey( 188 (new EspressoKey.Builder()).withCtrlPressed(true).withKeyCode(KeyEvent.KEYCODE_Z) 189 .build())); 190 onView(withId(R.id.textview)).check(matches(withText(text))); 191 } 192 193 @SmallTest 194 public void testDoubleTapToSelect() throws Exception { 195 final String helloWorld = "Hello SuetYi!"; 196 onView(withId(R.id.textview)).perform(click()); 197 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); 198 onView(withId(R.id.textview)).perform( 199 doubleClickOnTextAtIndex(helloWorld.indexOf("SuetYi"))); 200 201 onView(withId(R.id.textview)).check(hasSelection("SuetYi")); 202 } 203 204 @SmallTest 205 public void testDoubleTapAndDragToSelect() throws Exception { 206 final String helloWorld = "Hello young beautiful girl!"; 207 onView(withId(R.id.textview)).perform(click()); 208 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); 209 onView(withId(R.id.textview)).perform( 210 doubleTapAndDragOnText(helloWorld.indexOf("young"), helloWorld.indexOf(" girl!"))); 211 212 onView(withId(R.id.textview)).check(hasSelection("young beautiful")); 213 } 214 215 @SmallTest 216 public void testSelectBackwordsByTouch() throws Exception { 217 final String helloWorld = "Hello king of the Jungle!"; 218 onView(withId(R.id.textview)).perform(click()); 219 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); 220 onView(withId(R.id.textview)).perform( 221 doubleTapAndDragOnText(helloWorld.indexOf(" Jungle!"), helloWorld.indexOf("king"))); 222 223 onView(withId(R.id.textview)).check(hasSelection("king of the")); 224 } 225 226 @SmallTest 227 public void testToolbarAppearsAfterSelection() throws Exception { 228 final String text = "Toolbar appears after selection."; 229 onView(withId(R.id.textview)).perform(click()); 230 assertFloatingToolbarIsNotDisplayed(); 231 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 232 onView(withId(R.id.textview)).perform( 233 longPressOnTextAtIndex(text.indexOf("appears"))); 234 235 sleepForFloatingToolbarPopup(); 236 assertFloatingToolbarIsDisplayed(); 237 238 final String text2 = "Toolbar disappears after typing text."; 239 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text2)); 240 assertFloatingToolbarIsNotDisplayed(); 241 } 242 243 @SmallTest 244 public void testToolbarAppearsAfterSelection_withFirstStringLtrAlgorithmAndRtlHint() 245 throws Exception { 246 // after the hint layout change, the floating toolbar was not visible in the case below 247 // this test tests that the floating toolbar is displayed on the screen and is visible to 248 // user. 249 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 250 textView.post(new Runnable() { 251 @Override 252 public void run() { 253 textView.setTextDirection(TextView.TEXT_DIRECTION_FIRST_STRONG_LTR); 254 textView.setInputType(InputType.TYPE_CLASS_TEXT); 255 textView.setSingleLine(true); 256 textView.setHint("الروبوت"); 257 } 258 }); 259 getInstrumentation().waitForIdleSync(); 260 261 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView("test")); 262 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(1)); 263 onFloatingToolBarItem(withText(com.android.internal.R.string.cut)).perform(click()); 264 onView(withId(R.id.textview)).perform(longClick()); 265 sleepForFloatingToolbarPopup(); 266 267 assertFloatingToolbarIsDisplayed(); 268 } 269 270 @SmallTest 271 public void testToolbarAndInsertionHandle() throws Exception { 272 final String text = "text"; 273 onView(withId(R.id.textview)).perform(click()); 274 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 275 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 276 assertFloatingToolbarIsNotDisplayed(); 277 278 onHandleView(com.android.internal.R.id.insertion_handle).perform(click()); 279 sleepForFloatingToolbarPopup(); 280 assertFloatingToolbarIsDisplayed(); 281 282 assertFloatingToolbarContainsItem( 283 getActivity().getString(com.android.internal.R.string.selectAll)); 284 assertFloatingToolbarDoesNotContainItem( 285 getActivity().getString(com.android.internal.R.string.copy)); 286 assertFloatingToolbarDoesNotContainItem( 287 getActivity().getString(com.android.internal.R.string.cut)); 288 } 289 290 @SmallTest 291 public void testToolbarAndSelectionHandle() throws Exception { 292 final String text = "abcd efg hijk"; 293 onView(withId(R.id.textview)).perform(click()); 294 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 295 296 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf("f"))); 297 sleepForFloatingToolbarPopup(); 298 assertFloatingToolbarIsDisplayed(); 299 300 assertFloatingToolbarContainsItem( 301 getActivity().getString(com.android.internal.R.string.selectAll)); 302 assertFloatingToolbarContainsItem( 303 getActivity().getString(com.android.internal.R.string.copy)); 304 assertFloatingToolbarContainsItem( 305 getActivity().getString(com.android.internal.R.string.cut)); 306 307 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 308 onHandleView(com.android.internal.R.id.selection_start_handle) 309 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 310 sleepForFloatingToolbarPopup(); 311 assertFloatingToolbarIsDisplayed(); 312 313 onHandleView(com.android.internal.R.id.selection_end_handle) 314 .perform(dragHandle(textView, Handle.SELECTION_END, text.length())); 315 sleepForFloatingToolbarPopup(); 316 assertFloatingToolbarIsDisplayed(); 317 318 assertFloatingToolbarDoesNotContainItem( 319 getActivity().getString(com.android.internal.R.string.selectAll)); 320 assertFloatingToolbarContainsItem( 321 getActivity().getString(com.android.internal.R.string.copy)); 322 assertFloatingToolbarContainsItem( 323 getActivity().getString(com.android.internal.R.string.cut)); 324 } 325 326 @SmallTest 327 public void testInsertionHandle() throws Exception { 328 final String text = "abcd efg hijk "; 329 onView(withId(R.id.textview)).perform(click()); 330 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 331 332 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 333 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.length())); 334 335 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 336 337 onHandleView(com.android.internal.R.id.insertion_handle) 338 .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('a'))); 339 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("a"))); 340 341 onHandleView(com.android.internal.R.id.insertion_handle) 342 .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('f'))); 343 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("f"))); 344 } 345 346 @SmallTest 347 public void testInsertionHandle_multiLine() throws Exception { 348 final String text = "abcd\n" + "efg\n" + "hijk\n"; 349 onView(withId(R.id.textview)).perform(click()); 350 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 351 352 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 353 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.length())); 354 355 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 356 357 onHandleView(com.android.internal.R.id.insertion_handle) 358 .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('a'))); 359 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("a"))); 360 361 onHandleView(com.android.internal.R.id.insertion_handle) 362 .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('f'))); 363 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("f"))); 364 } 365 366 @SmallTest 367 public void testSelectionHandles() throws Exception { 368 final String text = "abcd efg hijk lmn"; 369 onView(withId(R.id.textview)).perform(click()); 370 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 371 372 assertNoSelectionHandles(); 373 374 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('f'))); 375 376 onHandleView(com.android.internal.R.id.selection_start_handle) 377 .check(matches(isDisplayed())); 378 onHandleView(com.android.internal.R.id.selection_end_handle) 379 .check(matches(isDisplayed())); 380 381 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 382 onHandleView(com.android.internal.R.id.selection_start_handle) 383 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 384 onView(withId(R.id.textview)).check(hasSelection("abcd efg")); 385 386 onHandleView(com.android.internal.R.id.selection_end_handle) 387 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('k') + 1)); 388 onView(withId(R.id.textview)).check(hasSelection("abcd efg hijk")); 389 } 390 391 @SmallTest 392 public void testSelectionHandles_multiLine() throws Exception { 393 final String text = "abcd\n" + "efg\n" + "hijk\n" + "lmn\n" + "opqr"; 394 onView(withId(R.id.textview)).perform(click()); 395 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 396 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 397 398 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 399 onHandleView(com.android.internal.R.id.selection_start_handle) 400 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('e'))); 401 onView(withId(R.id.textview)).check(hasSelection("efg\nhijk")); 402 403 onHandleView(com.android.internal.R.id.selection_start_handle) 404 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 405 onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk")); 406 407 onHandleView(com.android.internal.R.id.selection_end_handle) 408 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('n') + 1)); 409 onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk\nlmn")); 410 411 onHandleView(com.android.internal.R.id.selection_end_handle) 412 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('r') + 1)); 413 onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk\nlmn\nopqr")); 414 } 415 416 @SmallTest 417 public void testSelectionHandles_multiLine_rtl() throws Exception { 418 // Arabic text. 419 final String text = "\u062A\u062B\u062C\n" + "\u062D\u062E\u062F\n" 420 + "\u0630\u0631\u0632\n" + "\u0633\u0634\u0635\n" + "\u0636\u0637\u0638\n" 421 + "\u0639\u063A\u063B"; 422 onView(withId(R.id.textview)).perform(click()); 423 onView(withId(R.id.textview)).perform(replaceText(text)); 424 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 425 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('\u0634'))); 426 427 final TextView textView = (TextView)getActivity().findViewById(R.id.textview); 428 onHandleView(com.android.internal.R.id.selection_start_handle) 429 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u062E'))); 430 onView(withId(R.id.textview)).check(hasSelection( 431 text.substring(text.indexOf('\u062D'), text.indexOf('\u0635') + 1))); 432 433 onHandleView(com.android.internal.R.id.selection_start_handle) 434 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u062A'))); 435 onView(withId(R.id.textview)).check(hasSelection( 436 text.substring(text.indexOf('\u062A'), text.indexOf('\u0635') + 1))); 437 438 onHandleView(com.android.internal.R.id.selection_end_handle) 439 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('\u0638'))); 440 onView(withId(R.id.textview)).check(hasSelection( 441 text.substring(text.indexOf('\u062A'), text.indexOf('\u0638') + 1))); 442 443 onHandleView(com.android.internal.R.id.selection_end_handle) 444 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('\u063B'))); 445 onView(withId(R.id.textview)).check(hasSelection(text)); 446 } 447 448 449 @SmallTest 450 public void testSelectionHandles_doesNotPassAnotherHandle() throws Exception { 451 final String text = "abcd efg hijk lmn"; 452 onView(withId(R.id.textview)).perform(click()); 453 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 454 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('f'))); 455 456 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 457 onHandleView(com.android.internal.R.id.selection_start_handle) 458 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('l'))); 459 onView(withId(R.id.textview)).check(hasSelection("g")); 460 461 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('f'))); 462 onHandleView(com.android.internal.R.id.selection_end_handle) 463 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('a'))); 464 onView(withId(R.id.textview)).check(hasSelection("e")); 465 } 466 467 @SmallTest 468 public void testSelectionHandles_doesNotPassAnotherHandle_multiLine() throws Exception { 469 final String text = "abcd\n" + "efg\n" + "hijk\n" + "lmn\n" + "opqr"; 470 onView(withId(R.id.textview)).perform(click()); 471 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 472 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 473 474 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 475 onHandleView(com.android.internal.R.id.selection_start_handle) 476 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('r') + 1)); 477 onView(withId(R.id.textview)).check(hasSelection("k")); 478 479 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 480 onHandleView(com.android.internal.R.id.selection_end_handle) 481 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('a'))); 482 onView(withId(R.id.textview)).check(hasSelection("h")); 483 } 484 485 @SmallTest 486 public void testSelectionHandles_snapToWordBoundary() throws Exception { 487 final String text = "abcd efg hijk lmn opqr"; 488 onView(withId(R.id.textview)).perform(click()); 489 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 490 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 491 492 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 493 494 onHandleView(com.android.internal.R.id.selection_start_handle) 495 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('f'))); 496 onView(withId(R.id.textview)).check(hasSelection("efg hijk")); 497 498 onHandleView(com.android.internal.R.id.selection_start_handle) 499 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('d') + 1)); 500 onView(withId(R.id.textview)).check(hasSelection("efg hijk")); 501 502 503 onHandleView(com.android.internal.R.id.selection_start_handle) 504 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('c'))); 505 onView(withId(R.id.textview)).check(hasSelection("abcd efg hijk")); 506 507 onHandleView(com.android.internal.R.id.selection_start_handle) 508 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('d'))); 509 onView(withId(R.id.textview)).check(hasSelection("d efg hijk")); 510 511 onHandleView(com.android.internal.R.id.selection_start_handle) 512 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('b'))); 513 onView(withId(R.id.textview)).check(hasSelection("bcd efg hijk")); 514 515 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 516 517 onHandleView(com.android.internal.R.id.selection_end_handle) 518 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('n'))); 519 onView(withId(R.id.textview)).check(hasSelection("hijk lmn")); 520 521 onHandleView(com.android.internal.R.id.selection_end_handle) 522 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('o'))); 523 onView(withId(R.id.textview)).check(hasSelection("hijk lmn")); 524 525 onHandleView(com.android.internal.R.id.selection_end_handle) 526 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('q'))); 527 onView(withId(R.id.textview)).check(hasSelection("hijk lmn opqr")); 528 529 onHandleView(com.android.internal.R.id.selection_end_handle) 530 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('p'))); 531 onView(withId(R.id.textview)).check(hasSelection("hijk lmn o")); 532 533 onHandleView(com.android.internal.R.id.selection_end_handle) 534 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('r'))); 535 onView(withId(R.id.textview)).check(hasSelection("hijk lmn opq")); 536 } 537 538 @SmallTest 539 public void testSelectionHandles_snapToWordBoundary_multiLine() throws Exception { 540 final String text = "abcd efg\n" + "hijk lmn\n" + "opqr stu"; 541 onView(withId(R.id.textview)).perform(click()); 542 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 543 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('m'))); 544 545 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 546 547 onHandleView(com.android.internal.R.id.selection_start_handle) 548 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('c'))); 549 onView(withId(R.id.textview)).check(hasSelection("abcd efg\nhijk lmn")); 550 551 onHandleView(com.android.internal.R.id.selection_start_handle) 552 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('g'))); 553 onView(withId(R.id.textview)).check(hasSelection("g\nhijk lmn")); 554 555 onHandleView(com.android.internal.R.id.selection_start_handle) 556 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('m'))); 557 onView(withId(R.id.textview)).check(hasSelection("lmn")); 558 559 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 560 561 onHandleView(com.android.internal.R.id.selection_end_handle) 562 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('u'))); 563 onView(withId(R.id.textview)).check(hasSelection("hijk lmn\nopqr stu")); 564 565 onHandleView(com.android.internal.R.id.selection_end_handle) 566 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('p'))); 567 onView(withId(R.id.textview)).check(hasSelection("hijk lmn\no")); 568 569 onHandleView(com.android.internal.R.id.selection_end_handle) 570 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('i'))); 571 onView(withId(R.id.textview)).check(hasSelection("hijk")); 572 } 573 574 @SmallTest 575 public void testSetSelectionAndActionMode() throws Exception { 576 final String text = "abc def"; 577 onView(withId(R.id.textview)).perform(click()); 578 onView(withId(R.id.textview)).perform(replaceText(text)); 579 580 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 581 assertFloatingToolbarIsNotDisplayed(); 582 textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0, 3)); 583 getInstrumentation().waitForIdleSync(); 584 sleepForFloatingToolbarPopup(); 585 // Don't automatically start action mode. 586 assertFloatingToolbarIsNotDisplayed(); 587 // Make sure that "Select All" is included in the selection action mode when the entire text 588 // is not selected. 589 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('e'))); 590 sleepForFloatingToolbarPopup(); 591 assertFloatingToolbarIsDisplayed(); 592 // Changing the selection range by API should not interrupt the selection action mode. 593 textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0, 3)); 594 getInstrumentation().waitForIdleSync(); 595 sleepForFloatingToolbarPopup(); 596 assertFloatingToolbarIsDisplayed(); 597 assertFloatingToolbarContainsItem( 598 getActivity().getString(com.android.internal.R.string.selectAll)); 599 // Make sure that "Select All" is no longer included when the entire text is selected by 600 // API. 601 textView.post( 602 () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length())); 603 getInstrumentation().waitForIdleSync(); 604 sleepForFloatingToolbarPopup(); 605 assertFloatingToolbarIsDisplayed(); 606 assertFloatingToolbarDoesNotContainItem( 607 getActivity().getString(com.android.internal.R.string.selectAll)); 608 // Make sure that shrinking the selection range to cursor (an empty range) by API 609 // terminates selection action mode and does not trigger the insertion action mode. 610 textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0)); 611 getInstrumentation().waitForIdleSync(); 612 sleepForFloatingToolbarPopup(); 613 assertFloatingToolbarIsNotDisplayed(); 614 // Make sure that user click can trigger the insertion action mode. 615 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 616 onHandleView(com.android.internal.R.id.insertion_handle).perform(click()); 617 sleepForFloatingToolbarPopup(); 618 assertFloatingToolbarIsDisplayed(); 619 // Make sure that an existing insertion action mode keeps alive after the insertion point is 620 // moved by API. 621 textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0)); 622 getInstrumentation().waitForIdleSync(); 623 sleepForFloatingToolbarPopup(); 624 assertFloatingToolbarIsDisplayed(); 625 assertFloatingToolbarDoesNotContainItem( 626 getActivity().getString(com.android.internal.R.string.copy)); 627 // Make sure that selection action mode is started after selection is created by API when 628 // insertion action mode is active. 629 textView.post( 630 () -> Selection.setSelection((Spannable) textView.getText(), 1, text.length())); 631 getInstrumentation().waitForIdleSync(); 632 sleepForFloatingToolbarPopup(); 633 assertFloatingToolbarIsDisplayed(); 634 assertFloatingToolbarContainsItem( 635 getActivity().getString(com.android.internal.R.string.copy)); 636 } 637} 638