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