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