TextViewActivityTest.java revision 15485b8cae00133ac46a9b36db8e228aa8e73741
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_bidi() throws Exception { 393 final String text = "abc \u0621\u0622\u0623 def"; 394 onView(withId(R.id.textview)).perform(click()); 395 onView(withId(R.id.textview)).perform(replaceText(text)); 396 397 assertNoSelectionHandles(); 398 399 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('\u0622'))); 400 401 onHandleView(com.android.internal.R.id.selection_start_handle) 402 .check(matches(isDisplayed())); 403 onHandleView(com.android.internal.R.id.selection_end_handle) 404 .check(matches(isDisplayed())); 405 406 onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 407 408 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 409 onHandleView(com.android.internal.R.id.selection_start_handle) 410 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('f'))); 411 onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 412 413 onHandleView(com.android.internal.R.id.selection_end_handle) 414 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('a'))); 415 onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 416 417 onHandleView(com.android.internal.R.id.selection_start_handle) 418 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u0623') + 1, 419 false)); 420 onView(withId(R.id.textview)).check(hasSelection("\u0623")); 421 422 onHandleView(com.android.internal.R.id.selection_start_handle) 423 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u0621'), 424 false)); 425 onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 426 427 onHandleView(com.android.internal.R.id.selection_start_handle) 428 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 429 onView(withId(R.id.textview)).check(hasSelection("abc \u0621\u0622\u0623")); 430 431 onHandleView(com.android.internal.R.id.selection_end_handle) 432 .perform(dragHandle(textView, Handle.SELECTION_END, text.length())); 433 onView(withId(R.id.textview)).check(hasSelection("abc \u0621\u0622\u0623 def")); 434 } 435 436 @SmallTest 437 public void testSelectionHandles_multiLine() throws Exception { 438 final String text = "abcd\n" + "efg\n" + "hijk\n" + "lmn\n" + "opqr"; 439 onView(withId(R.id.textview)).perform(click()); 440 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 441 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 442 443 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 444 onHandleView(com.android.internal.R.id.selection_start_handle) 445 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('e'))); 446 onView(withId(R.id.textview)).check(hasSelection("efg\nhijk")); 447 448 onHandleView(com.android.internal.R.id.selection_start_handle) 449 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 450 onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk")); 451 452 onHandleView(com.android.internal.R.id.selection_end_handle) 453 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('n') + 1)); 454 onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk\nlmn")); 455 456 onHandleView(com.android.internal.R.id.selection_end_handle) 457 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('r') + 1)); 458 onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk\nlmn\nopqr")); 459 } 460 461 @SmallTest 462 public void testSelectionHandles_multiLine_rtl() throws Exception { 463 // Arabic text. 464 final String text = "\u062A\u062B\u062C\n" + "\u062D\u062E\u062F\n" 465 + "\u0630\u0631\u0632\n" + "\u0633\u0634\u0635\n" + "\u0636\u0637\u0638\n" 466 + "\u0639\u063A\u063B"; 467 onView(withId(R.id.textview)).perform(click()); 468 onView(withId(R.id.textview)).perform(replaceText(text)); 469 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 470 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('\u0634'))); 471 472 final TextView textView = (TextView)getActivity().findViewById(R.id.textview); 473 onHandleView(com.android.internal.R.id.selection_start_handle) 474 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u062E'))); 475 onView(withId(R.id.textview)).check(hasSelection( 476 text.substring(text.indexOf('\u062D'), text.indexOf('\u0635') + 1))); 477 478 onHandleView(com.android.internal.R.id.selection_start_handle) 479 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u062A'))); 480 onView(withId(R.id.textview)).check(hasSelection( 481 text.substring(text.indexOf('\u062A'), text.indexOf('\u0635') + 1))); 482 483 onHandleView(com.android.internal.R.id.selection_end_handle) 484 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('\u0638'))); 485 onView(withId(R.id.textview)).check(hasSelection( 486 text.substring(text.indexOf('\u062A'), text.indexOf('\u0638') + 1))); 487 488 onHandleView(com.android.internal.R.id.selection_end_handle) 489 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('\u063B'))); 490 onView(withId(R.id.textview)).check(hasSelection(text)); 491 } 492 493 494 @SmallTest 495 public void testSelectionHandles_doesNotPassAnotherHandle() throws Exception { 496 final String text = "abcd efg hijk lmn"; 497 onView(withId(R.id.textview)).perform(click()); 498 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 499 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('f'))); 500 501 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 502 onHandleView(com.android.internal.R.id.selection_start_handle) 503 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('l'))); 504 onView(withId(R.id.textview)).check(hasSelection("g")); 505 506 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('f'))); 507 onHandleView(com.android.internal.R.id.selection_end_handle) 508 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('a'))); 509 onView(withId(R.id.textview)).check(hasSelection("e")); 510 } 511 512 @SmallTest 513 public void testSelectionHandles_doesNotPassAnotherHandle_multiLine() throws Exception { 514 final String text = "abcd\n" + "efg\n" + "hijk\n" + "lmn\n" + "opqr"; 515 onView(withId(R.id.textview)).perform(click()); 516 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 517 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 518 519 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 520 onHandleView(com.android.internal.R.id.selection_start_handle) 521 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('r') + 1)); 522 onView(withId(R.id.textview)).check(hasSelection("k")); 523 524 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 525 onHandleView(com.android.internal.R.id.selection_end_handle) 526 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('a'))); 527 onView(withId(R.id.textview)).check(hasSelection("h")); 528 } 529 530 @SmallTest 531 public void testSelectionHandles_snapToWordBoundary() throws Exception { 532 final String text = "abcd efg hijk lmn opqr"; 533 onView(withId(R.id.textview)).perform(click()); 534 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 535 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 536 537 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 538 539 onHandleView(com.android.internal.R.id.selection_start_handle) 540 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('f'))); 541 onView(withId(R.id.textview)).check(hasSelection("efg hijk")); 542 543 onHandleView(com.android.internal.R.id.selection_start_handle) 544 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('d') + 1)); 545 onView(withId(R.id.textview)).check(hasSelection("efg hijk")); 546 547 548 onHandleView(com.android.internal.R.id.selection_start_handle) 549 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('c'))); 550 onView(withId(R.id.textview)).check(hasSelection("abcd efg hijk")); 551 552 onHandleView(com.android.internal.R.id.selection_start_handle) 553 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('d'))); 554 onView(withId(R.id.textview)).check(hasSelection("d efg hijk")); 555 556 onHandleView(com.android.internal.R.id.selection_start_handle) 557 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('b'))); 558 onView(withId(R.id.textview)).check(hasSelection("bcd efg hijk")); 559 560 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 561 562 onHandleView(com.android.internal.R.id.selection_end_handle) 563 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('n'))); 564 onView(withId(R.id.textview)).check(hasSelection("hijk lmn")); 565 566 onHandleView(com.android.internal.R.id.selection_end_handle) 567 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('o'))); 568 onView(withId(R.id.textview)).check(hasSelection("hijk lmn")); 569 570 onHandleView(com.android.internal.R.id.selection_end_handle) 571 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('q'))); 572 onView(withId(R.id.textview)).check(hasSelection("hijk lmn opqr")); 573 574 onHandleView(com.android.internal.R.id.selection_end_handle) 575 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('p'))); 576 onView(withId(R.id.textview)).check(hasSelection("hijk lmn o")); 577 578 onHandleView(com.android.internal.R.id.selection_end_handle) 579 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('r'))); 580 onView(withId(R.id.textview)).check(hasSelection("hijk lmn opq")); 581 } 582 583 @SmallTest 584 public void testSelectionHandles_snapToWordBoundary_multiLine() throws Exception { 585 final String text = "abcd efg\n" + "hijk lmn\n" + "opqr stu"; 586 onView(withId(R.id.textview)).perform(click()); 587 onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); 588 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('m'))); 589 590 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 591 592 onHandleView(com.android.internal.R.id.selection_start_handle) 593 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('c'))); 594 onView(withId(R.id.textview)).check(hasSelection("abcd efg\nhijk lmn")); 595 596 onHandleView(com.android.internal.R.id.selection_start_handle) 597 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('g'))); 598 onView(withId(R.id.textview)).check(hasSelection("g\nhijk lmn")); 599 600 onHandleView(com.android.internal.R.id.selection_start_handle) 601 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('m'))); 602 onView(withId(R.id.textview)).check(hasSelection("lmn")); 603 604 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); 605 606 onHandleView(com.android.internal.R.id.selection_end_handle) 607 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('u'))); 608 onView(withId(R.id.textview)).check(hasSelection("hijk lmn\nopqr stu")); 609 610 onHandleView(com.android.internal.R.id.selection_end_handle) 611 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('p'))); 612 onView(withId(R.id.textview)).check(hasSelection("hijk lmn\no")); 613 614 onHandleView(com.android.internal.R.id.selection_end_handle) 615 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('i'))); 616 onView(withId(R.id.textview)).check(hasSelection("hijk")); 617 } 618 619 @SmallTest 620 public void testSetSelectionAndActionMode() throws Exception { 621 final String text = "abc def"; 622 onView(withId(R.id.textview)).perform(click()); 623 onView(withId(R.id.textview)).perform(replaceText(text)); 624 625 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 626 assertFloatingToolbarIsNotDisplayed(); 627 textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0, 3)); 628 getInstrumentation().waitForIdleSync(); 629 sleepForFloatingToolbarPopup(); 630 // Don't automatically start action mode. 631 assertFloatingToolbarIsNotDisplayed(); 632 // Make sure that "Select All" is included in the selection action mode when the entire text 633 // is not selected. 634 onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('e'))); 635 sleepForFloatingToolbarPopup(); 636 assertFloatingToolbarIsDisplayed(); 637 // Changing the selection range by API should not interrupt the selection action mode. 638 textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0, 3)); 639 getInstrumentation().waitForIdleSync(); 640 sleepForFloatingToolbarPopup(); 641 assertFloatingToolbarIsDisplayed(); 642 assertFloatingToolbarContainsItem( 643 getActivity().getString(com.android.internal.R.string.selectAll)); 644 // Make sure that "Select All" is no longer included when the entire text is selected by 645 // API. 646 textView.post( 647 () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length())); 648 getInstrumentation().waitForIdleSync(); 649 sleepForFloatingToolbarPopup(); 650 assertFloatingToolbarIsDisplayed(); 651 assertFloatingToolbarDoesNotContainItem( 652 getActivity().getString(com.android.internal.R.string.selectAll)); 653 // Make sure that shrinking the selection range to cursor (an empty range) by API 654 // terminates selection action mode and does not trigger the insertion action mode. 655 textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0)); 656 getInstrumentation().waitForIdleSync(); 657 sleepForFloatingToolbarPopup(); 658 assertFloatingToolbarIsNotDisplayed(); 659 // Make sure that user click can trigger the insertion action mode. 660 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 661 onHandleView(com.android.internal.R.id.insertion_handle).perform(click()); 662 sleepForFloatingToolbarPopup(); 663 assertFloatingToolbarIsDisplayed(); 664 // Make sure that an existing insertion action mode keeps alive after the insertion point is 665 // moved by API. 666 textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0)); 667 getInstrumentation().waitForIdleSync(); 668 sleepForFloatingToolbarPopup(); 669 assertFloatingToolbarIsDisplayed(); 670 assertFloatingToolbarDoesNotContainItem( 671 getActivity().getString(com.android.internal.R.string.copy)); 672 // Make sure that selection action mode is started after selection is created by API when 673 // insertion action mode is active. 674 textView.post( 675 () -> Selection.setSelection((Spannable) textView.getText(), 1, text.length())); 676 getInstrumentation().waitForIdleSync(); 677 sleepForFloatingToolbarPopup(); 678 assertFloatingToolbarIsDisplayed(); 679 assertFloatingToolbarContainsItem( 680 getActivity().getString(com.android.internal.R.string.copy)); 681 } 682 683 @SmallTest 684 public void testTransientState() throws Exception { 685 final String text = "abc def"; 686 onView(withId(R.id.textview)).perform(click()); 687 onView(withId(R.id.textview)).perform(replaceText(text)); 688 689 final TextView textView = (TextView) getActivity().findViewById(R.id.textview); 690 assertFalse(textView.hasTransientState()); 691 692 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('b'))); 693 // hasTransientState should return true when user generated selection is active. 694 assertTrue(textView.hasTransientState()); 695 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('d'))); 696 // hasTransientState should return false as the selection has been cleared. 697 assertFalse(textView.hasTransientState()); 698 textView.post( 699 () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length())); 700 getInstrumentation().waitForIdleSync(); 701 // hasTransientState should return false when selection is created by API. 702 assertFalse(textView.hasTransientState()); 703 } 704} 705