TextViewActivityTest.java revision 29cb76849c94bdbd95439e372360a51720c6b067
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.Espresso.onView; 20import static android.support.test.espresso.action.ViewActions.click; 21import static android.support.test.espresso.action.ViewActions.longClick; 22import static android.support.test.espresso.action.ViewActions.pressKey; 23import static android.support.test.espresso.action.ViewActions.replaceText; 24import static android.support.test.espresso.assertion.ViewAssertions.matches; 25import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; 26import static android.support.test.espresso.matcher.ViewMatchers.withId; 27import static android.support.test.espresso.matcher.ViewMatchers.withText; 28import static android.widget.espresso.CustomViewActions.longPressAtRelativeCoordinates; 29import static android.widget.espresso.DragHandleUtils.onHandleView; 30import static android.widget.espresso.FloatingToolbarEspressoUtils 31 .assertFloatingToolbarContainsItem; 32import static android.widget.espresso.FloatingToolbarEspressoUtils 33 .assertFloatingToolbarDoesNotContainItem; 34import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed; 35import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarItemIndex; 36import static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem; 37import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup; 38import static android.widget.espresso.TextViewActions.Handle; 39import static android.widget.espresso.TextViewActions.clickOnTextAtIndex; 40import static android.widget.espresso.TextViewActions.doubleClickOnTextAtIndex; 41import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText; 42import static android.widget.espresso.TextViewActions.dragHandle; 43import static android.widget.espresso.TextViewActions.longPressAndDragOnText; 44import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex; 45import static android.widget.espresso.TextViewAssertions.doesNotHaveStyledText; 46import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex; 47import static android.widget.espresso.TextViewAssertions.hasSelection; 48 49import static junit.framework.Assert.assertFalse; 50import static junit.framework.Assert.assertTrue; 51 52import static org.hamcrest.Matchers.anyOf; 53import static org.hamcrest.Matchers.is; 54import static org.mockito.Matchers.any; 55import static org.mockito.Mockito.mock; 56import static org.mockito.Mockito.never; 57import static org.mockito.Mockito.verify; 58import static org.mockito.Mockito.when; 59 60import android.app.Activity; 61import android.app.Instrumentation; 62import android.content.ClipData; 63import android.content.ClipboardManager; 64import android.support.test.InstrumentationRegistry; 65import android.support.test.espresso.action.EspressoKey; 66import android.support.test.filters.MediumTest; 67import android.support.test.rule.ActivityTestRule; 68import android.support.test.runner.AndroidJUnit4; 69import android.support.test.uiautomator.UiDevice; 70import android.test.suitebuilder.annotation.Suppress; 71import android.text.InputType; 72import android.text.Selection; 73import android.text.Spannable; 74import android.text.SpannableString; 75import android.text.method.LinkMovementMethod; 76import android.view.ActionMode; 77import android.view.KeyEvent; 78import android.view.Menu; 79import android.view.MenuItem; 80import android.view.textclassifier.TextClassificationManager; 81import android.view.textclassifier.TextClassifier; 82import android.view.textclassifier.TextLinks; 83import android.view.textclassifier.TextLinksParams; 84import android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider; 85 86import com.android.frameworks.coretests.R; 87 88import org.junit.Before; 89import org.junit.Rule; 90import org.junit.Test; 91import org.junit.runner.RunWith; 92 93/** 94 * Tests the TextView widget from an Activity 95 */ 96@RunWith(AndroidJUnit4.class) 97@MediumTest 98public class TextViewActivityTest { 99 100 @Rule 101 public ActivityTestRule<TextViewActivity> mActivityRule = new ActivityTestRule<>( 102 TextViewActivity.class); 103 104 private Activity mActivity; 105 private Instrumentation mInstrumentation; 106 107 @Before 108 public void setUp() { 109 mActivity = mActivityRule.getActivity(); 110 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 111 mActivity.getSystemService(TextClassificationManager.class) 112 .setTextClassifier(TextClassifier.NO_OP); 113 } 114 115 @Test 116 public void testTypedTextIsOnScreen() { 117 final String helloWorld = "Hello world!"; 118 // We use replaceText instead of typeTextIntoFocusedView to input text to avoid 119 // unintentional interactions with software keyboard. 120 onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 121 122 onView(withId(R.id.textview)).check(matches(withText(helloWorld))); 123 } 124 @Test 125 public void testPositionCursorAtTextAtIndex() { 126 final String helloWorld = "Hello world!"; 127 onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 128 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(helloWorld.indexOf("world"))); 129 130 // Delete text at specified index and see if we got the right one. 131 onView(withId(R.id.textview)).perform(pressKey(KeyEvent.KEYCODE_FORWARD_DEL)); 132 onView(withId(R.id.textview)).check(matches(withText("Hello orld!"))); 133 } 134 135 @Test 136 public void testPositionCursorAtTextAtIndex_arabic() { 137 // Arabic text. The expected cursorable boundary is 138 // | \u0623 \u064F | \u067A | \u0633 \u0652 | 139 final String text = "\u0623\u064F\u067A\u0633\u0652"; 140 onView(withId(R.id.textview)).perform(replaceText(text)); 141 142 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0)); 143 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0)); 144 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(1)); 145 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(0), is(2)))); 146 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(2)); 147 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2)); 148 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(3)); 149 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(3)); 150 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(4)); 151 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(3), is(5)))); 152 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(5)); 153 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(5)); 154 } 155 156 @Test 157 public void testPositionCursorAtTextAtIndex_devanagari() { 158 // Devanagari text. The expected cursorable boundary is | \u0915 \u093E | 159 final String text = "\u0915\u093E"; 160 onView(withId(R.id.textview)).perform(replaceText(text)); 161 162 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0)); 163 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0)); 164 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(1)); 165 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(0), is(2)))); 166 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(2)); 167 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2)); 168 } 169 170 @Test 171 public void testLongPressToSelect() { 172 final String helloWorld = "Hello Kirk!"; 173 onView(withId(R.id.textview)).perform(click()); 174 onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 175 onView(withId(R.id.textview)).perform( 176 longPressOnTextAtIndex(helloWorld.indexOf("Kirk"))); 177 178 onView(withId(R.id.textview)).check(hasSelection("Kirk")); 179 } 180 181 @Test 182 public void testLongPressEmptySpace() { 183 final String helloWorld = "Hello big round sun!"; 184 onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 185 // Move cursor somewhere else 186 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(helloWorld.indexOf("big"))); 187 // Long-press at end of line. 188 onView(withId(R.id.textview)).perform(longPressAtRelativeCoordinates( 189 RelativeCoordinatesProvider.HorizontalReference.RIGHT, -5, 190 RelativeCoordinatesProvider.VerticalReference.CENTER, 0)); 191 192 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(helloWorld.length())); 193 } 194 195 @Test 196 public void testLongPressAndDragToSelect() { 197 final String helloWorld = "Hello little handsome boy!"; 198 onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 199 onView(withId(R.id.textview)).perform( 200 longPressAndDragOnText(helloWorld.indexOf("little"), helloWorld.indexOf(" boy!"))); 201 202 onView(withId(R.id.textview)).check(hasSelection("little handsome")); 203 } 204 205 @Test 206 public void testLongPressAndDragToSelect_emoji() { 207 final String text = "\uD83D\uDE00\uD83D\uDE01\uD83D\uDE02\uD83D\uDE03"; 208 onView(withId(R.id.textview)).perform(replaceText(text)); 209 210 onView(withId(R.id.textview)).perform(longPressAndDragOnText(4, 6)); 211 onView(withId(R.id.textview)).check(hasSelection("\uD83D\uDE02")); 212 213 onView(withId(R.id.textview)).perform(click()); 214 215 onView(withId(R.id.textview)).perform(longPressAndDragOnText(4, 2)); 216 onView(withId(R.id.textview)).check(hasSelection("\uD83D\uDE01")); 217 } 218 219 @Test 220 public void testDragAndDrop() { 221 final String text = "abc def ghi."; 222 onView(withId(R.id.textview)).perform(replaceText(text)); 223 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf("e"))); 224 225 onView(withId(R.id.textview)).perform( 226 longPressAndDragOnText(text.indexOf("e"), text.length())); 227 228 onView(withId(R.id.textview)).check(matches(withText("abc ghi.def"))); 229 onView(withId(R.id.textview)).check(hasSelection("")); 230 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex("abc ghi.def".length())); 231 232 // Test undo returns to the original state. 233 onView(withId(R.id.textview)).perform(pressKey( 234 (new EspressoKey.Builder()).withCtrlPressed(true).withKeyCode(KeyEvent.KEYCODE_Z) 235 .build())); 236 onView(withId(R.id.textview)).check(matches(withText(text))); 237 } 238 239 @Test 240 public void testDoubleTapToSelect() { 241 final String helloWorld = "Hello SuetYi!"; 242 onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 243 244 onView(withId(R.id.textview)).perform( 245 doubleClickOnTextAtIndex(helloWorld.indexOf("SuetYi"))); 246 247 onView(withId(R.id.textview)).check(hasSelection("SuetYi")); 248 } 249 250 @Test 251 public void testDoubleTapAndDragToSelect() { 252 final String helloWorld = "Hello young beautiful person!"; 253 onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 254 onView(withId(R.id.textview)).perform(doubleTapAndDragOnText(helloWorld.indexOf("young"), 255 helloWorld.indexOf(" person!"))); 256 257 onView(withId(R.id.textview)).check(hasSelection("young beautiful")); 258 } 259 260 @Test 261 public void testDoubleTapAndDragToSelect_multiLine() { 262 final String helloWorld = "abcd\n" + "efg\n" + "hijklm\n" + "nop"; 263 onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 264 onView(withId(R.id.textview)).perform( 265 doubleTapAndDragOnText(helloWorld.indexOf("m"), helloWorld.indexOf("a"))); 266 onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijklm")); 267 } 268 269 @Test 270 public void testSelectBackwordsByTouch() { 271 final String helloWorld = "Hello king of the Jungle!"; 272 onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 273 onView(withId(R.id.textview)).perform( 274 doubleTapAndDragOnText(helloWorld.indexOf(" Jungle!"), helloWorld.indexOf("king"))); 275 276 onView(withId(R.id.textview)).check(hasSelection("king of the")); 277 } 278 279 @Test 280 public void testToolbarAppearsAfterSelection() { 281 final String text = "Toolbar appears after selection."; 282 onView(withId(R.id.textview)).perform(replaceText(text)); 283 onView(withId(R.id.textview)).perform( 284 longPressOnTextAtIndex(text.indexOf("appears"))); 285 286 sleepForFloatingToolbarPopup(); 287 assertFloatingToolbarIsDisplayed(); 288 } 289 290 @Test 291 public void testToolbarAppearsAfterSelection_withFirstStringLtrAlgorithmAndRtlHint() 292 throws Throwable { 293 // after the hint layout change, the floating toolbar was not visible in the case below 294 // this test tests that the floating toolbar is displayed on the screen and is visible to 295 // user. 296 mActivityRule.runOnUiThread(() -> { 297 final TextView textView = mActivity.findViewById(R.id.textview); 298 textView.setTextDirection(TextView.TEXT_DIRECTION_FIRST_STRONG_LTR); 299 textView.setInputType(InputType.TYPE_CLASS_TEXT); 300 textView.setSingleLine(true); 301 textView.setHint("الروبوت"); 302 }); 303 mInstrumentation.waitForIdleSync(); 304 305 onView(withId(R.id.textview)).perform(replaceText("test")); 306 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(1)); 307 clickFloatingToolbarItem(mActivity.getString(com.android.internal.R.string.cut)); 308 onView(withId(R.id.textview)).perform(longClick()); 309 sleepForFloatingToolbarPopup(); 310 311 assertFloatingToolbarIsDisplayed(); 312 } 313 314 @Test 315 public void testToolbarAppearsAfterLinkClicked() throws Throwable { 316 TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.textview); 317 int position = (textLink.getStart() + textLink.getEnd()) / 2; 318 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(position)); 319 sleepForFloatingToolbarPopup(); 320 assertFloatingToolbarIsDisplayed(); 321 } 322 323 @Test 324 public void testToolbarAppearsAfterLinkClickedNonselectable() throws Throwable { 325 final TextView textView = mActivity.findViewById(R.id.nonselectable_textview); 326 final TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.nonselectable_textview); 327 final int position = (textLink.getStart() + textLink.getEnd()) / 2; 328 329 onView(withId(R.id.nonselectable_textview)).perform(clickOnTextAtIndex(position)); 330 sleepForFloatingToolbarPopup(); 331 assertFloatingToolbarIsDisplayed(); 332 assertTrue(textView.hasSelection()); 333 334 // toggle 335 onView(withId(R.id.nonselectable_textview)).perform(clickOnTextAtIndex(position)); 336 sleepForFloatingToolbarPopup(); 337 assertFalse(textView.hasSelection()); 338 339 onView(withId(R.id.nonselectable_textview)).perform(clickOnTextAtIndex(position)); 340 sleepForFloatingToolbarPopup(); 341 assertFloatingToolbarIsDisplayed(); 342 assertTrue(textView.hasSelection()); 343 344 // click outside 345 onView(withId(R.id.nonselectable_textview)).perform(clickOnTextAtIndex(0)); 346 sleepForFloatingToolbarPopup(); 347 assertFalse(textView.hasSelection()); 348 } 349 350 @Test 351 public void testSelectionRemovedWhenNonselectableTextLosesFocus() throws Throwable { 352 final TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.nonselectable_textview); 353 final int position = (textLink.getStart() + textLink.getEnd()) / 2; 354 final TextView textView = mActivity.findViewById(R.id.nonselectable_textview); 355 mActivityRule.runOnUiThread(() -> textView.setFocusableInTouchMode(true)); 356 357 onView(withId(R.id.nonselectable_textview)).perform(clickOnTextAtIndex(position)); 358 sleepForFloatingToolbarPopup(); 359 assertFloatingToolbarIsDisplayed(); 360 assertTrue(textView.hasSelection()); 361 362 mActivityRule.runOnUiThread(() -> textView.clearFocus()); 363 mInstrumentation.waitForIdleSync(); 364 sleepForFloatingToolbarPopup(); 365 366 assertFalse(textView.hasSelection()); 367 } 368 369 @Test 370 public void testSelectionRemovedFromNonselectableTextWhenWindowLosesFocus() throws Throwable { 371 TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.nonselectable_textview); 372 int nonselectablePosition = (textLink.getStart() + textLink.getEnd()) / 2; 373 TextView nonselectableTextView = mActivity.findViewById(R.id.nonselectable_textview); 374 375 onView(withId(R.id.nonselectable_textview)) 376 .perform(clickOnTextAtIndex(nonselectablePosition)); 377 sleepForFloatingToolbarPopup(); 378 assertFloatingToolbarIsDisplayed(); 379 assertTrue(nonselectableTextView.hasSelection()); 380 381 UiDevice device = UiDevice.getInstance(mInstrumentation); 382 device.openNotification(); 383 Thread.sleep(2000); 384 device.pressBack(); 385 Thread.sleep(2000); 386 387 assertFalse(nonselectableTextView.hasSelection()); 388 } 389 390 private TextLinks.TextLink addLinkifiedTextToTextView(int id) throws Throwable { 391 TextView textView = mActivity.findViewById(id); 392 useSystemDefaultTextClassifier(); 393 TextClassificationManager textClassificationManager = 394 mActivity.getSystemService(TextClassificationManager.class); 395 TextClassifier textClassifier = textClassificationManager.getTextClassifier(); 396 Spannable content = new SpannableString("Call me at +19148277737"); 397 TextLinks.Request request = new TextLinks.Request.Builder(content).build(); 398 TextLinks links = textClassifier.generateLinks(request); 399 TextLinksParams applyParams = new TextLinksParams.Builder() 400 .setApplyStrategy(TextLinks.APPLY_STRATEGY_REPLACE) 401 .build(); 402 applyParams.apply(content, links); 403 404 mActivityRule.runOnUiThread(() -> { 405 textView.setText(content); 406 textView.setMovementMethod(LinkMovementMethod.getInstance()); 407 }); 408 mInstrumentation.waitForIdleSync(); 409 410 // Wait for the UI thread to refresh 411 Thread.sleep(1000); 412 413 return links.getLinks().iterator().next(); 414 } 415 416 @Test 417 public void testToolbarAndInsertionHandle() { 418 final String text = "text"; 419 onView(withId(R.id.textview)).perform(replaceText(text)); 420 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 421 422 onHandleView(com.android.internal.R.id.insertion_handle).perform(click()); 423 sleepForFloatingToolbarPopup(); 424 assertFloatingToolbarIsDisplayed(); 425 426 assertFloatingToolbarContainsItem( 427 mActivity.getString(com.android.internal.R.string.selectAll)); 428 assertFloatingToolbarDoesNotContainItem( 429 mActivity.getString(com.android.internal.R.string.copy)); 430 assertFloatingToolbarDoesNotContainItem( 431 mActivity.getString(com.android.internal.R.string.cut)); 432 } 433 434 @Test 435 public void testToolbarAndSelectionHandle() { 436 final String text = "abcd efg hijk"; 437 onView(withId(R.id.textview)).perform(replaceText(text)); 438 439 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf("f"))); 440 sleepForFloatingToolbarPopup(); 441 assertFloatingToolbarIsDisplayed(); 442 443 assertFloatingToolbarContainsItem( 444 mActivity.getString(com.android.internal.R.string.selectAll)); 445 assertFloatingToolbarContainsItem( 446 mActivity.getString(com.android.internal.R.string.copy)); 447 assertFloatingToolbarContainsItem( 448 mActivity.getString(com.android.internal.R.string.cut)); 449 450 final TextView textView = mActivity.findViewById(R.id.textview); 451 onHandleView(com.android.internal.R.id.selection_start_handle) 452 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 453 sleepForFloatingToolbarPopup(); 454 assertFloatingToolbarIsDisplayed(); 455 456 onHandleView(com.android.internal.R.id.selection_end_handle) 457 .perform(dragHandle(textView, Handle.SELECTION_END, text.length())); 458 sleepForFloatingToolbarPopup(); 459 assertFloatingToolbarIsDisplayed(); 460 461 assertFloatingToolbarDoesNotContainItem( 462 mActivity.getString(com.android.internal.R.string.selectAll)); 463 assertFloatingToolbarContainsItem( 464 mActivity.getString(com.android.internal.R.string.copy)); 465 assertFloatingToolbarContainsItem( 466 mActivity.getString(com.android.internal.R.string.cut)); 467 } 468 469 @Test 470 public void testInsertionHandle() { 471 final String text = "abcd efg hijk "; 472 onView(withId(R.id.textview)).perform(replaceText(text)); 473 474 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 475 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.length())); 476 477 final TextView textView = mActivity.findViewById(R.id.textview); 478 479 onHandleView(com.android.internal.R.id.insertion_handle) 480 .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('a'))); 481 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("a"))); 482 483 onHandleView(com.android.internal.R.id.insertion_handle) 484 .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('f'))); 485 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("f"))); 486 } 487 488 @Test 489 public void testInsertionHandle_multiLine() { 490 final String text = "abcd\n" + "efg\n" + "hijk\n"; 491 onView(withId(R.id.textview)).perform(replaceText(text)); 492 493 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 494 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.length())); 495 496 final TextView textView = mActivity.findViewById(R.id.textview); 497 498 onHandleView(com.android.internal.R.id.insertion_handle) 499 .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('a'))); 500 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("a"))); 501 502 onHandleView(com.android.internal.R.id.insertion_handle) 503 .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('f'))); 504 onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("f"))); 505 } 506 507 @Test 508 public void testSelectionHandles() { 509 final String text = "abcd efg hijk lmn"; 510 onView(withId(R.id.textview)).perform(replaceText(text)); 511 512 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('f'))); 513 514 onHandleView(com.android.internal.R.id.selection_start_handle) 515 .check(matches(isDisplayed())); 516 onHandleView(com.android.internal.R.id.selection_end_handle) 517 .check(matches(isDisplayed())); 518 519 final TextView textView = mActivity.findViewById(R.id.textview); 520 onHandleView(com.android.internal.R.id.selection_start_handle) 521 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 522 onView(withId(R.id.textview)).check(hasSelection("abcd efg")); 523 524 onHandleView(com.android.internal.R.id.selection_end_handle) 525 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('k') + 1)); 526 onView(withId(R.id.textview)).check(hasSelection("abcd efg hijk")); 527 } 528 529 @Test 530 public void testSelectionHandles_bidi() { 531 final String text = "abc \u0621\u0622\u0623 def"; 532 onView(withId(R.id.textview)).perform(replaceText(text)); 533 534 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('\u0622'))); 535 536 onHandleView(com.android.internal.R.id.selection_start_handle) 537 .check(matches(isDisplayed())); 538 onHandleView(com.android.internal.R.id.selection_end_handle) 539 .check(matches(isDisplayed())); 540 541 onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 542 543 final TextView textView = mActivity.findViewById(R.id.textview); 544 onHandleView(com.android.internal.R.id.selection_start_handle) 545 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('f'))); 546 onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 547 548 onHandleView(com.android.internal.R.id.selection_end_handle) 549 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('a'))); 550 onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 551 552 onHandleView(com.android.internal.R.id.selection_start_handle) 553 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u0623'), 554 false)); 555 onView(withId(R.id.textview)).check(hasSelection("\u0623")); 556 557 onHandleView(com.android.internal.R.id.selection_start_handle) 558 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u0621'), 559 false)); 560 onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 561 562 onHandleView(com.android.internal.R.id.selection_start_handle) 563 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 564 onView(withId(R.id.textview)).check(hasSelection("abc \u0621\u0622\u0623")); 565 566 onHandleView(com.android.internal.R.id.selection_end_handle) 567 .perform(dragHandle(textView, Handle.SELECTION_END, text.length())); 568 onView(withId(R.id.textview)).check(hasSelection("abc \u0621\u0622\u0623 def")); 569 } 570 571 @Test 572 public void testSelectionHandles_multiLine() { 573 final String text = "abcd\n" + "efg\n" + "hijk\n" + "lmn\n" + "opqr"; 574 onView(withId(R.id.textview)).perform(replaceText(text)); 575 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 576 577 final TextView textView = mActivity.findViewById(R.id.textview); 578 onHandleView(com.android.internal.R.id.selection_start_handle) 579 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('e'))); 580 onView(withId(R.id.textview)).check(hasSelection("efg\nhijk")); 581 582 onHandleView(com.android.internal.R.id.selection_start_handle) 583 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 584 onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk")); 585 586 onHandleView(com.android.internal.R.id.selection_end_handle) 587 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('n') + 1)); 588 onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk\nlmn")); 589 590 onHandleView(com.android.internal.R.id.selection_end_handle) 591 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('r') + 1)); 592 onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk\nlmn\nopqr")); 593 } 594 595 @Suppress // Consistently failing. 596 @Test 597 public void testSelectionHandles_multiLine_rtl() { 598 // Arabic text. 599 final String text = "\u062A\u062B\u062C\n" + "\u062D\u062E\u062F\n" 600 + "\u0630\u0631\u0632\n" + "\u0633\u0634\u0635\n" + "\u0636\u0637\u0638\n" 601 + "\u0639\u063A\u063B"; 602 onView(withId(R.id.textview)).perform(replaceText(text)); 603 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('\u0634'))); 604 605 final TextView textView = mActivity.findViewById(R.id.textview); 606 onHandleView(com.android.internal.R.id.selection_start_handle) 607 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u062E'))); 608 onView(withId(R.id.textview)).check(hasSelection( 609 text.substring(text.indexOf('\u062D'), text.indexOf('\u0635') + 1))); 610 611 onHandleView(com.android.internal.R.id.selection_start_handle) 612 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u062A'))); 613 onView(withId(R.id.textview)).check(hasSelection( 614 text.substring(text.indexOf('\u062A'), text.indexOf('\u0635') + 1))); 615 616 onHandleView(com.android.internal.R.id.selection_end_handle) 617 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('\u0638'))); 618 onView(withId(R.id.textview)).check(hasSelection( 619 text.substring(text.indexOf('\u062A'), text.indexOf('\u0638') + 1))); 620 621 onHandleView(com.android.internal.R.id.selection_end_handle) 622 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('\u063B'))); 623 onView(withId(R.id.textview)).check(hasSelection(text)); 624 } 625 626 @Test 627 public void testSelectionHandles_doesNotPassAnotherHandle() { 628 final String text = "abcd efg hijk lmn"; 629 onView(withId(R.id.textview)).perform(replaceText(text)); 630 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('f'))); 631 632 final TextView textView = mActivity.findViewById(R.id.textview); 633 onHandleView(com.android.internal.R.id.selection_start_handle) 634 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('l'))); 635 onView(withId(R.id.textview)).check(hasSelection("g")); 636 637 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('f'))); 638 onHandleView(com.android.internal.R.id.selection_end_handle) 639 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('a'))); 640 onView(withId(R.id.textview)).check(hasSelection("e")); 641 } 642 643 @Test 644 public void testSelectionHandles_doesNotPassAnotherHandle_multiLine() { 645 final String text = "abcd\n" + "efg\n" + "hijk\n" + "lmn\n" + "opqr"; 646 onView(withId(R.id.textview)).perform(replaceText(text)); 647 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 648 649 final TextView textView = mActivity.findViewById(R.id.textview); 650 onHandleView(com.android.internal.R.id.selection_start_handle) 651 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('r') + 1)); 652 onView(withId(R.id.textview)).check(hasSelection("k")); 653 654 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 655 onHandleView(com.android.internal.R.id.selection_end_handle) 656 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('a'))); 657 onView(withId(R.id.textview)).check(hasSelection("h")); 658 } 659 660 @Test 661 public void testSelectionHandles_snapToWordBoundary() { 662 final String text = "abcd efg hijk lmn opqr"; 663 onView(withId(R.id.textview)).perform(replaceText(text)); 664 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 665 666 final TextView textView = mActivity.findViewById(R.id.textview); 667 668 onHandleView(com.android.internal.R.id.selection_start_handle) 669 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('f'))); 670 onView(withId(R.id.textview)).check(hasSelection("efg hijk")); 671 672 onHandleView(com.android.internal.R.id.selection_start_handle) 673 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('d') + 1)); 674 onView(withId(R.id.textview)).check(hasSelection("efg hijk")); 675 676 677 onHandleView(com.android.internal.R.id.selection_start_handle) 678 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('c'))); 679 onView(withId(R.id.textview)).check(hasSelection("abcd efg hijk")); 680 681 onHandleView(com.android.internal.R.id.selection_start_handle) 682 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('d'))); 683 onView(withId(R.id.textview)).check(hasSelection("d efg hijk")); 684 685 onHandleView(com.android.internal.R.id.selection_start_handle) 686 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('b'))); 687 onView(withId(R.id.textview)).check(hasSelection("bcd efg hijk")); 688 689 onView(withId(R.id.textview)).perform(click()); 690 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 691 692 onHandleView(com.android.internal.R.id.selection_end_handle) 693 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('n'))); 694 onView(withId(R.id.textview)).check(hasSelection("hijk lmn")); 695 696 onHandleView(com.android.internal.R.id.selection_end_handle) 697 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('o'))); 698 onView(withId(R.id.textview)).check(hasSelection("hijk lmn")); 699 700 onHandleView(com.android.internal.R.id.selection_end_handle) 701 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('q'))); 702 onView(withId(R.id.textview)).check(hasSelection("hijk lmn opqr")); 703 704 onHandleView(com.android.internal.R.id.selection_end_handle) 705 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('p'))); 706 onView(withId(R.id.textview)).check(hasSelection("hijk lmn o")); 707 708 onHandleView(com.android.internal.R.id.selection_end_handle) 709 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('r'))); 710 onView(withId(R.id.textview)).check(hasSelection("hijk lmn opq")); 711 } 712 713 @Test 714 public void testSelectionHandles_snapToWordBoundary_multiLine() { 715 final String text = "abcd efg\n" + "hijk lmn\n" + "opqr stu"; 716 onView(withId(R.id.textview)).perform(replaceText(text)); 717 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('m'))); 718 719 final TextView textView = mActivity.findViewById(R.id.textview); 720 721 onHandleView(com.android.internal.R.id.selection_start_handle) 722 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('c'))); 723 onView(withId(R.id.textview)).check(hasSelection("abcd efg\nhijk lmn")); 724 725 onHandleView(com.android.internal.R.id.selection_start_handle) 726 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('g'))); 727 onView(withId(R.id.textview)).check(hasSelection("g\nhijk lmn")); 728 729 onHandleView(com.android.internal.R.id.selection_start_handle) 730 .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('m'))); 731 onView(withId(R.id.textview)).check(hasSelection("lmn")); 732 733 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 734 735 onHandleView(com.android.internal.R.id.selection_end_handle) 736 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('u'))); 737 onView(withId(R.id.textview)).check(hasSelection("hijk lmn\nopqr stu")); 738 739 onHandleView(com.android.internal.R.id.selection_end_handle) 740 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('p'))); 741 onView(withId(R.id.textview)).check(hasSelection("hijk lmn\no")); 742 743 onHandleView(com.android.internal.R.id.selection_end_handle) 744 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('i'))); 745 onView(withId(R.id.textview)).check(hasSelection("hijk")); 746 } 747 748 @Test 749 public void testSelectionHandles_visibleEvenWithEmptyMenu() { 750 ((TextView) mActivity.findViewById(R.id.textview)).setCustomSelectionActionModeCallback( 751 new ActionMode.Callback() { 752 @Override 753 public boolean onCreateActionMode(ActionMode mode, Menu menu) { 754 menu.clear(); 755 return true; 756 } 757 758 @Override 759 public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 760 menu.clear(); 761 return true; 762 } 763 764 @Override 765 public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 766 return false; 767 } 768 769 @Override 770 public void onDestroyActionMode(ActionMode mode) {} 771 }); 772 final String text = "abcd efg hijk lmn"; 773 onView(withId(R.id.textview)).perform(replaceText(text)); 774 775 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('f'))); 776 777 onHandleView(com.android.internal.R.id.selection_start_handle) 778 .check(matches(isDisplayed())); 779 onHandleView(com.android.internal.R.id.selection_end_handle) 780 .check(matches(isDisplayed())); 781 } 782 783 @Test 784 public void testSetSelectionAndActionMode() throws Throwable { 785 final TextView textView = mActivity.findViewById(R.id.textview); 786 final ActionMode.Callback amCallback = mock(ActionMode.Callback.class); 787 when(amCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))) 788 .thenReturn(true); 789 when(amCallback.onPrepareActionMode(any(ActionMode.class), any(Menu.class))) 790 .thenReturn(true); 791 textView.setCustomSelectionActionModeCallback(amCallback); 792 793 final String text = "abc def"; 794 onView(withId(R.id.textview)).perform(replaceText(text)); 795 mActivityRule.runOnUiThread( 796 () -> Selection.setSelection((Spannable) textView.getText(), 0, 3)); 797 mInstrumentation.waitForIdleSync(); 798 // Don't automatically start action mode. 799 verify(amCallback, never()).onCreateActionMode(any(ActionMode.class), any(Menu.class)); 800 // Make sure that "Select All" is included in the selection action mode when the entire text 801 // is not selected. 802 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('e'))); 803 sleepForFloatingToolbarPopup(); 804 assertFloatingToolbarIsDisplayed(); 805 // Changing the selection range by API should not interrupt the selection action mode. 806 mActivityRule.runOnUiThread( 807 () -> Selection.setSelection((Spannable) textView.getText(), 0, 3)); 808 mInstrumentation.waitForIdleSync(); 809 sleepForFloatingToolbarPopup(); 810 assertFloatingToolbarIsDisplayed(); 811 assertFloatingToolbarContainsItem( 812 mActivity.getString(com.android.internal.R.string.selectAll)); 813 // Make sure that "Select All" is no longer included when the entire text is selected by 814 // API. 815 mActivityRule.runOnUiThread( 816 () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length())); 817 mInstrumentation.waitForIdleSync(); 818 819 sleepForFloatingToolbarPopup(); 820 assertFloatingToolbarIsDisplayed(); 821 assertFloatingToolbarDoesNotContainItem( 822 mActivity.getString(com.android.internal.R.string.selectAll)); 823 // Make sure that shrinking the selection range to cursor (an empty range) by API 824 // terminates selection action mode and does not trigger the insertion action mode. 825 mActivityRule.runOnUiThread( 826 () -> Selection.setSelection((Spannable) textView.getText(), 0)); 827 mInstrumentation.waitForIdleSync(); 828 829 // Make sure that user click can trigger the insertion action mode. 830 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 831 onHandleView(com.android.internal.R.id.insertion_handle).perform(click()); 832 sleepForFloatingToolbarPopup(); 833 assertFloatingToolbarIsDisplayed(); 834 // Make sure that an existing insertion action mode keeps alive after the insertion point is 835 // moved by API. 836 mActivityRule.runOnUiThread( 837 () -> Selection.setSelection((Spannable) textView.getText(), 0)); 838 mInstrumentation.waitForIdleSync(); 839 840 sleepForFloatingToolbarPopup(); 841 assertFloatingToolbarIsDisplayed(); 842 assertFloatingToolbarDoesNotContainItem( 843 mActivity.getString(com.android.internal.R.string.copy)); 844 // Make sure that selection action mode is started after selection is created by API when 845 // insertion action mode is active. 846 mActivityRule.runOnUiThread( 847 () -> Selection.setSelection((Spannable) textView.getText(), 1, text.length())); 848 mInstrumentation.waitForIdleSync(); 849 850 sleepForFloatingToolbarPopup(); 851 assertFloatingToolbarIsDisplayed(); 852 assertFloatingToolbarContainsItem( 853 mActivity.getString(com.android.internal.R.string.copy)); 854 } 855 856 @Test 857 public void testTransientState() throws Throwable { 858 final String text = "abc def"; 859 onView(withId(R.id.textview)).perform(replaceText(text)); 860 861 final TextView textView = mActivity.findViewById(R.id.textview); 862 assertFalse(textView.hasTransientState()); 863 864 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('b'))); 865 // hasTransientState should return true when user generated selection is active. 866 assertTrue(textView.hasTransientState()); 867 onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('d'))); 868 // hasTransientState should return false as the selection has been cleared. 869 assertFalse(textView.hasTransientState()); 870 mActivityRule.runOnUiThread( 871 () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length())); 872 mInstrumentation.waitForIdleSync(); 873 874 // hasTransientState should return false when selection is created by API. 875 assertFalse(textView.hasTransientState()); 876 } 877 878 @Test 879 public void testResetMenuItemTitle() throws Throwable { 880 mActivity.getSystemService(TextClassificationManager.class).setTextClassifier(null); 881 final TextView textView = mActivity.findViewById(R.id.textview); 882 final int itemId = 1; 883 final String title1 = " AFIGBO"; 884 final int index = title1.indexOf('I'); 885 final String title2 = title1.substring(index); 886 final String[] title = new String[]{title1}; 887 mActivityRule.runOnUiThread(() -> textView.setCustomSelectionActionModeCallback( 888 new ActionMode.Callback() { 889 @Override 890 public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { 891 return true; 892 } 893 894 @Override 895 public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { 896 menu.removeItem(itemId); 897 menu.add(Menu.NONE /* group */, itemId, 0 /* order */, title[0]); 898 return true; 899 } 900 901 @Override 902 public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { 903 return false; 904 } 905 906 @Override 907 public void onDestroyActionMode(ActionMode actionMode) { 908 } 909 })); 910 mInstrumentation.waitForIdleSync(); 911 912 onView(withId(R.id.textview)).perform(replaceText(title1)); 913 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(index)); 914 sleepForFloatingToolbarPopup(); 915 assertFloatingToolbarContainsItem(title1); 916 917 // Change the menu item title. 918 title[0] = title2; 919 // Change the selection to invalidate the action mode without restarting it. 920 onHandleView(com.android.internal.R.id.selection_start_handle) 921 .perform(dragHandle(textView, Handle.SELECTION_START, index)); 922 sleepForFloatingToolbarPopup(); 923 assertFloatingToolbarContainsItem(title2); 924 } 925 926 @Test 927 public void testAssistItemIsAtIndexZero() throws Throwable { 928 useSystemDefaultTextClassifier(); 929 final TextView textView = mActivity.findViewById(R.id.textview); 930 mActivityRule.runOnUiThread(() -> textView.setCustomSelectionActionModeCallback( 931 new ActionMode.Callback() { 932 @Override 933 public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { 934 // Create another item at order position 0 to confirm that it will never be 935 // placed before the textAssist item. 936 menu.add(Menu.NONE, 0 /* id */, 0 /* order */, "Test"); 937 return true; 938 } 939 940 @Override 941 public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { 942 return true; 943 } 944 945 @Override 946 public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { 947 return false; 948 } 949 950 @Override 951 public void onDestroyActionMode(ActionMode actionMode) { 952 } 953 })); 954 mInstrumentation.waitForIdleSync(); 955 final String text = "droid@android.com"; 956 957 onView(withId(R.id.textview)).perform(replaceText(text)); 958 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('@'))); 959 sleepForFloatingToolbarPopup(); 960 assertFloatingToolbarItemIndex(android.R.id.textAssist, 0); 961 } 962 963 @Test 964 public void testNoAssistItemForPasswordField() throws Throwable { 965 useSystemDefaultTextClassifier(); 966 final TextView textView = mActivity.findViewById(R.id.textview); 967 mActivityRule.runOnUiThread(() -> { 968 textView.setInputType( 969 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); 970 }); 971 mInstrumentation.waitForIdleSync(); 972 final String password = "afigbo@android.com"; 973 974 onView(withId(R.id.textview)).perform(replaceText(password)); 975 onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(password.indexOf('@'))); 976 sleepForFloatingToolbarPopup(); 977 assertFloatingToolbarDoesNotContainItem(android.R.id.textAssist); 978 } 979 980 @Test 981 public void testPastePlainText_menuAction() { 982 initializeClipboardWithText(TextStyle.STYLED); 983 984 onView(withId(R.id.textview)).perform(replaceText("")); 985 onView(withId(R.id.textview)).perform(longClick()); 986 sleepForFloatingToolbarPopup(); 987 clickFloatingToolbarItem( 988 mActivity.getString(com.android.internal.R.string.paste_as_plain_text)); 989 mInstrumentation.waitForIdleSync(); 990 991 onView(withId(R.id.textview)).check(matches(withText("styledtext"))); 992 onView(withId(R.id.textview)).check(doesNotHaveStyledText()); 993 } 994 995 @Test 996 public void testPastePlainText_noMenuItemForPlainText() { 997 initializeClipboardWithText(TextStyle.PLAIN); 998 999 onView(withId(R.id.textview)).perform(replaceText("")); 1000 onView(withId(R.id.textview)).perform(longClick()); 1001 sleepForFloatingToolbarPopup(); 1002 1003 assertFloatingToolbarDoesNotContainItem( 1004 mActivity.getString(com.android.internal.R.string.paste_as_plain_text)); 1005 } 1006 1007 private void useSystemDefaultTextClassifier() { 1008 mActivity.getSystemService(TextClassificationManager.class).setTextClassifier(null); 1009 } 1010 1011 private void initializeClipboardWithText(TextStyle textStyle) { 1012 final ClipData clip; 1013 switch (textStyle) { 1014 case STYLED: 1015 clip = ClipData.newHtmlText("html", "styledtext", "<b>styledtext</b>"); 1016 break; 1017 case PLAIN: 1018 clip = ClipData.newPlainText("plain", "plaintext"); 1019 break; 1020 default: 1021 throw new IllegalArgumentException("Invalid text style"); 1022 } 1023 mActivity.getWindow().getDecorView().post(() -> 1024 mActivity.getSystemService(ClipboardManager.class).setPrimaryClip(clip)); 1025 mInstrumentation.waitForIdleSync(); 1026 } 1027 1028 private enum TextStyle { 1029 PLAIN, STYLED 1030 } 1031} 1032