1 /* 2 * Copyright (C) 2016 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 17 package android.widget; 18 19 import android.test.ActivityInstrumentationTestCase2; 20 import android.test.suitebuilder.annotation.SmallTest; 21 import android.view.Choreographer; 22 import android.view.ViewGroup; 23 24 import java.util.concurrent.CountDownLatch; 25 import java.util.concurrent.TimeUnit; 26 27 import static android.support.test.espresso.Espresso.onView; 28 import static android.support.test.espresso.action.ViewActions.click; 29 import static android.widget.espresso.TextViewAssertions.hasInsertionPointerOnLeft; 30 import static android.widget.espresso.TextViewAssertions.hasInsertionPointerOnRight; 31 import static org.hamcrest.MatcherAssert.assertThat; 32 import static org.hamcrest.Matchers.equalTo; 33 import static org.hamcrest.Matchers.isEmptyString; 34 import static org.hamcrest.Matchers.nullValue; 35 import static org.hamcrest.Matchers.sameInstance; 36 37 public class EditorCursorTest extends ActivityInstrumentationTestCase2<TextViewActivity> { 38 39 40 private final static String LTR_STRING = "aaaaaaaaaaaaaaaaaaaaaa"; 41 private final static String LTR_HINT = "hint"; 42 private final static String RTL_STRING = " "; 43 private final static String RTL_HINT = ""; 44 private final static int CURSOR_BLINK_MS = 500; 45 46 private EditText mEditText; 47 48 public EditorCursorTest() { 49 super(TextViewActivity.class); 50 } 51 52 @Override 53 protected void setUp() throws Exception { 54 super.setUp(); 55 mEditText = new EditText(getActivity()); 56 mEditText.setTextSize(30); 57 mEditText.setSingleLine(true); 58 mEditText.setLines(1); 59 mEditText.setPadding(15, 15, 15, 15); 60 ViewGroup.LayoutParams editTextLayoutParams = new ViewGroup.LayoutParams(200, 61 ViewGroup.LayoutParams.WRAP_CONTENT); 62 63 mEditText.setLayoutParams(editTextLayoutParams); 64 65 final FrameLayout layout = new FrameLayout(getActivity()); 66 ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams( 67 ViewGroup.LayoutParams.MATCH_PARENT, 68 ViewGroup.LayoutParams.MATCH_PARENT); 69 layout.setLayoutParams(layoutParams); 70 layout.addView(mEditText); 71 72 getActivity().runOnUiThread(new Runnable() { 73 @Override 74 public void run() { 75 getActivity().setContentView(layout); 76 } 77 }); 78 getInstrumentation().waitForIdleSync(); 79 onView(sameInstance(mEditText)).perform(click()); 80 } 81 82 @SmallTest 83 public void testCursorIsInViewBoundariesWhenOnRightForLtr() { 84 // Asserts that when an EditText has LTR text, and cursor is at the end (right), 85 // cursor is drawn to the right edge of the view 86 setEditTextText(LTR_STRING, LTR_STRING.length()); 87 88 onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight()); 89 } 90 91 @SmallTest 92 public void testCursorIsInViewBoundariesWhenOnLeftForLtr() { 93 // Asserts that when an EditText has LTR text, and cursor is at the beginning, 94 // cursor is drawn to the left edge of the view 95 setEditTextText(LTR_STRING, 0); 96 97 onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft()); 98 } 99 100 @SmallTest 101 public void testCursorIsInViewBoundariesWhenOnRightForRtl() { 102 // Asserts that when an EditText has RTL text, and cursor is at the end, 103 // cursor is drawn to the left edge of the view 104 setEditTextText(RTL_STRING, 0); 105 106 onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight()); 107 } 108 109 @SmallTest 110 public void testCursorIsInViewBoundariesWhenOnLeftForRtl() { 111 // Asserts that when an EditText has RTL text, and cursor is at the beginning, 112 // cursor is drawn to the right edge of the view 113 setEditTextText(RTL_STRING, RTL_STRING.length()); 114 115 onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft()); 116 } 117 118 /* Tests for cursor positioning with hint */ 119 @SmallTest 120 public void testCursorIsOnLeft_withFirstStrongLtrAlgorithm() { 121 setEditTextHint(null, TextView.TEXT_DIRECTION_FIRST_STRONG_LTR, 0); 122 assertThat(mEditText.getText().toString(), isEmptyString()); 123 assertThat(mEditText.getHint(), nullValue()); 124 125 onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft()); 126 127 setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_LTR, 0); 128 assertThat(mEditText.getText().toString(), isEmptyString()); 129 130 onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft()); 131 132 setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_LTR, 0); 133 assertThat(mEditText.getText().toString(), isEmptyString()); 134 135 onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft()); 136 } 137 138 @SmallTest 139 public void testCursorIsOnRight_withFirstStrongRtlAlgorithm() { 140 setEditTextHint(null, TextView.TEXT_DIRECTION_FIRST_STRONG_RTL, 0); 141 assertThat(mEditText.getText().toString(), isEmptyString()); 142 assertThat(mEditText.getHint(), nullValue()); 143 144 onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight()); 145 146 setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_RTL, 0); 147 assertThat(mEditText.getText().toString(), isEmptyString()); 148 149 onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight()); 150 151 setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_RTL, 0); 152 assertThat(mEditText.getText().toString(), isEmptyString()); 153 154 onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight()); 155 } 156 157 @SmallTest 158 public void testCursorIsOnLeft_withLtrAlgorithm() { 159 setEditTextHint(null, TextView.TEXT_DIRECTION_LTR, 0); 160 assertThat(mEditText.getText().toString(), isEmptyString()); 161 assertThat(mEditText.getHint(), nullValue()); 162 163 onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft()); 164 165 setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_LTR, 0); 166 assertThat(mEditText.getText().toString(), isEmptyString()); 167 168 onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft()); 169 170 setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_LTR, 0); 171 assertThat(mEditText.getText().toString(), isEmptyString()); 172 173 onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft()); 174 } 175 176 @SmallTest 177 public void testCursorIsOnRight_withRtlAlgorithm() { 178 setEditTextHint(null, TextView.TEXT_DIRECTION_RTL, 0); 179 assertThat(mEditText.getText().toString(), isEmptyString()); 180 assertThat(mEditText.getHint(), nullValue()); 181 182 onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight()); 183 184 setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_RTL, 0); 185 assertThat(mEditText.getText().toString(), isEmptyString()); 186 187 onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight()); 188 189 setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_RTL, 0); 190 assertThat(mEditText.getText().toString(), isEmptyString()); 191 192 onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight()); 193 } 194 195 private void setEditTextProperties(final String text, final String hint, 196 final Integer textDirection, final Integer selection) { 197 getActivity().runOnUiThread(new Runnable() { 198 @Override 199 public void run() { 200 if (textDirection != null) mEditText.setTextDirection(textDirection); 201 if (text != null) mEditText.setText(text); 202 if (hint != null) mEditText.setHint(hint); 203 if (selection != null) mEditText.setSelection(selection); 204 } 205 }); 206 getInstrumentation().waitForIdleSync(); 207 208 // wait for cursor to be drawn. updateCursorPositions function is called during draw() and 209 // only when cursor is visible during blink. 210 final CountDownLatch latch = new CountDownLatch(1); 211 mEditText.postOnAnimationDelayed(new Runnable() { 212 @Override 213 public void run() { 214 latch.countDown(); 215 } 216 }, CURSOR_BLINK_MS); 217 try { 218 assertThat("Problem while waiting for the cursor to blink", 219 latch.await(10, TimeUnit.SECONDS), equalTo(true)); 220 } catch (Exception e) { 221 fail("Problem while waiting for the cursor to blink"); 222 } 223 } 224 225 private void setEditTextHint(final String hint, final int textDirection, final int selection) { 226 setEditTextProperties(null, hint, textDirection, selection); 227 } 228 229 private void setEditTextText(final String text, final Integer selection) { 230 setEditTextProperties(text, null, null, selection); 231 } 232 } 233