1223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki/* 2223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * Copyright (C) 2015 The Android Open Source Project 3223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * 4223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * Licensed under the Apache License, Version 2.0 (the "License"); 5223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * you may not use this file except in compliance with the License. 6223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * You may obtain a copy of the License at 7223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * 8223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * http://www.apache.org/licenses/LICENSE-2.0 9223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * 10223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * Unless required by applicable law or agreed to in writing, software 11223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * distributed under the License is distributed on an "AS IS" BASIS, 12223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * See the License for the specific language governing permissions and 14223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * limitations under the License 15223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki */ 16223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki 17223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Tokipackage android.widget; 18223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki 192191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.support.test.espresso.Espresso.onView; 202191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.support.test.espresso.action.ViewActions.click; 212191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.support.test.espresso.action.ViewActions.longClick; 222191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.support.test.espresso.action.ViewActions.pressKey; 232191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.support.test.espresso.action.ViewActions.replaceText; 242191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.support.test.espresso.assertion.ViewAssertions.matches; 252191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; 262191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.support.test.espresso.matcher.ViewMatchers.withId; 272191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.support.test.espresso.matcher.ViewMatchers.withText; 289479d3ebe2457726d5b3624774b5540fb7d1e09cAbodunrinwa Tokiimport static android.widget.espresso.CustomViewActions.longPressAtRelativeCoordinates; 29d42cb8ffa77266abe3bcffe98212d313d223a86cKeisuke Kuroyanagiimport static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles; 30d42cb8ffa77266abe3bcffe98212d313d223a86cKeisuke Kuroyanagiimport static android.widget.espresso.DragHandleUtils.onHandleView; 312191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem; 322191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarDoesNotContainItem; 332191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed; 342191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsNotDisplayed; 352191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarItemIndex; 362191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem; 372191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup; 382191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.widget.espresso.TextViewActions.Handle; 3990cdfe0514154bbc008d39f1c99f7a1d2684446cAbodunrinwa Tokiimport static android.widget.espresso.TextViewActions.clickOnTextAtIndex; 408a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Tokiimport static android.widget.espresso.TextViewActions.doubleClickOnTextAtIndex; 412191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.widget.espresso.TextViewActions.doubleTapAndDragOnText; 42da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagiimport static android.widget.espresso.TextViewActions.dragHandle; 43ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Tokiimport static android.widget.espresso.TextViewActions.longPressAndDragOnText; 448a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Tokiimport static android.widget.espresso.TextViewActions.longPressOnTextAtIndex; 452191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static android.widget.espresso.TextViewAssertions.doesNotHaveStyledText; 468a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Tokiimport static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex; 47ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Tokiimport static android.widget.espresso.TextViewAssertions.hasSelection; 482191418305ca42e4f219020a02f16c045c539755Siyamed Sinir 492191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static junit.framework.Assert.assertFalse; 502191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport static junit.framework.Assert.assertTrue; 512191418305ca42e4f219020a02f16c045c539755Siyamed Sinir 52c5b54bae62d5d82a576ca267202675652144185cAbodunrinwa Tokiimport static org.hamcrest.Matchers.anyOf; 53c5b54bae62d5d82a576ca267202675652144185cAbodunrinwa Tokiimport static org.hamcrest.Matchers.is; 54223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki 552191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport android.app.Activity; 562191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport android.app.Instrumentation; 57ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Tokiimport android.content.ClipData; 58ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Tokiimport android.content.ClipboardManager; 592191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport android.support.test.InstrumentationRegistry; 602191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport android.support.test.espresso.action.EspressoKey; 612191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport android.support.test.filters.MediumTest; 622191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport android.support.test.rule.ActivityTestRule; 632191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport android.support.test.runner.AndroidJUnit4; 642191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport android.text.InputType; 652191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport android.text.Selection; 662191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport android.text.Spannable; 676eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Tokiimport android.view.ActionMode; 682191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport android.view.KeyEvent; 696eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Tokiimport android.view.Menu; 706eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Tokiimport android.view.MenuItem; 716eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Tokiimport android.view.textclassifier.TextClassificationManager; 726eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Tokiimport android.view.textclassifier.TextClassifier; 739479d3ebe2457726d5b3624774b5540fb7d1e09cAbodunrinwa Tokiimport android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider; 74223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki 75c5b54bae62d5d82a576ca267202675652144185cAbodunrinwa Tokiimport com.android.frameworks.coretests.R; 76e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi 772191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport org.junit.Before; 782191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport org.junit.Rule; 792191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport org.junit.Test; 802191418305ca42e4f219020a02f16c045c539755Siyamed Sinirimport org.junit.runner.RunWith; 812191418305ca42e4f219020a02f16c045c539755Siyamed Sinir 82223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki/** 83223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki * Tests the TextView widget from an Activity 84223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki */ 852191418305ca42e4f219020a02f16c045c539755Siyamed Sinir@RunWith(AndroidJUnit4.class) 86c5b54bae62d5d82a576ca267202675652144185cAbodunrinwa Toki@MediumTest 872191418305ca42e4f219020a02f16c045c539755Siyamed Sinirpublic class TextViewActivityTest { 88223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki 892191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Rule 902191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public ActivityTestRule<TextViewActivity> mActivityRule = new ActivityTestRule<>( 912191418305ca42e4f219020a02f16c045c539755Siyamed Sinir TextViewActivity.class); 922191418305ca42e4f219020a02f16c045c539755Siyamed Sinir 932191418305ca42e4f219020a02f16c045c539755Siyamed Sinir private Activity mActivity; 942191418305ca42e4f219020a02f16c045c539755Siyamed Sinir private Instrumentation mInstrumentation; 95223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki 962191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Before 972191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void setUp() { 982191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity = mActivityRule.getActivity(); 992191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation = InstrumentationRegistry.getInstrumentation(); 1002191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getSystemService(TextClassificationManager.class) 1016eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki .setTextClassifier(TextClassifier.NO_OP); 102c9e924eb5347872aeec64ed09d1793ac8483ea10Abodunrinwa Toki } 103c9e924eb5347872aeec64ed09d1793ac8483ea10Abodunrinwa Toki 1042191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 1052191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testTypedTextIsOnScreen() { 106223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki final String helloWorld = "Hello world!"; 10799e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi // We use replaceText instead of typeTextIntoFocusedView to input text to avoid 10899e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi // unintentional interactions with software keyboard. 10999e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 110223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki 111223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki onView(withId(R.id.textview)).check(matches(withText(helloWorld))); 112223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki } 1132191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 1142191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testPositionCursorAtTextAtIndex() { 11590cdfe0514154bbc008d39f1c99f7a1d2684446cAbodunrinwa Toki final String helloWorld = "Hello world!"; 11699e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 11790cdfe0514154bbc008d39f1c99f7a1d2684446cAbodunrinwa Toki onView(withId(R.id.textview)).perform(clickOnTextAtIndex(helloWorld.indexOf("world"))); 11890cdfe0514154bbc008d39f1c99f7a1d2684446cAbodunrinwa Toki 11990cdfe0514154bbc008d39f1c99f7a1d2684446cAbodunrinwa Toki // Delete text at specified index and see if we got the right one. 12090cdfe0514154bbc008d39f1c99f7a1d2684446cAbodunrinwa Toki onView(withId(R.id.textview)).perform(pressKey(KeyEvent.KEYCODE_FORWARD_DEL)); 12190cdfe0514154bbc008d39f1c99f7a1d2684446cAbodunrinwa Toki onView(withId(R.id.textview)).check(matches(withText("Hello orld!"))); 12290cdfe0514154bbc008d39f1c99f7a1d2684446cAbodunrinwa Toki } 123ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Toki 1242191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 1252191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testPositionCursorAtTextAtIndex_arabic() { 126e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi // Arabic text. The expected cursorable boundary is 127e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi // | \u0623 \u064F | \u067A | \u0633 \u0652 | 128e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi final String text = "\u0623\u064F\u067A\u0633\u0652"; 129e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 130e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi 131e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0)); 132e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0)); 133e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(1)); 134e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(0), is(2)))); 135e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(2)); 136e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2)); 137e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(3)); 138e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(3)); 139e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(4)); 140e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(3), is(5)))); 141e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(5)); 142e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(5)); 143e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi } 144e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi 1452191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 1462191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testPositionCursorAtTextAtIndex_devanagari() { 147e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi // Devanagari text. The expected cursorable boundary is | \u0915 \u093E | 148e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi final String text = "\u0915\u093E"; 149e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 150e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi 151e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0)); 152e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0)); 153e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(1)); 154e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(0), is(2)))); 155e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(2)); 156e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2)); 157e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi } 158e27e0850fe4acbdc911e2e4e6272be10ac2f2779Keisuke Kuroyanagi 1592191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 1602191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testLongPressToSelect() { 1618a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki final String helloWorld = "Hello Kirk!"; 1628a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki onView(withId(R.id.textview)).perform(click()); 16399e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 1648a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki onView(withId(R.id.textview)).perform( 1658a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki longPressOnTextAtIndex(helloWorld.indexOf("Kirk"))); 1668a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki 1678a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki onView(withId(R.id.textview)).check(hasSelection("Kirk")); 1688a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki } 1698a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki 1702191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 1712191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testLongPressEmptySpace() { 1728a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki final String helloWorld = "Hello big round sun!"; 17399e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 1748a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki // Move cursor somewhere else 1758a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki onView(withId(R.id.textview)).perform(clickOnTextAtIndex(helloWorld.indexOf("big"))); 1768a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki // Long-press at end of line. 1779479d3ebe2457726d5b3624774b5540fb7d1e09cAbodunrinwa Toki onView(withId(R.id.textview)).perform(longPressAtRelativeCoordinates( 1789479d3ebe2457726d5b3624774b5540fb7d1e09cAbodunrinwa Toki RelativeCoordinatesProvider.HorizontalReference.RIGHT, -5, 1799479d3ebe2457726d5b3624774b5540fb7d1e09cAbodunrinwa Toki RelativeCoordinatesProvider.VerticalReference.CENTER, 0)); 1808a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki 1818a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(helloWorld.length())); 1828a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki } 1838a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki 1842191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 1852191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testLongPressAndDragToSelect() { 186ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Toki final String helloWorld = "Hello little handsome boy!"; 18799e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 188ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Toki onView(withId(R.id.textview)).perform( 189ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Toki longPressAndDragOnText(helloWorld.indexOf("little"), helloWorld.indexOf(" boy!"))); 190ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Toki 191ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Toki onView(withId(R.id.textview)).check(hasSelection("little handsome")); 192ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Toki } 193ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Toki 1942191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 1952191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testLongPressAndDragToSelect_emoji() { 196133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi final String text = "\uD83D\uDE00\uD83D\uDE01\uD83D\uDE02\uD83D\uDE03"; 197133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 198133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi 199133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressAndDragOnText(4, 6)); 200133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("\uD83D\uDE02")); 201133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi 202133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(click()); 203133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi 204133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressAndDragOnText(4, 2)); 205133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("\uD83D\uDE01")); 206133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi } 207133dfc0068d9f14eb9907a4ca77e4e87e8a705e4Keisuke Kuroyanagi 2082191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 2092191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testDragAndDrop() { 2104307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi final String text = "abc def ghi."; 21199e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 2124307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf("e"))); 2134307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi 2144307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi onView(withId(R.id.textview)).perform( 2154307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi longPressAndDragOnText(text.indexOf("e"), text.length())); 2164307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi 2174307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi onView(withId(R.id.textview)).check(matches(withText("abc ghi.def"))); 2184307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("")); 2194307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi assertNoSelectionHandles(); 2204307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex("abc ghi.def".length())); 221fae4578311970afadca8ee28a47e1e11df00eeddKeisuke Kuroyanagi 222fae4578311970afadca8ee28a47e1e11df00eeddKeisuke Kuroyanagi // Test undo returns to the original state. 223fae4578311970afadca8ee28a47e1e11df00eeddKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(pressKey( 224fae4578311970afadca8ee28a47e1e11df00eeddKeisuke Kuroyanagi (new EspressoKey.Builder()).withCtrlPressed(true).withKeyCode(KeyEvent.KEYCODE_Z) 225fae4578311970afadca8ee28a47e1e11df00eeddKeisuke Kuroyanagi .build())); 226fae4578311970afadca8ee28a47e1e11df00eeddKeisuke Kuroyanagi onView(withId(R.id.textview)).check(matches(withText(text))); 2274307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi } 2284307aeb935ab9c824f90d41bf181660c3937b1e4Keisuke Kuroyanagi 2292191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 2302191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testDoubleTapToSelect() { 2318a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki final String helloWorld = "Hello SuetYi!"; 23299e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 23399e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi 2348a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki onView(withId(R.id.textview)).perform( 2358a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki doubleClickOnTextAtIndex(helloWorld.indexOf("SuetYi"))); 2368a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki 2378a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki onView(withId(R.id.textview)).check(hasSelection("SuetYi")); 2388a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki } 2398a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki 2402191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 2412191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testDoubleTapAndDragToSelect() { 2422191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final String helloWorld = "Hello young beautiful person!"; 24399e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 2442191418305ca42e4f219020a02f16c045c539755Siyamed Sinir onView(withId(R.id.textview)).perform(doubleTapAndDragOnText(helloWorld.indexOf("young"), 2452191418305ca42e4f219020a02f16c045c539755Siyamed Sinir helloWorld.indexOf(" person!"))); 246ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Toki 247ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Toki onView(withId(R.id.textview)).check(hasSelection("young beautiful")); 248ca4aaf3c17fdea4e373accc212867bd9f1e2be7fAbodunrinwa Toki } 2498a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki 2502191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 2512191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testDoubleTapAndDragToSelect_multiLine() { 25268c433d6052b06f3c9688c740dd55c89f8b43d7fSara Kato final String helloWorld = "abcd\n" + "efg\n" + "hijklm\n" + "nop"; 25368c433d6052b06f3c9688c740dd55c89f8b43d7fSara Kato onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 25468c433d6052b06f3c9688c740dd55c89f8b43d7fSara Kato onView(withId(R.id.textview)).perform( 25568c433d6052b06f3c9688c740dd55c89f8b43d7fSara Kato doubleTapAndDragOnText(helloWorld.indexOf("m"), helloWorld.indexOf("a"))); 25668c433d6052b06f3c9688c740dd55c89f8b43d7fSara Kato onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijklm")); 25768c433d6052b06f3c9688c740dd55c89f8b43d7fSara Kato } 25868c433d6052b06f3c9688c740dd55c89f8b43d7fSara Kato 2592191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 2602191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testSelectBackwordsByTouch() { 2618a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki final String helloWorld = "Hello king of the Jungle!"; 26299e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(helloWorld)); 2638a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki onView(withId(R.id.textview)).perform( 2648a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki doubleTapAndDragOnText(helloWorld.indexOf(" Jungle!"), helloWorld.indexOf("king"))); 2658a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki 2668a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki onView(withId(R.id.textview)).check(hasSelection("king of the")); 2678a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki } 2688a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki 2692191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 2702191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testToolbarAppearsAfterSelection() { 2718a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki final String text = "Toolbar appears after selection."; 272b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarIsNotDisplayed(); 27399e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 2748a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki onView(withId(R.id.textview)).perform( 2758a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki longPressOnTextAtIndex(text.indexOf("appears"))); 2768a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki 277b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 278b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarIsDisplayed(); 279b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi 280b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi final String text2 = "Toolbar disappears after typing text."; 28199e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text2)); 28299e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 283b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarIsNotDisplayed(); 284b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi } 285b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi 2862191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 287987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir public void testToolbarAppearsAfterSelection_withFirstStringLtrAlgorithmAndRtlHint() 2882191418305ca42e4f219020a02f16c045c539755Siyamed Sinir throws Throwable { 289987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir // after the hint layout change, the floating toolbar was not visible in the case below 290987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir // this test tests that the floating toolbar is displayed on the screen and is visible to 291987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir // user. 2922191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivityRule.runOnUiThread(() -> { 2932191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 2942191418305ca42e4f219020a02f16c045c539755Siyamed Sinir textView.setTextDirection(TextView.TEXT_DIRECTION_FIRST_STRONG_LTR); 2952191418305ca42e4f219020a02f16c045c539755Siyamed Sinir textView.setInputType(InputType.TYPE_CLASS_TEXT); 2962191418305ca42e4f219020a02f16c045c539755Siyamed Sinir textView.setSingleLine(true); 2972191418305ca42e4f219020a02f16c045c539755Siyamed Sinir textView.setHint("الروبوت"); 298987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir }); 2992191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 300987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir 30199e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText("test")); 302987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(1)); 3032191418305ca42e4f219020a02f16c045c539755Siyamed Sinir clickFloatingToolbarItem(mActivity.getString(com.android.internal.R.string.cut)); 304987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir onView(withId(R.id.textview)).perform(longClick()); 305987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir sleepForFloatingToolbarPopup(); 306987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir 307987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir assertFloatingToolbarIsDisplayed(); 308987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir } 309987ec6588b2279891179c9eff09fc25ec14430c4Siyamed Sinir 3102191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 3112191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testToolbarAndInsertionHandle() { 312b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi final String text = "text"; 31399e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 314b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 315b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarIsNotDisplayed(); 316b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi 317b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.insertion_handle).perform(click()); 318b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 319b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarIsDisplayed(); 320b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi 321b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarContainsItem( 3222191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.selectAll)); 323b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarDoesNotContainItem( 3242191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.copy)); 325b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarDoesNotContainItem( 3262191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.cut)); 327b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi } 328b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi 3292191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 3302191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testToolbarAndSelectionHandle() { 331b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi final String text = "abcd efg hijk"; 33299e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 333b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi 334b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf("f"))); 335b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 336b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarIsDisplayed(); 337b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi 338b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarContainsItem( 3392191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.selectAll)); 340b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarContainsItem( 3412191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.copy)); 342b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarContainsItem( 3432191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.cut)); 344b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi 3452191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 346b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 347b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 348b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 349b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarIsDisplayed(); 350b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi 351b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 352b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.length())); 353b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 354b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarIsDisplayed(); 355b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi 356b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarDoesNotContainItem( 3572191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.selectAll)); 358b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarContainsItem( 3592191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.copy)); 360b0dd77c4115d333527a06cad84bc1c6ea8b4ac8eKeisuke Kuroyanagi assertFloatingToolbarContainsItem( 3612191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.cut)); 3628a5e1ae2f4e1aaf2db2a217e841371e18851df3fAbodunrinwa Toki } 363da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagi 3642191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 3652191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testInsertionHandle() { 366e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi final String text = "abcd efg hijk "; 36799e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 368e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi 369e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 370e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.length())); 371e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi 3722191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 373e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi 374e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.insertion_handle) 375e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('a'))); 376e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("a"))); 377e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi 378e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.insertion_handle) 379e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('f'))); 380e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("f"))); 381e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi } 382e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi 3832191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 3842191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testInsertionHandle_multiLine() { 385e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi final String text = "abcd\n" + "efg\n" + "hijk\n"; 38699e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 387e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi 388e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 389e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.length())); 390e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi 3912191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 392e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi 393e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.insertion_handle) 394e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('a'))); 395e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("a"))); 396e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi 397e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.insertion_handle) 398e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('f'))); 399e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("f"))); 400e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi } 401e8b3dd47914a52a229c1726b79fe8f02fb59bb73Keisuke Kuroyanagi 4022191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 4032191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testSelectionHandles() { 404da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagi final String text = "abcd efg hijk lmn"; 40599e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 406fc6e25ef6e288cf75d70cf8185ff1c8831428936Abodunrinwa Toki 407fc6e25ef6e288cf75d70cf8185ff1c8831428936Abodunrinwa Toki assertNoSelectionHandles(); 408fc6e25ef6e288cf75d70cf8185ff1c8831428936Abodunrinwa Toki 40999e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('f'))); 410da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagi 411fc6e25ef6e288cf75d70cf8185ff1c8831428936Abodunrinwa Toki onHandleView(com.android.internal.R.id.selection_start_handle) 412fc6e25ef6e288cf75d70cf8185ff1c8831428936Abodunrinwa Toki .check(matches(isDisplayed())); 413fc6e25ef6e288cf75d70cf8185ff1c8831428936Abodunrinwa Toki onHandleView(com.android.internal.R.id.selection_end_handle) 414fc6e25ef6e288cf75d70cf8185ff1c8831428936Abodunrinwa Toki .check(matches(isDisplayed())); 415fc6e25ef6e288cf75d70cf8185ff1c8831428936Abodunrinwa Toki 4162191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 417da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 418da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 419da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("abcd efg")); 420da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagi 421da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 422da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('k') + 1)); 423da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("abcd efg hijk")); 424da79ee683d74f2ad7d29147a30f3da17dd0ea6e2Keisuke Kuroyanagi } 425c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi 4262191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 4272191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testSelectionHandles_bidi() { 428f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi final String text = "abc \u0621\u0622\u0623 def"; 429f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 430f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi 431f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi assertNoSelectionHandles(); 432f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi 43399e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('\u0622'))); 434f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi 435f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 436f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi .check(matches(isDisplayed())); 437f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 438f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi .check(matches(isDisplayed())); 439f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi 440f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 441f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi 4422191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 443f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 444f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('f'))); 445f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 446f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi 447f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 448f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('a'))); 449f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 450f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi 451f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 45299e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u0623'), 453f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi false)); 454f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("\u0623")); 455f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi 456f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 457f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u0621'), 458f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi false)); 459f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("\u0621\u0622\u0623")); 460f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi 461f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 462f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 463f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("abc \u0621\u0622\u0623")); 464f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi 465f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 466f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.length())); 467f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("abc \u0621\u0622\u0623 def")); 468f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi } 469f0bb87b7c40efeeaee58d4c7b767961c9800463eKeisuke Kuroyanagi 4702191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 4712191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testSelectionHandles_multiLine() { 472c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi final String text = "abcd\n" + "efg\n" + "hijk\n" + "lmn\n" + "opqr"; 47399e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 47499e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 475c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi 4762191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 477c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 478c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('e'))); 479c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("efg\nhijk")); 480c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi 481c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 482c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); 483c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk")); 484c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi 485c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 486c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('n') + 1)); 487c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk\nlmn")); 488c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi 489c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 490c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('r') + 1)); 491c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk\nlmn\nopqr")); 492c24c2bbb69634435d1d9fc97671229df245bd8d0Keisuke Kuroyanagi } 493cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi 4942191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 4952191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testSelectionHandles_multiLine_rtl() { 49626454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi // Arabic text. 49726454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi final String text = "\u062A\u062B\u062C\n" + "\u062D\u062E\u062F\n" 49826454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi + "\u0630\u0631\u0632\n" + "\u0633\u0634\u0635\n" + "\u0636\u0637\u0638\n" 49926454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi + "\u0639\u063A\u063B"; 50026454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 50199e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('\u0634'))); 50226454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi 5032191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 50426454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 50526454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u062E'))); 50626454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection( 50726454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi text.substring(text.indexOf('\u062D'), text.indexOf('\u0635') + 1))); 50826454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi 50926454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 51026454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('\u062A'))); 51126454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection( 51226454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi text.substring(text.indexOf('\u062A'), text.indexOf('\u0635') + 1))); 51326454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi 51426454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 51526454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('\u0638'))); 51626454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection( 51726454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi text.substring(text.indexOf('\u062A'), text.indexOf('\u0638') + 1))); 51826454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi 51926454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 52026454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('\u063B'))); 52126454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection(text)); 52226454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi } 52326454141a8c489d84b7d486ad03869ff0f44dfdcKeisuke Kuroyanagi 5242191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 5252191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testSelectionHandles_doesNotPassAnotherHandle() { 526cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi final String text = "abcd efg hijk lmn"; 52799e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 52899e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('f'))); 529cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi 5302191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 531cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 532cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('l'))); 533cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("g")); 534cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi 53599e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('f'))); 536cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 537cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('a'))); 538cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("e")); 539cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi } 540cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi 5412191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 5422191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testSelectionHandles_doesNotPassAnotherHandle_multiLine() { 543cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi final String text = "abcd\n" + "efg\n" + "hijk\n" + "lmn\n" + "opqr"; 54499e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 54599e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 546cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi 5472191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 548cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 549cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('r') + 1)); 550cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("k")); 551cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi 55299e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 553cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 554cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('a'))); 555cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("h")); 556cb6e8420cbf8bc4000d4761e38fd6d830fc1aca0Keisuke Kuroyanagi } 557ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 5582191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 5592191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testSelectionHandles_snapToWordBoundary() { 560ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi final String text = "abcd efg hijk lmn opqr"; 56199e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 56299e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 563ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 5642191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 565ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 566ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 567ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('f'))); 568ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("efg hijk")); 569ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 570ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 571ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('d') + 1)); 572ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("efg hijk")); 573ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 574ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 575ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 576ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('c'))); 577ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("abcd efg hijk")); 578ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 579ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 580ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('d'))); 581ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("d efg hijk")); 582ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 583ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 584ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('b'))); 585ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("bcd efg hijk")); 586ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 58799e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(click()); 58899e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 589ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 590ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 591ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('n'))); 592ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("hijk lmn")); 593ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 594ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 595ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('o'))); 596ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("hijk lmn")); 597ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 598ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 599ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('q'))); 600ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("hijk lmn opqr")); 601ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 602ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 603ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('p'))); 604ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("hijk lmn o")); 605ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 606ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 607ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('r'))); 608ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("hijk lmn opq")); 609ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi } 610ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 6112191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 6122191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testSelectionHandles_snapToWordBoundary_multiLine() { 613ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi final String text = "abcd efg\n" + "hijk lmn\n" + "opqr stu"; 61499e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 61599e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('m'))); 616ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 6172191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 618ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 619ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 620ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('c'))); 621ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("abcd efg\nhijk lmn")); 622ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 623ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 624ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('g'))); 625ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("g\nhijk lmn")); 626ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 627ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_start_handle) 628ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('m'))); 629ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("lmn")); 630ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 63199e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('i'))); 632ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 633ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 634ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('u'))); 635ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("hijk lmn\nopqr stu")); 636ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 637ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 638ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('p'))); 639ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("hijk lmn\no")); 640ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi 641ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onHandleView(com.android.internal.R.id.selection_end_handle) 642ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('i'))); 643ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi onView(withId(R.id.textview)).check(hasSelection("hijk")); 644ec913c0eb6c3cb70f69653ee988d440f47e5cc55Keisuke Kuroyanagi } 645c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi 6462191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 6472191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testSetSelectionAndActionMode() throws Throwable { 648c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi final String text = "abc def"; 649c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 650c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi 6512191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 652c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarIsNotDisplayed(); 6532191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivityRule.runOnUiThread( 6542191418305ca42e4f219020a02f16c045c539755Siyamed Sinir () -> Selection.setSelection((Spannable) textView.getText(), 0, 3)); 6552191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 656c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 657c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // Don't automatically start action mode. 658c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarIsNotDisplayed(); 659c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // Make sure that "Select All" is included in the selection action mode when the entire text 660c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // is not selected. 66199e86231851c23a6d198b2abeb880db097c541aeKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('e'))); 662c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 663c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarIsDisplayed(); 664c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // Changing the selection range by API should not interrupt the selection action mode. 6652191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivityRule.runOnUiThread( 6662191418305ca42e4f219020a02f16c045c539755Siyamed Sinir () -> Selection.setSelection((Spannable) textView.getText(), 0, 3)); 6672191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 668c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 669c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarIsDisplayed(); 670c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarContainsItem( 6712191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.selectAll)); 672c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // Make sure that "Select All" is no longer included when the entire text is selected by 673c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // API. 6742191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivityRule.runOnUiThread( 675c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length())); 6762191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 6772191418305ca42e4f219020a02f16c045c539755Siyamed Sinir 678c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 679c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarIsDisplayed(); 680c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarDoesNotContainItem( 6812191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.selectAll)); 682c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // Make sure that shrinking the selection range to cursor (an empty range) by API 683c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // terminates selection action mode and does not trigger the insertion action mode. 6842191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivityRule.runOnUiThread( 6852191418305ca42e4f219020a02f16c045c539755Siyamed Sinir () -> Selection.setSelection((Spannable) textView.getText(), 0)); 6862191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 6872191418305ca42e4f219020a02f16c045c539755Siyamed Sinir 688c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 689c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarIsNotDisplayed(); 690c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // Make sure that user click can trigger the insertion action mode. 691c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); 692c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi onHandleView(com.android.internal.R.id.insertion_handle).perform(click()); 693c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 694c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarIsDisplayed(); 695c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // Make sure that an existing insertion action mode keeps alive after the insertion point is 696c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // moved by API. 6972191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivityRule.runOnUiThread( 6982191418305ca42e4f219020a02f16c045c539755Siyamed Sinir () -> Selection.setSelection((Spannable) textView.getText(), 0)); 6992191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 7002191418305ca42e4f219020a02f16c045c539755Siyamed Sinir 701c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 702c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarIsDisplayed(); 703c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarDoesNotContainItem( 7042191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.copy)); 705c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // Make sure that selection action mode is started after selection is created by API when 706c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi // insertion action mode is active. 7072191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivityRule.runOnUiThread( 708c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi () -> Selection.setSelection((Spannable) textView.getText(), 1, text.length())); 7092191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 7102191418305ca42e4f219020a02f16c045c539755Siyamed Sinir 711c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi sleepForFloatingToolbarPopup(); 712c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarIsDisplayed(); 713c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi assertFloatingToolbarContainsItem( 7142191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.copy)); 715c477b5830af5f9e87069fae4ff87a2a6b3e275fbKeisuke Kuroyanagi } 716183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi 7172191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 7182191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testTransientState() throws Throwable { 719183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi final String text = "abc def"; 720183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(replaceText(text)); 721183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi 7222191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 723183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi assertFalse(textView.hasTransientState()); 724183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi 725183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('b'))); 726183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi // hasTransientState should return true when user generated selection is active. 727183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi assertTrue(textView.hasTransientState()); 728183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('d'))); 729183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi // hasTransientState should return false as the selection has been cleared. 730183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi assertFalse(textView.hasTransientState()); 7312191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivityRule.runOnUiThread( 732183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length())); 7332191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 7342191418305ca42e4f219020a02f16c045c539755Siyamed Sinir 735183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi // hasTransientState should return false when selection is created by API. 736183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi assertFalse(textView.hasTransientState()); 737183fd5071ea84aab82209c827fa0e4ff84a6b590Keisuke Kuroyanagi } 7386eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki 7392191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 7402191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testResetMenuItemTitle() throws Throwable { 7412191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getSystemService(TextClassificationManager.class).setTextClassifier(null); 7422191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 7437b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki final int itemId = 1; 7447b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki final String title1 = " AFIGBO"; 7457b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki final int index = title1.indexOf('I'); 7467b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki final String title2 = title1.substring(index); 7477b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki final String[] title = new String[]{title1}; 7482191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivityRule.runOnUiThread(() -> textView.setCustomSelectionActionModeCallback( 7497b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki new ActionMode.Callback() { 7507b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki @Override 7517b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { 7527b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki return true; 7537b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki } 7547b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki 7557b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki @Override 7567b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { 7577b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki menu.removeItem(itemId); 7587b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki menu.add(Menu.NONE /* group */, itemId, 0 /* order */, title[0]); 7597b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki return true; 7607b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki } 7617b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki 7627b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki @Override 7637b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { 7647b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki return false; 7657b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki } 7667b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki 7677b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki @Override 7687b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki public void onDestroyActionMode(ActionMode actionMode) { 7697b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki } 7707b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki })); 7712191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 7722191418305ca42e4f219020a02f16c045c539755Siyamed Sinir 7737b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki onView(withId(R.id.textview)).perform(replaceText(title1)); 7747b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(index)); 7757b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki sleepForFloatingToolbarPopup(); 7767b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki assertFloatingToolbarContainsItem(title1); 7777b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki 7787b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki // Change the menu item title. 7797b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki title[0] = title2; 7807b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki // Change the selection to invalidate the action mode without restarting it. 7817b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki onHandleView(com.android.internal.R.id.selection_start_handle) 7827b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki .perform(dragHandle(textView, Handle.SELECTION_START, index)); 7837b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki sleepForFloatingToolbarPopup(); 7847b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki assertFloatingToolbarContainsItem(title2); 7857b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki } 7867b97180ddfdc3dd6b595ac44b5df8dce137e80c6Abodunrinwa Toki 7872191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 7882191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testAssistItemIsAtIndexZero() throws Throwable { 78976b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki useSystemDefaultTextClassifier(); 7902191418305ca42e4f219020a02f16c045c539755Siyamed Sinir final TextView textView = mActivity.findViewById(R.id.textview); 7912191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivityRule.runOnUiThread(() -> textView.setCustomSelectionActionModeCallback( 7926eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki new ActionMode.Callback() { 7936eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki @Override 7946eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { 7956eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki // Create another item at order position 0 to confirm that it will never be 7966eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki // placed before the textAssist item. 7976eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki menu.add(Menu.NONE, 0 /* id */, 0 /* order */, "Test"); 7986eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki return true; 7996eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki } 8006eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki 8016eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki @Override 8026eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { 8036eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki return true; 8046eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki } 8056eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki 8066eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki @Override 8076eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { 8086eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki return false; 8096eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki } 8106eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki 8116eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki @Override 812ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki public void onDestroyActionMode(ActionMode actionMode) { 813ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki } 8146eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki })); 8152191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 8166eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki final String text = "droid@android.com"; 8176eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki 8186eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki onView(withId(R.id.textview)).perform(replaceText(text)); 8196eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('@'))); 8206eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki sleepForFloatingToolbarPopup(); 8216eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki assertFloatingToolbarItemIndex(android.R.id.textAssist, 0); 8226eecdc934c6050d67a639116cde600c09e5b76bdAbodunrinwa Toki } 823ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki 8242191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 82576b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki public void testNoAssistItemForPasswordField() throws Throwable { 82676b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki useSystemDefaultTextClassifier(); 82776b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki final TextView textView = mActivity.findViewById(R.id.textview); 82876b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki mActivityRule.runOnUiThread(() -> { 82976b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki textView.setInputType( 83076b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); 83176b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki }); 83276b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki mInstrumentation.waitForIdleSync(); 83376b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki final String password = "afigbo@android.com"; 83476b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki 83576b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki onView(withId(R.id.textview)).perform(replaceText(password)); 83676b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(password.indexOf('@'))); 83776b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki sleepForFloatingToolbarPopup(); 83876b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki assertFloatingToolbarDoesNotContainItem(android.R.id.textAssist); 83976b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki } 84076b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki 84176b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki @Test 8422191418305ca42e4f219020a02f16c045c539755Siyamed Sinir public void testPastePlainText_menuAction() { 843ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki initializeClipboardWithText(TextStyle.STYLED); 844ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki 845ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki onView(withId(R.id.textview)).perform(replaceText("")); 846ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki onView(withId(R.id.textview)).perform(longClick()); 847ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki sleepForFloatingToolbarPopup(); 848ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki clickFloatingToolbarItem( 8492191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.paste_as_plain_text)); 8502191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 851ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki 852ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki onView(withId(R.id.textview)).check(matches(withText("styledtext"))); 853ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki onView(withId(R.id.textview)).check(doesNotHaveStyledText()); 854ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki } 855ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki 8562191418305ca42e4f219020a02f16c045c539755Siyamed Sinir @Test 857ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki public void testPastePlainText_noMenuItemForPlainText() { 858ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki initializeClipboardWithText(TextStyle.PLAIN); 859ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki 860ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki onView(withId(R.id.textview)).perform(replaceText("")); 861ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki onView(withId(R.id.textview)).perform(longClick()); 862ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki sleepForFloatingToolbarPopup(); 863ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki 864ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki assertFloatingToolbarDoesNotContainItem( 8652191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getString(com.android.internal.R.string.paste_as_plain_text)); 866ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki } 867ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki 86876b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki private void useSystemDefaultTextClassifier() { 86976b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki mActivity.getSystemService(TextClassificationManager.class).setTextClassifier(null); 87076b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki } 87176b51dc450255bd1774f0309745ceb404b4cc5cfAbodunrinwa Toki 872ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki private void initializeClipboardWithText(TextStyle textStyle) { 873ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki final ClipData clip; 874ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki switch (textStyle) { 875ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki case STYLED: 876ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki clip = ClipData.newHtmlText("html", "styledtext", "<b>styledtext</b>"); 877ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki break; 878ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki case PLAIN: 879ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki clip = ClipData.newPlainText("plain", "plaintext"); 880ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki break; 881ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki default: 882ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki throw new IllegalArgumentException("Invalid text style"); 883ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki } 8842191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getWindow().getDecorView().post(() -> 8852191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mActivity.getSystemService(ClipboardManager.class).setPrimaryClip(clip)); 8862191418305ca42e4f219020a02f16c045c539755Siyamed Sinir mInstrumentation.waitForIdleSync(); 887ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki } 888ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki 889ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki private enum TextStyle { 890ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki PLAIN, STYLED 891ea6cb1215e97232bf96da02e35b6b8e938572eaaAbodunrinwa Toki } 892223c8392f066823cf4a3a98957960deb80ab1680Abodunrinwa Toki} 893