TextViewTest.java revision a3cf2598fa76975e1051852c12fffe208cdfb52c
1fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su/*
2fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * Copyright (C) 2008 The Android Open Source Project
3fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su *
4fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * Licensed under the Apache License, Version 2.0 (the "License");
5fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * you may not use this file except in compliance with the License.
6fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * You may obtain a copy of the License at
7fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su *
8fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su *      http://www.apache.org/licenses/LICENSE-2.0
9fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su *
10fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * Unless required by applicable law or agreed to in writing, software
11fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * distributed under the License is distributed on an "AS IS" BASIS,
12fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * See the License for the specific language governing permissions and
14fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * limitations under the License.
15fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su */
16fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
17fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Supackage android.widget.cts;
18fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
19a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.junit.Assert.assertEquals;
20a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.junit.Assert.assertFalse;
21a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.junit.Assert.assertNotNull;
22a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.junit.Assert.assertNull;
23a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.junit.Assert.assertSame;
24a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.junit.Assert.assertTrue;
25a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.junit.Assert.fail;
26a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Matchers.any;
27a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Matchers.eq;
28a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Matchers.refEq;
29a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.doAnswer;
30a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.doCallRealMethod;
31a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.doNothing;
32a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.mock;
33a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.never;
34a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.reset;
35a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.spy;
36a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.times;
37a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.verify;
38a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.verifyNoMoreInteractions;
39a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.verifyZeroInteractions;
40a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport static org.mockito.Mockito.when;
41be24fc17bf75d329d40d8acce9e22d8d3ff30f1fAurimas Liutikas
42fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.app.Activity;
43fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.app.Instrumentation;
44fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.app.Instrumentation.ActivityMonitor;
45354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.content.Context;
46fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.content.Intent;
472751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonakaimport android.content.pm.PackageManager;
48fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.content.res.ColorStateList;
49938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikovimport android.content.res.Resources;
50fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.content.res.Resources.NotFoundException;
51b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanuimport android.cts.util.CtsKeyEventUtil;
52a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport android.cts.util.CtsTouchUtils;
530162547f44173f0604d8a80143c128d9892460a1Kristian Monsenimport android.cts.util.PollingCheck;
54d82745ff4a8b174f7be1258fd329dedc52ce58bbChenjie Luoimport android.cts.util.WidgetTestUtils;
55fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.Color;
56fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.Paint;
57afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.graphics.Path;
589560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanuimport android.graphics.Point;
59fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukaiimport android.graphics.PorterDuff;
60fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.Rect;
61afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.graphics.RectF;
62fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.Typeface;
63fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.drawable.BitmapDrawable;
64ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levienimport android.graphics.drawable.ColorDrawable;
65fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.drawable.Drawable;
66fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.net.Uri;
67fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.os.Bundle;
68354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.os.Handler;
69265b3d21959154e9a6ce0fdd888249f3699b7bddYohei Yukawaimport android.os.LocaleList;
70354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.os.Looper;
715b51f77b99861d48fec1c327252416f726b3b01aJames Cookimport android.os.Parcelable;
72354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.os.ResultReceiver;
7357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarriimport android.os.SystemClock;
74a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport android.support.test.InstrumentationRegistry;
75a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport android.support.test.annotation.UiThreadTest;
763763966148d1d014b62a1bd27a68021c5ca17240Kirill Grouchnikovimport android.support.test.filters.MediumTest;
773763966148d1d014b62a1bd27a68021c5ca17240Kirill Grouchnikovimport android.support.test.filters.SmallTest;
78a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport android.support.test.rule.ActivityTestRule;
79a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport android.support.test.runner.AndroidJUnit4;
80fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.Editable;
81fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.InputFilter;
82fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.InputType;
83fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.Layout;
84fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.Selection;
85fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.Spannable;
86fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.SpannableString;
87ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levienimport android.text.Spanned;
88fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.TextPaint;
89fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.TextUtils;
90fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.TextUtils.TruncateAt;
91afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.text.TextWatcher;
92fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.ArrowKeyMovementMethod;
93fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.DateKeyListener;
94fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.DateTimeKeyListener;
95fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.DialerKeyListener;
96fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.DigitsKeyListener;
97fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.KeyListener;
98fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.LinkMovementMethod;
99fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.MovementMethod;
100fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.PasswordTransformationMethod;
101fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.QwertyKeyListener;
102fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.SingleLineTransformationMethod;
103fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.TextKeyListener;
104afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.text.method.TextKeyListener.Capitalize;
105fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.TimeKeyListener;
106fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.TransformationMethod;
10757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarriimport android.text.style.ClickableSpan;
10898d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinirimport android.text.style.ImageSpan;
109fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.style.URLSpan;
110ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagiimport android.text.style.UnderlineSpan;
111fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.util.Linkify;
112fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.util.DisplayMetrics;
1139560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanuimport android.util.SparseArray;
114fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.util.TypedValue;
115ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levienimport android.view.ActionMode;
116fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.view.ContextMenu;
117afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.view.ContextMenu.ContextMenuInfo;
118fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.view.Gravity;
11957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarriimport android.view.InputDevice;
120fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.view.KeyEvent;
12132944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagiimport android.view.Menu;
12257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarriimport android.view.MotionEvent;
12357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarriimport android.view.PointerIcon;
124fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.view.View;
1259560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanuimport android.view.ViewConfiguration;
126afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.view.ViewGroup;
1279560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanuimport android.view.ViewGroup.LayoutParams;
12832944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagiimport android.view.accessibility.AccessibilityNodeInfo;
12972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubachimport android.view.inputmethod.BaseInputConnection;
13018731b8489073e46e594c798247e5b6338204c3eSiyamed Sinirimport android.view.inputmethod.CompletionInfo;
13171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagiimport android.view.inputmethod.CorrectionInfo;
13272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubachimport android.view.inputmethod.EditorInfo;
13372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubachimport android.view.inputmethod.ExtractedText;
13472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubachimport android.view.inputmethod.ExtractedTextRequest;
135c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cookimport android.view.inputmethod.InputConnection;
136354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.view.inputmethod.InputMethodManager;
137c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunneimport android.widget.EditText;
138bed9d222439713a766c3d5c91fae1526b5bc35dcBrian Muramatsuimport android.widget.FrameLayout;
13962808562ee0218f6ea3c07d333f7a65fc57c122fBrian Muramatsuimport android.widget.LinearLayout;
140354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.widget.ScrollView;
141fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.widget.Scroller;
142fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.widget.TextView;
143fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.widget.TextView.BufferType;
144938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikovimport android.widget.cts.util.TestUtils;
145fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
146a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport org.junit.Before;
147a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport org.junit.Rule;
148a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport org.junit.Test;
149a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovimport org.junit.runner.RunWith;
150938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikovimport org.mockito.invocation.InvocationOnMock;
151ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levienimport org.xmlpull.v1.XmlPullParserException;
152ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien
153fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport java.io.IOException;
154b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonakaimport java.util.Locale;
155fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
156fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su/**
157fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * Test {@link TextView}.
158fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su */
159a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov@MediumTest
160a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov@RunWith(AndroidJUnit4.class)
161a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikovpublic class TextViewTest {
162fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private Instrumentation mInstrumentation;
163a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    private Activity mActivity;
164a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    private TextView mTextView;
1659560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    private TextView mSecondTextView;
166a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov
167fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private static final String LONG_TEXT = "This is a really long string which exceeds "
1687375565c2caf62392b32049cafb7df0730373794Gilles Debunne            + "the width of the view. New devices have a much larger screen which "
1697375565c2caf62392b32049cafb7df0730373794Gilles Debunne            + "actually enables long strings to be displayed with no fading. "
1707375565c2caf62392b32049cafb7df0730373794Gilles Debunne            + "I have made this string longer to fix this case. If you are correcting "
1717375565c2caf62392b32049cafb7df0730373794Gilles Debunne            + "this text, I would love to see the kind of devices you guys now use!";
172fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private static final long TIMEOUT = 5000;
17322d40a1fcc078329a7e5a34ff5eeadeca9c70d49Kenny Root    private CharSequence mTransformedText;
174354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    private Handler mHandler = new Handler(Looper.getMainLooper());
175fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
176a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Rule
177a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    public ActivityTestRule<TextViewCtsActivity> mActivityRule =
178a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov            new ActivityTestRule<>(TextViewCtsActivity.class);
179fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
180a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Before
181a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    public void setup() {
182a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation = InstrumentationRegistry.getInstrumentation();
183a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mActivity = mActivityRule.getActivity();
184b7724cefaf6067b1f6b59d3abae73828b48945c3Kirill Grouchnikov        PollingCheck.waitFor(mActivity::hasWindowFocus);
185fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
186fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
18728715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    /**
1886beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu     * Promotes the TextView to editable and places focus in it to allow simulated typing. Used in
189a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov     * test methods annotated with {@link UiThreadTest}.
19028715a6877392e4e63cb2b0170c1592fb50079dcJames Cook     */
19128715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    private void initTextViewForTyping() {
1926beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView = findTextView(R.id.textview_text);
1936beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setKeyListener(QwertyKeyListener.getInstance(false, Capitalize.NONE));
1946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setText("", BufferType.EDITABLE);
1956beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.requestFocus();
1966beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    }
1976beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
1986beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    /**
1996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu     * Used in test methods that can not entirely be run on the UiThread (e.g: tests that need to
2006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu     * emulate touches and/or key presses).
2016beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu     */
2024b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    private void initTextViewForTypingOnUiThread() throws Throwable {
2034b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(this::initTextViewForTyping);
20428715a6877392e4e63cb2b0170c1592fb50079dcJames Cook        mInstrumentation.waitForIdleSync();
20528715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    }
20628715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
207047c430fa4b8c5dfb7735fe32b8a3d5abf8bbbafAndrei Stingaceanu    @UiThreadTest
208a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
209047c430fa4b8c5dfb7735fe32b8a3d5abf8bbbafAndrei Stingaceanu    public void testConstructorOnUiThread() {
210047c430fa4b8c5dfb7735fe32b8a3d5abf8bbbafAndrei Stingaceanu        verifyConstructor();
211047c430fa4b8c5dfb7735fe32b8a3d5abf8bbbafAndrei Stingaceanu    }
212fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
213047c430fa4b8c5dfb7735fe32b8a3d5abf8bbbafAndrei Stingaceanu    @Test
214047c430fa4b8c5dfb7735fe32b8a3d5abf8bbbafAndrei Stingaceanu    public void testConstructorOffUiThread() {
215047c430fa4b8c5dfb7735fe32b8a3d5abf8bbbafAndrei Stingaceanu        verifyConstructor();
216047c430fa4b8c5dfb7735fe32b8a3d5abf8bbbafAndrei Stingaceanu    }
217fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
218047c430fa4b8c5dfb7735fe32b8a3d5abf8bbbafAndrei Stingaceanu    private void verifyConstructor() {
219047c430fa4b8c5dfb7735fe32b8a3d5abf8bbbafAndrei Stingaceanu        new TextView(mActivity);
220047c430fa4b8c5dfb7735fe32b8a3d5abf8bbbafAndrei Stingaceanu        new TextView(mActivity, null);
221938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        new TextView(mActivity, null, android.R.attr.textViewStyle);
222f0b8eb2d36b704834dd594c9eebe7f7134a94b40Kirill Grouchnikov        new TextView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_TextView);
223f0b8eb2d36b704834dd594c9eebe7f7134a94b40Kirill Grouchnikov        new TextView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_TextView);
224f0b8eb2d36b704834dd594c9eebe7f7134a94b40Kirill Grouchnikov        new TextView(mActivity, null, 0, android.R.style.Widget_Material_TextView);
225938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        new TextView(mActivity, null, 0, android.R.style.Widget_Material_Light_TextView);
226fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
227fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
228fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
229a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
230fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessText() {
231fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView tv = findTextView(R.id.textview_text);
232fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
233fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String expected = mActivity.getResources().getString(R.string.text_view_hello);
234fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(expected);
235fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(expected, tv.getText().toString());
236fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
237fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(null);
238fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", tv.getText().toString());
239fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
240fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2419560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
242a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
243fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetLineHeight() {
244fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
245fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLineHeight() > 0);
246fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
247fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLineSpacing(1.2f, 1.5f);
248fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLineHeight() > 0);
249fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
250fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
251a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2524b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testGetLayout() throws Throwable {
2539560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
2546beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = findTextView(R.id.textview_text);
2556beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.CENTER);
256fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
257fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
258fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(mTextView.getLayout());
259fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
260fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TestLayoutRunnable runnable = new TestLayoutRunnable(mTextView) {
261fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            public void run() {
262fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                // change the text of TextView.
263fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.setText("Hello, Android!");
264fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                saveLayout();
265fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            }
266fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        };
2679560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(runnable);
268fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
269fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(runnable.getLayout());
270fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(mTextView.getLayout());
271fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
272fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
273a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2744b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testAccessKeyListener() throws Throwable {
2759560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = findTextView(R.id.textview_text));
276fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
277fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
278fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getKeyListener());
279fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
280fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final KeyListener digitsKeyListener = DigitsKeyListener.getInstance();
281fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2829560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setKeyListener(digitsKeyListener));
283fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
284fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(digitsKeyListener, mTextView.getKeyListener());
285fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
286fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final QwertyKeyListener qwertyKeyListener
287fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                = QwertyKeyListener.getInstance(false, Capitalize.NONE);
2889560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setKeyListener(qwertyKeyListener));
289fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
290fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(qwertyKeyListener, mTextView.getKeyListener());
291fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
292fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
293a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2944b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testAccessMovementMethod() throws Throwable {
295fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final CharSequence LONG_TEXT = "Scrolls the specified widget to the specified "
296fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                + "coordinates, except constrains the X scrolling position to the horizontal "
297fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                + "regions of the text that will be visible after scrolling to "
298fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                + "the specified Y position.";
299fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final int selectionStart = 10;
300fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final int selectionEnd = LONG_TEXT.length();
301fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final MovementMethod movementMethod = ArrowKeyMovementMethod.getInstance();
3029560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
3036beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = findTextView(R.id.textview_text);
3046beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setMovementMethod(movementMethod);
3056beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(LONG_TEXT, BufferType.EDITABLE);
3066beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Editable) mTextView.getText(),
3076beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    selectionStart, selectionEnd);
3086beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
309fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
310fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
311fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
312fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(movementMethod, mTextView.getMovementMethod());
313fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
314fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionEnd, Selection.getSelectionEnd(mTextView.getText()));
315b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_SHIFT_LEFT,
316b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu                KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.KEYCODE_DPAD_UP);
317fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the selection has been removed.
318fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
319fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, Selection.getSelectionEnd(mTextView.getText()));
320fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3219560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
3226beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setMovementMethod(null);
3236beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Editable) mTextView.getText(),
3246beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    selectionStart, selectionEnd);
3256beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
326fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
327fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
328fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
329fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getMovementMethod());
330fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
331fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionEnd, Selection.getSelectionEnd(mTextView.getText()));
332b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_SHIFT_LEFT,
333b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu                KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.KEYCODE_DPAD_UP);
334fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the selection will not be changed.
335fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
336fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionEnd, Selection.getSelectionEnd(mTextView.getText()));
337fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
338fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
339fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
340a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
341fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testLength() {
342fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
343fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
344fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String content = "This is content";
345fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(content);
346fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(content.length(), mTextView.length());
347fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
348fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText("");
349fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.length());
350fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
351fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(null);
352fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.length());
353fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
354fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
355fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
356a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
357fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessGravity() {
358fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.setContentView(R.layout.textview_gravity);
359fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
360fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_default);
3614bb7d555a927c5f7a8747fdd85f7c94e1c0d2f19Fabrice Di Meglio        assertEquals(Gravity.TOP | Gravity.START, mTextView.getGravity());
362fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
363fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_bottom);
3644bb7d555a927c5f7a8747fdd85f7c94e1c0d2f19Fabrice Di Meglio        assertEquals(Gravity.BOTTOM | Gravity.START, mTextView.getGravity());
365fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
366fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_right);
367fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.TOP | Gravity.RIGHT, mTextView.getGravity());
368fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
369fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_center);
370fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.CENTER, mTextView.getGravity());
371fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
372fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_fill);
373fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.FILL, mTextView.getGravity());
374fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
375fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_center_vertical_right);
376fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.CENTER_VERTICAL | Gravity.RIGHT, mTextView.getGravity());
377fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
378fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
379fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, mTextView.getGravity());
380fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.FILL);
381fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.FILL, mTextView.getGravity());
382fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.CENTER);
383fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.CENTER, mTextView.getGravity());
384fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
385fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.NO_GRAVITY);
3864bb7d555a927c5f7a8747fdd85f7c94e1c0d2f19Fabrice Di Meglio        assertEquals(Gravity.TOP | Gravity.START, mTextView.getGravity());
387fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
388fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.RIGHT);
389fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.TOP | Gravity.RIGHT, mTextView.getGravity());
390fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
391fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.FILL_VERTICAL);
3924bb7d555a927c5f7a8747fdd85f7c94e1c0d2f19Fabrice Di Meglio        assertEquals(Gravity.FILL_VERTICAL | Gravity.START, mTextView.getGravity());
393fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
394fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //test negative input value.
395fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(-1);
396fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getGravity());
397fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
398fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
399a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4004b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testAccessAutoLinkMask() throws Throwable {
401fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
402fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final CharSequence text1 =
403fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new SpannableString("URL: http://www.google.com. mailto: account@gmail.com");
4049560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
4056beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setAutoLinkMask(Linkify.ALL);
4066beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text1, BufferType.EDITABLE);
407fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
408fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
409fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.ALL, mTextView.getAutoLinkMask());
410fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
411fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Spannable spanString = (Spannable) mTextView.getText();
412fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        URLSpan[] spans = spanString.getSpans(0, spanString.length(), URLSpan.class);
413fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(spans);
414fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, spans.length);
415fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("http://www.google.com", spans[0].getURL());
416fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("mailto:account@gmail.com", spans[1].getURL());
417fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
418fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final CharSequence text2 =
419fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            new SpannableString("name: Jack. tel: +41 44 800 8999");
4209560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
4216beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setAutoLinkMask(Linkify.PHONE_NUMBERS);
4226beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text2, BufferType.EDITABLE);
423fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
424fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
425fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.PHONE_NUMBERS, mTextView.getAutoLinkMask());
426fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
427fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spanString = (Spannable) mTextView.getText();
428fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spans = spanString.getSpans(0, spanString.length(), URLSpan.class);
429fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(spans);
430fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, spans.length);
431fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("tel:+41448008999", spans[0].getURL());
432fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
433fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        layout(R.layout.textview_autolink);
434fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 1 for web, 2 for email, 4 for phone, 7 for all(web|email|phone)
435fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, getAutoLinkMask(R.id.autolink_default));
436fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.WEB_URLS, getAutoLinkMask(R.id.autolink_web));
437fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.EMAIL_ADDRESSES, getAutoLinkMask(R.id.autolink_email));
438fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.PHONE_NUMBERS, getAutoLinkMask(R.id.autolink_phone));
439fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.ALL, getAutoLinkMask(R.id.autolink_all));
440fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES,
441fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                getAutoLinkMask(R.id.autolink_compound1));
442fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.WEB_URLS | Linkify.PHONE_NUMBERS,
443fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                getAutoLinkMask(R.id.autolink_compound2));
444fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS,
445fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                getAutoLinkMask(R.id.autolink_compound3));
446fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.PHONE_NUMBERS | Linkify.ALL,
447fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                getAutoLinkMask(R.id.autolink_compound4));
448fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
449fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4509560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
451a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
452fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessTextSize() {
453fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        DisplayMetrics metrics = mActivity.getResources().getDisplayMetrics();
454fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
455fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
456fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, 20f);
457fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 20f, metrics),
458fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTextSize(), 0.01f);
459fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
460fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20f);
461fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20f, metrics),
462fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTextSize(), 0.01f);
463fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
464fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20f);
465fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20f, metrics),
466fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTextSize(), 0.01f);
467fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
468fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // setTextSize by default unit "sp"
469fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextSize(20f);
470fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20f, metrics),
471fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTextSize(), 0.01f);
472fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
473fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextSize(200f);
474fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 200f, metrics),
475fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTextSize(), 0.01f);
476fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
477fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4789560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
479a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
480fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessTextColor() {
481fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
482fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
483fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextColor(Color.GREEN);
484fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.GREEN, mTextView.getCurrentTextColor());
485fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.GREEN), mTextView.getTextColors());
486fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
487fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextColor(Color.BLACK);
488fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLACK, mTextView.getCurrentTextColor());
489fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.BLACK), mTextView.getTextColors());
490fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
491fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextColor(Color.RED);
492fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.RED, mTextView.getCurrentTextColor());
493fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.RED), mTextView.getTextColors());
494fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
495fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // using ColorStateList
496fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // normal
497fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        ColorStateList colors = new ColorStateList(new int[][] {
498fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { android.R.attr.state_focused}, new int[0] },
499fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { Color.rgb(0, 255, 0), Color.BLACK });
500fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextColor(colors);
501fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(colors, mTextView.getTextColors());
502fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLACK, mTextView.getCurrentTextColor());
503fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
504fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // exceptional
505fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
506fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.setTextColor(null);
507fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should thrown exception if the colors is null");
508fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e){
509fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
510fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
511fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
512a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
513325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette    public void testGetTextColor() {
514325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette        // TODO: How to get a suitable TypedArray to test this method.
515325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette
516325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette        try {
517325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette            TextView.getTextColor(mActivity, null, -1);
518325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette            fail("There should be a NullPointerException thrown out.");
519325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette        } catch (NullPointerException e) {
520325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette        }
521325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette    }
522325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette
523a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5244b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testAccessHighlightColor() throws Throwable {
525354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
526354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5279560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
528354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            textView.setTextIsSelectable(true);
529354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            textView.setText("abcd", BufferType.EDITABLE);
530354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            textView.setHighlightColor(Color.BLUE);
531354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        });
532354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
533354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
534354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(textView.isTextSelectable());
535354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(Color.BLUE, textView.getHighlightColor());
536354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
537354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Long click on the text selects all text and shows selection handlers. The view has an
538354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // attribute layout_width="wrap_content", so clicked location (the center of the view)
539354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // should be on the text.
5409560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        CtsTouchUtils.emulateLongPressOnViewCenter(mInstrumentation, textView);
541fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
542354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // At this point the entire content of our TextView should be selected and highlighted
543354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // with blue. Now change the highlight to red while the selection is still on.
5449560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> textView.setHighlightColor(Color.RED));
545354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
546354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
547354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(Color.RED, textView.getHighlightColor());
548354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(TextUtils.equals("abcd", textView.getText()));
549354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
550354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Remove the selection
5519560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> Selection.removeSelection((Spannable) textView.getText()));
552354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
553354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
554354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // And switch highlight to green after the selection has been removed
5559560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> textView.setHighlightColor(Color.GREEN));
556354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
557354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
558354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(Color.GREEN, textView.getHighlightColor());
559354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(TextUtils.equals("abcd", textView.getText()));
560fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
561fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5629560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
563a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
564fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetShadowLayer() {
5656a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // test values
5666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final MockTextView mockTextView = new MockTextView(mActivity);
5676a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
5686a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.setShadowLayer(1.0f, 0.3f, 0.4f, Color.CYAN);
5696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(Color.CYAN, mockTextView.getShadowColor());
570a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(0.3f, mockTextView.getShadowDx(), 0.0f);
571a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(0.4f, mockTextView.getShadowDy(), 0.0f);
572a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(1.0f, mockTextView.getShadowRadius(), 0.0f);
573fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
574fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // shadow is placed to the left and below the text
5756a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.setShadowLayer(1.0f, 0.3f, 0.3f, Color.CYAN);
5766a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(mockTextView.isPaddingOffsetRequired());
5776a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getLeftPaddingOffset());
5786a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getTopPaddingOffset());
5796a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(1, mockTextView.getRightPaddingOffset());
5806a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(1, mockTextView.getBottomPaddingOffset());
581fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
582fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // shadow is placed to the right and above the text
5836a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.setShadowLayer(1.0f, -0.8f, -0.8f, Color.CYAN);
5846a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(mockTextView.isPaddingOffsetRequired());
5856a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(-1, mockTextView.getLeftPaddingOffset());
5866a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(-1, mockTextView.getTopPaddingOffset());
5876a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getRightPaddingOffset());
5886a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getBottomPaddingOffset());
589fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
590fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // no shadow
5916a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.setShadowLayer(0.0f, 0.0f, 0.0f, Color.CYAN);
5926a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(mockTextView.isPaddingOffsetRequired());
5936a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getLeftPaddingOffset());
5946a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getTopPaddingOffset());
5956a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getRightPaddingOffset());
5966a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getBottomPaddingOffset());
597fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
598fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
599fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
600a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
601fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetSelectAllOnFocus() {
602fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.setContentView(R.layout.textview_selectallonfocus);
603fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String content = "This is the content";
604fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String blank = "";
605fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.selectAllOnFocus_default);
606fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(blank, BufferType.SPANNABLE);
607fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change the focus
608fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        findTextView(R.id.selectAllOnFocus_dummy).requestFocus();
609fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.isFocused());
610fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestFocus();
611fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.isFocused());
612fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
613fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
614fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
615fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
616fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(content, BufferType.SPANNABLE);
617fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setSelectAllOnFocus(true);
618fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change the focus
619fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        findTextView(R.id.selectAllOnFocus_dummy).requestFocus();
620fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.isFocused());
621fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestFocus();
622fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.isFocused());
623fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
624fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionStart());
625fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(content.length(), mTextView.getSelectionEnd());
626fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
627fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 0);
628fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setSelectAllOnFocus(false);
629fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change the focus
630fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        findTextView(R.id.selectAllOnFocus_dummy).requestFocus();
631fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.isFocused());
632fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestFocus();
633fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.isFocused());
634fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
635fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionStart());
636fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionEnd());
637fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
638fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(blank, BufferType.SPANNABLE);
639fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setSelectAllOnFocus(true);
640fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change the focus
641fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        findTextView(R.id.selectAllOnFocus_dummy).requestFocus();
642fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.isFocused());
643fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestFocus();
644fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.isFocused());
645fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
646fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionStart());
647fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(blank.length(), mTextView.getSelectionEnd());
648fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
649fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 0);
650fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setSelectAllOnFocus(false);
651fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change the focus
652fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        findTextView(R.id.selectAllOnFocus_dummy).requestFocus();
653fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.isFocused());
654fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestFocus();
655fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.isFocused());
656fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
657fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionStart());
658fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionEnd());
659fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
660fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6619560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
662a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
663fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetPaint() {
664fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
665fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextPaint tp = mTextView.getPaint();
666fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(tp);
667fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
668fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaintFlags(), tp.getFlags());
669fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
670fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
671fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
672a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
673fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessLinksClickable() {
674fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.setContentView(R.layout.textview_hint_linksclickable_freezestext);
675fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
676fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_linksClickable_freezesText_default);
677fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLinksClickable());
678fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
679fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.linksClickable_true);
680fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLinksClickable());
681fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
682fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.linksClickable_false);
683fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getLinksClickable());
684fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
685fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinksClickable(false);
686fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getLinksClickable());
687fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
688fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinksClickable(true);
689fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLinksClickable());
690fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
691fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getMovementMethod());
692fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
693fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final CharSequence text = new SpannableString("name: Jack. tel: +41 44 800 8999");
694fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
695fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setAutoLinkMask(Linkify.PHONE_NUMBERS);
696fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.EDITABLE);
697fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
698fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Movement method will be automatically set to LinkMovementMethod
699fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getMovementMethod() instanceof LinkMovementMethod);
700fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
701fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7029560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
703a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
704fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessHintTextColor() {
705fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
706fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // using int values
707fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // normal
708fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHintTextColor(Color.GREEN);
709fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.GREEN, mTextView.getCurrentHintTextColor());
710fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.GREEN), mTextView.getHintTextColors());
711fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
712fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHintTextColor(Color.BLUE);
713fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.BLUE), mTextView.getHintTextColors());
714fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLUE, mTextView.getCurrentHintTextColor());
715fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
716fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHintTextColor(Color.RED);
717fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.RED), mTextView.getHintTextColors());
718fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.RED, mTextView.getCurrentHintTextColor());
719fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
720fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // using ColorStateList
721fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // normal
722fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        ColorStateList colors = new ColorStateList(new int[][] {
723fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { android.R.attr.state_focused}, new int[0] },
724fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { Color.rgb(0, 255, 0), Color.BLACK });
725fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHintTextColor(colors);
726fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(colors, mTextView.getHintTextColors());
727fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLACK, mTextView.getCurrentHintTextColor());
728fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
729fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // exceptional
730fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHintTextColor(null);
731fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getHintTextColors());
732fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCurrentTextColor(), mTextView.getCurrentHintTextColor());
733fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
734fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7359560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
736a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
737fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessLinkTextColor() {
738fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
739fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // normal
740fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinkTextColor(Color.GRAY);
741fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.GRAY), mTextView.getLinkTextColors());
742fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.GRAY, mTextView.getPaint().linkColor);
743fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
744fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinkTextColor(Color.YELLOW);
745fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.YELLOW), mTextView.getLinkTextColors());
746fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.YELLOW, mTextView.getPaint().linkColor);
747fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
748fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinkTextColor(Color.WHITE);
749fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.WHITE), mTextView.getLinkTextColors());
750fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.WHITE, mTextView.getPaint().linkColor);
751fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
752fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        ColorStateList colors = new ColorStateList(new int[][] {
753fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { android.R.attr.state_expanded}, new int[0] },
754fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { Color.rgb(0, 255, 0), Color.BLACK });
755fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinkTextColor(colors);
756fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(colors, mTextView.getLinkTextColors());
757fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLACK, mTextView.getPaint().linkColor);
758fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
759fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinkTextColor(null);
760fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getLinkTextColors());
761fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLACK, mTextView.getPaint().linkColor);
762fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
763fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7649560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
765a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
766fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessPaintFlags() {
767fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
76853959f211c113aa7b2a2ebaf80e10b79ddcccef1Victoria Lease        assertEquals(Paint.DEV_KERN_TEXT_FLAG | Paint.EMBEDDED_BITMAP_TEXT_FLAG
76953959f211c113aa7b2a2ebaf80e10b79ddcccef1Victoria Lease                | Paint.ANTI_ALIAS_FLAG, mTextView.getPaintFlags());
770fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
771fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setPaintFlags(Paint.UNDERLINE_TEXT_FLAG | Paint.FAKE_BOLD_TEXT_FLAG);
772fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Paint.UNDERLINE_TEXT_FLAG | Paint.FAKE_BOLD_TEXT_FLAG,
773fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getPaintFlags());
774fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
775fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setPaintFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.LINEAR_TEXT_FLAG);
776fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Paint.STRIKE_THRU_TEXT_FLAG | Paint.LINEAR_TEXT_FLAG,
777fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getPaintFlags());
778fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
779fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
780a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
7814b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testHeight() throws Throwable {
782fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
7836a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalHeight = mTextView.getHeight();
784fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7856a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // test setMaxHeight
7866a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        int newHeight = originalHeight + 1;
7876a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxHeight(newHeight);
788fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalHeight, mTextView.getHeight());
7896a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
790fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7916a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = originalHeight - 1;
7926a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxHeight(newHeight);
7936a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getHeight());
7946a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
795fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7966a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = -1;
7976a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxHeight(newHeight);
798fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getHeight());
7996a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
800fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8016a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = Integer.MAX_VALUE;
8026a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxHeight(newHeight);
803fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalHeight, mTextView.getHeight());
8046a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
805fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8066a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // test setMinHeight
8076a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = originalHeight + 1;
8086a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinHeight(newHeight);
8096a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getHeight());
8106a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
811fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8126a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = originalHeight - 1;
8136a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinHeight(newHeight);
814fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalHeight, mTextView.getHeight());
8156a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
816fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8176a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = -1;
8186a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinHeight(newHeight);
819fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalHeight, mTextView.getHeight());
8206a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
821fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8226a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // reset min and max height
823fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinHeight(0);
824fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMaxHeight(Integer.MAX_VALUE);
825fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8266a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // test setHeight
8276a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = originalHeight + 1;
8286a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setHeight(newHeight);
8296a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getHeight());
8306a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
8316a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
8326a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
8336a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = originalHeight - 1;
8346a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setHeight(newHeight);
8356a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getHeight());
8366a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
8376a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
8386a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
8396a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = -1;
8406a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setHeight(newHeight);
841fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getHeight());
8426a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
8436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
844fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
845fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setHeight(originalHeight);
846fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalHeight, mTextView.getHeight());
8476a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(originalHeight, mTextView.getMaxHeight());
8486a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(originalHeight, mTextView.getMinHeight());
849fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8506a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // setting max/min lines should cause getMaxHeight/getMinHeight to return -1
8516a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxLines(2);
8526a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("Setting maxLines should return -1 fir maxHeight",
8536a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                -1, mTextView.getMaxHeight());
8546a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
8556a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinLines(1);
8566a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("Setting minLines should return -1 for minHeight",
8576a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                -1, mTextView.getMinHeight());
8586a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
8596a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
860a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
8614b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testWidth() throws Throwable {
8626a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView = findTextView(R.id.textview_text);
8636a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        int originalWidth = mTextView.getWidth();
8646a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
8656a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        int newWidth = mTextView.getWidth() / 8;
8666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setWidth(newWidth);
8676a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getWidth());
8686a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMaxWidth());
8696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMinWidth());
870fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
871fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Min Width
8726a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newWidth = originalWidth + 1;
8736a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinWidth(newWidth);
874fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
8756a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getWidth());
8766a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMinWidth());
877fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8786a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newWidth = originalWidth - 1;
879fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinWidth(originalWidth - 1);
8809c3b459233e30a88d24e7178cc7514731fa56f55Brian Muramatsu        assertEquals(2, mTextView.getLineCount());
8816a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getWidth());
8826a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMinWidth());
883fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
884fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Width
8856a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newWidth = originalWidth + 1;
8866a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setWidth(newWidth);
887fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
8886a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getWidth());
8896a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMaxWidth());
8906a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMinWidth());
891fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8926a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newWidth = originalWidth - 1;
8936a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setWidth(newWidth);
8949c3b459233e30a88d24e7178cc7514731fa56f55Brian Muramatsu        assertEquals(2, mTextView.getLineCount());
8956a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getWidth());
8966a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMaxWidth());
8976a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMinWidth());
8986a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
8996a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // setting ems should cause getMaxWidth/getMinWidth to return -1
9006a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setEms(1);
9016a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("Setting ems should return -1 for maxWidth", -1, mTextView.getMaxWidth());
9026a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("Setting ems should return -1 for maxWidth", -1, mTextView.getMinWidth());
903fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
904fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
905a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
9064b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testSetMinEms() throws Throwable {
907fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
908fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
9099c3b459233e30a88d24e7178cc7514731fa56f55Brian Muramatsu
9106a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalWidth = mTextView.getWidth();
9116a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalEms = originalWidth / mTextView.getLineHeight();
912fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
913fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinEms(originalEms + 1);
914fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals((originalEms + 1) * mTextView.getLineHeight(), mTextView.getWidth());
91598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinWidth());
91698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms + 1, mTextView.getMinEms());
917fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
918fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinEms(originalEms - 1);
919fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalWidth, mTextView.getWidth());
92098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinWidth());
92198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms - 1, mTextView.getMinEms());
9226a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
9236a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinWidth(1);
9246a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(-1, mTextView.getMinEms());
925fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
926fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
927a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
9284b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testSetMaxEms() throws Throwable {
929fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
930fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
9316a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
9326a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalWidth = mTextView.getWidth();
9336a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalEms = originalWidth / mTextView.getLineHeight();
934fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
935fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMaxEms(originalEms + 1);
936fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
937fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalWidth, mTextView.getWidth());
93898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMaxWidth());
93998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms + 1, mTextView.getMaxEms());
940fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
941fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMaxEms(originalEms - 1);
942fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(1 < mTextView.getLineCount());
9436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals((originalEms - 1) * mTextView.getLineHeight(), mTextView.getWidth());
94498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMaxWidth());
94598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms - 1, mTextView.getMaxEms());
9466a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
9476a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxWidth(originalWidth);
9486a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(-1, mTextView.getMaxEms());
949fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
950fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
951a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
9524b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testSetEms() throws Throwable {
953fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
954fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("check height", 1, mTextView.getLineCount());
9556a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalWidth = mTextView.getWidth();
9566a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalEms = originalWidth / mTextView.getLineHeight();
957fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
958fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setEms(originalEms + 1);
959fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
9606a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals((originalEms + 1) * mTextView.getLineHeight(), mTextView.getWidth());
96198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinWidth());
96298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMaxWidth());
96398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms + 1, mTextView.getMinEms());
96498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms + 1, mTextView.getMaxEms());
965fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
966fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setEms(originalEms - 1);
967fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue((1 < mTextView.getLineCount()));
9686a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals((originalEms - 1) * mTextView.getLineHeight(), mTextView.getWidth());
96998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinWidth());
97098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMaxWidth());
97198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms - 1, mTextView.getMinEms());
97298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms - 1, mTextView.getMaxEms());
973fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
974fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
975a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
9764b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testSetLineSpacing() throws Throwable {
9779560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = new TextView(mActivity));
9789560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
979fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int originalLineHeight = mTextView.getLineHeight();
980fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
981fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // normal
982fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        float add = 1.2f;
983fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        float mult = 1.4f;
984fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
98592e24e51c89759b176c38a0ceaa94ae7b23c1930Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
986fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = 0.0f;
987fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = 1.4f;
988fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
98992e24e51c89759b176c38a0ceaa94ae7b23c1930Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
990fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
991fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // abnormal
992fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = -1.2f;
993fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = 1.4f;
994fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
99592e24e51c89759b176c38a0ceaa94ae7b23c1930Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
996fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = -1.2f;
997fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = -1.4f;
998fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
99992e24e51c89759b176c38a0ceaa94ae7b23c1930Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
1000fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = 1.2f;
1001fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = 0.0f;
1002fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
100392e24e51c89759b176c38a0ceaa94ae7b23c1930Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
1004fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1005fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // edge
1006fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = Float.MIN_VALUE;
1007fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = Float.MIN_VALUE;
1008fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
1009ae663de2120beb9de33d57e2c0ebfa6662e1d9f8Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
1010ae663de2120beb9de33d57e2c0ebfa6662e1d9f8Alan Viverette
1011ae663de2120beb9de33d57e2c0ebfa6662e1d9f8Alan Viverette        // edge case where the behavior of Math.round() deviates from
1012ae663de2120beb9de33d57e2c0ebfa6662e1d9f8Alan Viverette        // FastMath.round(), requiring us to use an explicit 0 value
1013fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = Float.MAX_VALUE;
1014fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = Float.MAX_VALUE;
1015fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
1016ae663de2120beb9de33d57e2c0ebfa6662e1d9f8Alan Viverette        assertEquals(0, mTextView.getLineHeight());
1017fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1018fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1019a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
10204b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testSetElegantLineHeight() throws Throwable {
1021ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        mTextView = findTextView(R.id.textview_text);
1022ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertFalse(mTextView.getPaint().isElegantTextHeight());
10239560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
10246beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setWidth(mTextView.getWidth() / 3);
10256beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setPadding(1, 2, 3, 4);
10266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.BOTTOM);
1027ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        });
1028ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        mInstrumentation.waitForIdleSync();
1029ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien
1030ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        int oldHeight = mTextView.getHeight();
10319560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setElegantTextHeight(true));
1032ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        mInstrumentation.waitForIdleSync();
1033ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien
1034ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertTrue(mTextView.getPaint().isElegantTextHeight());
1035ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertTrue(mTextView.getHeight() > oldHeight);
1036ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien
10379560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setElegantTextHeight(false));
1038ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        mInstrumentation.waitForIdleSync();
1039ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertFalse(mTextView.getPaint().isElegantTextHeight());
1040ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertTrue(mTextView.getHeight() == oldHeight);
1041ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien    }
1042ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien
1043a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1044fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessFreezesText() throws Throwable {
1045fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        layout(R.layout.textview_hint_linksclickable_freezestext);
1046fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1047fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_linksClickable_freezesText_default);
1048fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getFreezesText());
1049fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1050fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.freezesText_true);
1051fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getFreezesText());
1052fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1053fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.freezesText_false);
1054fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getFreezesText());
1055fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1056fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setFreezesText(false);
1057fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getFreezesText());
1058fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1059fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final CharSequence text = "Hello, TextView.";
10609560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setText(text));
1061fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
1062fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1063fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final URLSpan urlSpan = new URLSpan("ctstest://TextView/test");
106472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        // TODO: How to simulate the TextView in frozen icicles.
1065a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        ActivityMonitor am = mInstrumentation.addMonitor(MockURLSpanTestActivity.class.getName(),
1066fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                null, false);
1067fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
10689560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
10696beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Uri uri = Uri.parse(urlSpan.getURL());
10706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
10716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mActivity.startActivity(intent);
1072fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
1073fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1074fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Activity newActivity = am.waitForActivityWithTimeout(TIMEOUT);
1075fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(newActivity);
1076fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        newActivity.finish();
1077a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.removeMonitor(am);
1078fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the text of TextView is removed.
1079fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.freezesText_false);
108072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
108172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(text.toString(), mTextView.getText().toString());
1082fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1083fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setFreezesText(true);
1084fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getFreezesText());
1085fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
10869560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setText(text));
1087fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
108872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        // TODO: How to simulate the TextView in frozen icicles.
1089a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        am = mInstrumentation.addMonitor(MockURLSpanTestActivity.class.getName(),
1090fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                null, false);
1091fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
10929560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
10936beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Uri uri = Uri.parse(urlSpan.getURL());
10946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
10956beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mActivity.startActivity(intent);
1096fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
1097fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
109807b9d3406e116f2f6b92932925783eed79503de0Mist Liao        Activity oldActivity = newActivity;
109907b9d3406e116f2f6b92932925783eed79503de0Mist Liao        while (true) {
110007b9d3406e116f2f6b92932925783eed79503de0Mist Liao            newActivity = am.waitForActivityWithTimeout(TIMEOUT);
110107b9d3406e116f2f6b92932925783eed79503de0Mist Liao            assertNotNull(newActivity);
110207b9d3406e116f2f6b92932925783eed79503de0Mist Liao            if (newActivity != oldActivity) {
110307b9d3406e116f2f6b92932925783eed79503de0Mist Liao                break;
110407b9d3406e116f2f6b92932925783eed79503de0Mist Liao            }
110507b9d3406e116f2f6b92932925783eed79503de0Mist Liao        }
1106fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        newActivity.finish();
1107a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.removeMonitor(am);
1108fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the text of TextView is still there.
1109fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.freezesText_false);
1110fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(text.toString(), mTextView.getText().toString());
1111fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1112fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
11139560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
1114a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1115fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetEditableFactory() {
1116fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
1117fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String text = "sample";
1118fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
111998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final Editable.Factory mockEditableFactory = spy(new Editable.Factory());
112098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        doCallRealMethod().when(mockEditableFactory).newEditable(any(CharSequence.class));
112198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mTextView.setEditableFactory(mockEditableFactory);
112298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov
1123fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text);
112498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
1125fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
112698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockEditableFactory);
1127fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.SPANNABLE);
112898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
1129fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
113098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockEditableFactory);
1131fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.NORMAL);
113298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
1133fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
113498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockEditableFactory);
1135fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.EDITABLE);
113698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockEditableFactory, times(1)).newEditable(text);
1137fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1138fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setKeyListener(DigitsKeyListener.getInstance());
113998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockEditableFactory);
1140fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.EDITABLE);
114198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockEditableFactory, times(1)).newEditable(text);
1142fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1143fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1144fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.setEditableFactory(null);
1145fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("The factory can not set to null!");
1146fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e) {
1147fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1148fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1149fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
11509560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
1151a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1152fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetSpannableFactory() {
1153fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
1154fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String text = "sample";
1155fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
115698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final Spannable.Factory mockSpannableFactory = spy(new Spannable.Factory());
115798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        doCallRealMethod().when(mockSpannableFactory).newSpannable(any(CharSequence.class));
115898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mTextView.setSpannableFactory(mockSpannableFactory);
115998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov
1160fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text);
116198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
1162fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
116398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockSpannableFactory);
1164fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.EDITABLE);
116598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
1166fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
116798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockSpannableFactory);
1168fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.NORMAL);
116998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
1170fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
117198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockSpannableFactory);
1172fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.SPANNABLE);
117398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockSpannableFactory, times(1)).newSpannable(text);
1174fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1175fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setMovementMethod(LinkMovementMethod.getInstance());
117698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockSpannableFactory);
1177fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.NORMAL);
117898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockSpannableFactory, times(1)).newSpannable(text);
1179fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1180fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1181fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.setSpannableFactory(null);
1182fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("The factory can not set to null!");
1183fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e) {
1184fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1185fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1186fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
11879560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
1188a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1189fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testTextChangedListener() {
1190fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
1191fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        MockTextWatcher watcher0 = new MockTextWatcher();
1192fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        MockTextWatcher watcher1 = new MockTextWatcher();
1193fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1194fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.addTextChangedListener(watcher0);
1195fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.addTextChangedListener(watcher1);
1196fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1197fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher0.reset();
1198fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher1.reset();
1199fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText("Changed");
1200fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledBeforeTextChanged());
1201fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledOnTextChanged());
1202fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledAfterTextChanged());
1203fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledBeforeTextChanged());
1204fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledOnTextChanged());
1205fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledAfterTextChanged());
1206fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1207fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher0.reset();
1208fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher1.reset();
1209fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // BeforeTextChanged and OnTextChanged are called though the strings are same
1210fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText("Changed");
1211fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledBeforeTextChanged());
1212fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledOnTextChanged());
1213fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledAfterTextChanged());
1214fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledBeforeTextChanged());
1215fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledOnTextChanged());
1216fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledAfterTextChanged());
1217fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1218fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher0.reset();
1219fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher1.reset();
1220fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // BeforeTextChanged and OnTextChanged are called twice (The text is not
1221fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Editable, so in Append() it calls setText() first)
1222fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.append("and appended");
1223fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledBeforeTextChanged());
1224fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledOnTextChanged());
1225fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledAfterTextChanged());
1226fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledBeforeTextChanged());
1227fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledOnTextChanged());
1228fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledAfterTextChanged());
1229fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1230fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher0.reset();
1231fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher1.reset();
1232fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Methods are not called if the string does not change
1233fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.append("");
1234fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher0.hasCalledBeforeTextChanged());
1235fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher0.hasCalledOnTextChanged());
1236fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher0.hasCalledAfterTextChanged());
1237fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledBeforeTextChanged());
1238fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledOnTextChanged());
1239fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledAfterTextChanged());
1240fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1241fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher0.reset();
1242fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher1.reset();
1243fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.removeTextChangedListener(watcher1);
1244fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(null);
1245fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledBeforeTextChanged());
1246fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledOnTextChanged());
1247fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledAfterTextChanged());
1248fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledBeforeTextChanged());
1249fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledOnTextChanged());
1250fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledAfterTextChanged());
1251fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1252fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
12539560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
1254a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1255fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetTextKeepState1() {
1256fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
1257fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1258fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String longString = "very long content";
1259fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String shortString = "short";
1260fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1261fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // selection is at the exact place which is inside the short string
1262fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString, BufferType.SPANNABLE);
1263fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 3);
1264fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString);
1265fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1266fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(3, mTextView.getSelectionStart());
1267fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(3, mTextView.getSelectionEnd());
1268fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1269fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // selection is at the exact place which is outside the short string
1270fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1271fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), shortString.length() + 1);
1272fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString);
1273fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1274fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionStart());
1275fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1276fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1277fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which is inside the short string
1278fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1279fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 1, 4);
1280fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString);
1281fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1282fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getSelectionStart());
1283fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(4, mTextView.getSelectionEnd());
1284fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1285fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which ends outside the short string
1286fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1287fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 2, shortString.length() + 1);
1288fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString);
1289fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1290fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, mTextView.getSelectionStart());
1291fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1292fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1293fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which is outside the short string
1294fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1295fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(),
1296fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                shortString.length() + 1, shortString.length() + 3);
1297fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString);
1298fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1299fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionStart());
1300fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1301fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1302fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1303fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
1304a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1305fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetEditableText() {
1306fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView tv = findTextView(R.id.textview_text);
1307fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1308fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String text = "Hello";
1309fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(text, BufferType.EDITABLE);
1310fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(text, tv.getText().toString());
1311fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Editable);
1312fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(text, tv.getEditableText().toString());
1313fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1314fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(text, BufferType.SPANNABLE);
1315fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(text, tv.getText().toString());
1316fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Spannable);
1317fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(tv.getEditableText());
1318fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1319fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(null, BufferType.EDITABLE);
1320fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", tv.getText().toString());
1321fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Editable);
1322fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", tv.getEditableText().toString());
1323fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1324fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(null, BufferType.SPANNABLE);
1325fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", tv.getText().toString());
1326fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Spannable);
1327fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(tv.getEditableText());
1328fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1329fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1330fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
1331a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1332fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetText2() {
1333fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String string = "This is a test for setting text content by char array";
1334fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        char[] input = string.toCharArray();
1335fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView tv = findTextView(R.id.textview_text);
1336fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1337fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(input, 0, input.length);
1338fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(string, tv.getText().toString());
1339fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1340fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(input, 0, 5);
1341fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(string.substring(0, 5), tv.getText().toString());
1342fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1343fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1344fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            tv.setText(input, -1, input.length);
1345fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception if the start position is negative!");
1346fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (IndexOutOfBoundsException exception) {
1347fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1348fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1349fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1350fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            tv.setText(input, 0, -1);
1351fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception if the length is negative!");
1352fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (IndexOutOfBoundsException exception) {
1353fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1354fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1355fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1356fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            tv.setText(input, 1, input.length);
1357fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception if the end position is out of index!");
1358fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (IndexOutOfBoundsException exception) {
1359fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1360fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1361fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(input, 1, 0);
1362fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", tv.getText().toString());
1363fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1364fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1365fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
1366a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1367fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetText1() {
1368fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
1369fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1370fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String longString = "very long content";
1371fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String shortString = "short";
1372fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1373fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // selection is at the exact place which is inside the short string
1374fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString, BufferType.SPANNABLE);
1375fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 3);
1376fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString, BufferType.EDITABLE);
1377fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1378fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1379fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1380fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(3, mTextView.getSelectionStart());
1381fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(3, mTextView.getSelectionEnd());
1382fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1383fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(shortString, BufferType.EDITABLE);
1384fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1385fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1386fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1387fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no selection.
1388fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
1389fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
1390fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1391fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // selection is at the exact place which is outside the short string
1392fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1393fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), longString.length());
1394fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString, BufferType.EDITABLE);
1395fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1396fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1397fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1398fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionStart());
1399fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1400fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1401fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(shortString, BufferType.EDITABLE);
1402fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1403fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1404fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1405fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no selection.
1406fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
1407fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
1408fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1409fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which is inside the short string
1410fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1411fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 1, shortString.length() - 1);
1412fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString, BufferType.EDITABLE);
1413fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1414fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1415fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1416fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getSelectionStart());
1417fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length() - 1, mTextView.getSelectionEnd());
1418fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1419fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(shortString, BufferType.EDITABLE);
1420fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1421fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1422fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1423fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no selection.
1424fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
1425fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
1426fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1427fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which ends outside the short string
1428fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1429fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 2, longString.length());
1430fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString, BufferType.EDITABLE);
1431fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1432fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1433fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1434fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, mTextView.getSelectionStart());
1435fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1436fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1437fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(shortString, BufferType.EDITABLE);
1438fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1439fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1440fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1441fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no selection.
1442fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
1443fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
1444fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1445fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which is outside the short string
1446fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1447fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(),
1448fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                shortString.length() + 1, shortString.length() + 3);
1449fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString, BufferType.EDITABLE);
1450fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1451fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1452fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1453fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionStart());
1454fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1455fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1456fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(shortString, BufferType.EDITABLE);
1457fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1458fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1459fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1460fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no selection.
1461fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
1462fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
1463fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1464fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1465fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
1466a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1467fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetText3() {
1468fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView tv = findTextView(R.id.textview_text);
1469fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1470fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int resId = R.string.text_view_hint;
1471fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String result = mActivity.getResources().getString(resId);
1472fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1473fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(resId);
1474fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(result, tv.getText().toString());
1475fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1476fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1477fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            tv.setText(-1);
1478fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception with illegal id");
1479fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NotFoundException e) {
1480fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1481fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1482fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1483a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
14849560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testSetTextUpdatesHeightAfterRemovingImageSpan() throws Throwable {
148598d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // Height calculation had problems when TextView had width: match_parent
148698d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final int textViewWidth = ViewGroup.LayoutParams.MATCH_PARENT;
148798d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final Spannable text = new SpannableString("some text");
148898d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final int spanHeight = 100;
148998d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
149098d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // prepare TextView, width: MATCH_PARENT
14919560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = new TextView(mActivity));
14929560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
14939560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setSingleLine(true);
14949560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 2);
14959560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setPadding(0, 0, 0, 0);
14969560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setIncludeFontPadding(false);
14979560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setText(text);
149898d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
149998d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(textViewWidth,
150098d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT);
15019560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        layout.addView(mTextView, layoutParams);
150298d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        layout.setLayoutParams(layoutParams);
15039560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mActivity.setContentView(layout));
1504a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.waitForIdleSync();
150598d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
150698d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // measure height of text with no span
15079560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final int heightWithoutSpan = mTextView.getHeight();
150898d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        assertTrue("Text height should be smaller than span height",
150998d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir                heightWithoutSpan < spanHeight);
151098d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
151198d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // add ImageSpan to text
151298d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        Drawable drawable = mInstrumentation.getContext().getDrawable(R.drawable.scenery);
151398d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        drawable.setBounds(0, 0, spanHeight, spanHeight);
151498d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        ImageSpan span = new ImageSpan(drawable);
151598d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        text.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
15169560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setText(text));
151798d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        mInstrumentation.waitForIdleSync();
151898d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
151998d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // measure height with span
15209560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final int heightWithSpan = mTextView.getHeight();
152198d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        assertTrue("Text height should be greater or equal than span height",
152298d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir                heightWithSpan >= spanHeight);
152398d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
152498d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // remove the span
152598d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        text.removeSpan(span);
15269560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setText(text));
152798d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        mInstrumentation.waitForIdleSync();
152898d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
15299560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final int heightAfterRemoveSpan = mTextView.getHeight();
153098d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        assertEquals("Text height should be same after removing the span",
153198d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir                heightWithoutSpan, heightAfterRemoveSpan);
153298d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir    }
153398d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
1534a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
15354b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testRemoveSelectionWithSelectionHandles() throws Throwable {
15366beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
1537af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi
1538354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertFalse(mTextView.isTextSelectable());
15399560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
1540354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            mTextView.setTextIsSelectable(true);
1541354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            mTextView.setText("abcd", BufferType.EDITABLE);
1542af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        });
1543af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        mInstrumentation.waitForIdleSync();
1544354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(mTextView.isTextSelectable());
1545af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi
1546af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        // Long click on the text selects all text and shows selection handlers. The view has an
1547af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        // attribute layout_width="wrap_content", so clicked location (the center of the view)
1548af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        // should be on the text.
15499560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        CtsTouchUtils.emulateLongPressOnViewCenter(mInstrumentation, mTextView);
1550af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi
15519560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> Selection.removeSelection((Spannable) mTextView.getText()));
1552af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        mInstrumentation.waitForIdleSync();
1553354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
1554354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(TextUtils.equals("abcd", mTextView.getText()));
1555af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi    }
1556af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi
1557a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
15584b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testUndo_insert() throws Throwable {
15596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
15605b51f77b99861d48fec1c327252416f726b3b01aJames Cook
15615b51f77b99861d48fec1c327252416f726b3b01aJames Cook        // Type some text.
1562b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "abc");
15639560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
15646beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Precondition: The cursor is at the end of the text.
15656beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(3, mTextView.getSelectionStart());
15666beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
15676beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo removes the typed string in one step.
15686beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
15696beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
15706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(0, mTextView.getSelectionStart());
15716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
15726beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Redo restores the text and cursor position.
15736beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.redo);
15746beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abc", mTextView.getText().toString());
15756beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(3, mTextView.getSelectionStart());
15766beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
15776beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undoing the redo clears the text again.
15786beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
15796beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
15806beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
15816beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo when the undo stack is empty does nothing.
15826beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
15836beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
15845b51f77b99861d48fec1c327252416f726b3b01aJames Cook        });
15855b51f77b99861d48fec1c327252416f726b3b01aJames Cook        mInstrumentation.waitForIdleSync();
158628715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    }
15875b51f77b99861d48fec1c327252416f726b3b01aJames Cook
1588a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
15894b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testUndo_delete() throws Throwable {
15906beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
15915b51f77b99861d48fec1c327252416f726b3b01aJames Cook
159228715a6877392e4e63cb2b0170c1592fb50079dcJames Cook        // Simulate deleting text and undoing it.
1593b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "xyz");
1594b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_DEL,
1595b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu                KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL);
15969560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
15976beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Precondition: The text was actually deleted.
15986beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
15996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(0, mTextView.getSelectionStart());
16006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
16016beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo restores the typed string and cursor position in one step.
16026beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
16036beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("xyz", mTextView.getText().toString());
16046beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(3, mTextView.getSelectionStart());
16056beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
16066beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Redo removes the text in one step.
16076beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.redo);
16086beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
16096beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(0, mTextView.getSelectionStart());
16106beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
16116beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undoing the redo restores the text again.
16126beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
16136beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("xyz", mTextView.getText().toString());
16146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(3, mTextView.getSelectionStart());
16156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
16166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undoing again undoes the original typing.
16176beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
16186beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
16196beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(0, mTextView.getSelectionStart());
16205b51f77b99861d48fec1c327252416f726b3b01aJames Cook        });
16215b51f77b99861d48fec1c327252416f726b3b01aJames Cook        mInstrumentation.waitForIdleSync();
162228715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    }
16235b51f77b99861d48fec1c327252416f726b3b01aJames Cook
1624c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    // Initialize the text view for simulated IME typing. Must be called on UI thread.
1625c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    private InputConnection initTextViewForSimulatedIme() {
1626c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView = findTextView(R.id.textview_text);
162718731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        return initTextViewForSimulatedIme(mTextView);
162818731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir    }
162918731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir
163018731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir    private InputConnection initTextViewForSimulatedIme(TextView textView) {
163118731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        textView.setKeyListener(QwertyKeyListener.getInstance(false, Capitalize.NONE));
163218731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        textView.setText("", BufferType.EDITABLE);
163318731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        return textView.onCreateInputConnection(new EditorInfo());
1634c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1635c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1636c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    // Simulates IME composing text behavior.
1637c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    private void setComposingTextInBatch(InputConnection input, CharSequence text) {
1638c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.beginBatchEdit();
1639c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.setComposingText(text, 1);  // Leave cursor at end.
1640c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.endBatchEdit();
1641c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1642c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1643c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    @UiThreadTest
1644a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1645c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_imeInsertLatin() {
1646c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        InputConnection input = initTextViewForSimulatedIme();
1647c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1648c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Simulate IME text entry behavior. The Latin IME enters text by replacing partial words,
1649c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // such as "c" -> "ca" -> "cat" -> "cat ".
1650c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, "c");
1651c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, "ca");
1652c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1653c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // The completion and space are added in the same batch.
1654c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.beginBatchEdit();
1655c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.commitText("cat", 1);
1656c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.commitText(" ", 1);
1657c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.endBatchEdit();
1658c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1659c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // The repeated replacements undo in a single step.
1660c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.undo);
1661c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        assertEquals("", mTextView.getText().toString());
1662c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1663c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1664c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    @UiThreadTest
1665a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1666c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_imeInsertJapanese() {
1667c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        InputConnection input = initTextViewForSimulatedIme();
1668c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1669c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // The Japanese IME does repeated replacements of Latin characters to hiragana to kanji.
1670c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        final String HA = "\u306F";  // HIRAGANA LETTER HA
1671c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        final String NA = "\u306A";  // HIRAGANA LETTER NA
1672c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, "h");
1673c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, HA);
1674c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, HA + "n");
1675c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, HA + NA);
1676c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1677c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // The result may be a surrogate pair. The composition ends in the same batch.
1678c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.beginBatchEdit();
1679c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.commitText("\uD83C\uDF37", 1);  // U+1F337 TULIP
1680c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.setComposingText("", 1);
1681c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.endBatchEdit();
1682c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1683c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // The repeated replacements are a single undo step.
1684c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.undo);
1685c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        assertEquals("", mTextView.getText().toString());
1686c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1687c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1688c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    @UiThreadTest
1689a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
169071e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    public void testUndo_imeInsertAndDeleteLatin() {
169171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        InputConnection input = initTextViewForSimulatedIme();
169271e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
169371e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "t");
169471e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "te");
169571e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "tes");
169671e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "test");
169771e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "tes");
169871e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "te");
169971e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "t");
170071e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
170171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.beginBatchEdit();
170271e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.setComposingText("", 1);
170371e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.finishComposingText();
170471e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.endBatchEdit();
170571e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
170671e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        mTextView.onTextContextMenuItem(android.R.id.undo);
170771e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        assertEquals("test", mTextView.getText().toString());
170871e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        mTextView.onTextContextMenuItem(android.R.id.undo);
170971e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        assertEquals("", mTextView.getText().toString());
171071e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    }
171171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
171271e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    @UiThreadTest
1713a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
171471e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    public void testUndo_imeAutoCorrection() {
171518731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        mTextView = findTextView(R.id.textview_text);
171618731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        TextView spiedTextView = spy(mTextView);
171718731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        InputConnection input = initTextViewForSimulatedIme(spiedTextView);
171871e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
171971e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        // Start typing a composition.
172071e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "t");
172171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "te");
172271e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "teh");
172371e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
172418731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        CorrectionInfo correctionInfo = new CorrectionInfo(0, "teh", "the");
172518731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        reset(spiedTextView);
172671e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.beginBatchEdit();
172771e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        // Auto correct "teh" to "the".
172818731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        assertTrue(input.commitCorrection(correctionInfo));
172971e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.commitText("the", 1);
173071e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.endBatchEdit();
173171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
173218731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        verify(spiedTextView, times(1)).onCommitCorrection(refEq(correctionInfo));
173318731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir
173418731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        assertEquals("the", spiedTextView.getText().toString());
173518731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        spiedTextView.onTextContextMenuItem(android.R.id.undo);
173618731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        assertEquals("teh", spiedTextView.getText().toString());
173718731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        spiedTextView.onTextContextMenuItem(android.R.id.undo);
173818731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        assertEquals("", spiedTextView.getText().toString());
173918731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir    }
174018731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir
174118731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir    @UiThreadTest
1742a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
174318731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir    public void testUndo_imeAutoCompletion() {
174418731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        mTextView = findTextView(R.id.textview_text);
174518731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        TextView spiedTextView = spy(mTextView);
174618731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        InputConnection input = initTextViewForSimulatedIme(spiedTextView);
174718731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir
174818731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        // Start typing a composition.
174918731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        setComposingTextInBatch(input, "a");
175018731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        setComposingTextInBatch(input, "an");
175118731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        setComposingTextInBatch(input, "and");
175218731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir
175318731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        CompletionInfo completionInfo = new CompletionInfo(0, 0, "android");
175418731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        reset(spiedTextView);
175518731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        input.beginBatchEdit();
175618731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        // Auto complete "and" to "android".
175718731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        assertTrue(input.commitCompletion(completionInfo));
175818731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        input.commitText("android", 1);
175918731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        input.endBatchEdit();
176018731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir
176118731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        verify(spiedTextView, times(1)).onCommitCompletion(refEq(completionInfo));
176218731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir
176318731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        assertEquals("android", spiedTextView.getText().toString());
176418731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        spiedTextView.onTextContextMenuItem(android.R.id.undo);
176518731b8489073e46e594c798247e5b6338204c3eSiyamed Sinir        assertEquals("", spiedTextView.getText().toString());
176671e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    }
176771e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
176871e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    @UiThreadTest
1769a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1770c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_imeCancel() {
1771c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        InputConnection input = initTextViewForSimulatedIme();
1772c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.setText("flower");
1773c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1774c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Start typing a composition.
1775c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        final String HA = "\u306F";  // HIRAGANA LETTER HA
1776c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, "h");
1777c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, HA);
1778c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, HA + "n");
1779c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1780c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Cancel the composition.
1781c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, "");
1782c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1783c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.undo);
178471e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        assertEquals(HA + "n" + "flower", mTextView.getText().toString());
1785c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.redo);
1786c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        assertEquals("flower", mTextView.getText().toString());
1787c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1788c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1789c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    @UiThreadTest
1790a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1791c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_imeEmptyBatch() {
1792c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        InputConnection input = initTextViewForSimulatedIme();
1793c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.setText("flower");
1794c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1795c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Send an empty batch edit. This happens if the IME is hidden and shown.
1796c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.beginBatchEdit();
1797c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.endBatchEdit();
1798c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1799c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Undo and redo do nothing.
1800c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.undo);
1801c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        assertEquals("flower", mTextView.getText().toString());
1802c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.redo);
1803c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        assertEquals("flower", mTextView.getText().toString());
1804c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1805c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1806a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
18074b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testUndo_setText() throws Throwable {
18086beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
180928715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
1810c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Create two undo operations, an insert and a delete.
1811b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "xyz");
1812b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_DEL,
1813b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu                KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL);
18149560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
18156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Calling setText() clears both undo operations, so undo doesn't happen.
18166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("Hello", BufferType.EDITABLE);
18176beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18186beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("Hello", mTextView.getText().toString());
18196beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
18206beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Clearing text programmatically does not undo either.
18216beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("", BufferType.EDITABLE);
18226beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18236beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
1824277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        });
1825277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mInstrumentation.waitForIdleSync();
1826277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    }
182728715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
1828a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
18294b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testRedo_setText() throws Throwable {
18306beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
1831277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1832277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        // Type some text. This creates an undo entry.
1833b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "abc");
18349560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
18356beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo the typing to create a redo entry.
18366beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
1837277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
18386beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Calling setText() clears the redo stack, so redo doesn't happen.
18396beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("Hello", BufferType.EDITABLE);
18406beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.redo);
18416beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("Hello", mTextView.getText().toString());
1842277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        });
1843277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mInstrumentation.waitForIdleSync();
1844277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    }
1845277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1846a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
18474b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testUndo_directAppend() throws Throwable {
18486beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
184928715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
1850277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        // Type some text.
1851b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "abc");
18529560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
18536beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Programmatically append some text.
18546beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.append("def");
18556beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abcdef", mTextView.getText().toString());
1856277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
18576beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo removes the append as a separate step.
18586beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abc", mTextView.getText().toString());
1860277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
18616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Another undo removes the original typing.
18626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18636beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
1864277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        });
1865277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mInstrumentation.waitForIdleSync();
1866277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    }
1867277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1868a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
18694b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testUndo_directInsert() throws Throwable {
18706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
1871277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1872277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        // Type some text.
1873b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "abc");
18749560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
18756beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Directly modify the underlying Editable to insert some text.
18766beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // NOTE: This is a violation of the API of getText() which specifies that the
18776beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // returned object should not be modified. However, some apps do this anyway and
18786beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // the framework needs to handle it.
18796beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Editable text = (Editable) mTextView.getText();
18806beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            text.insert(0, "def");
18816beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("defabc", mTextView.getText().toString());
18826beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
18836beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo removes the insert as a separate step.
18846beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18856beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abc", mTextView.getText().toString());
18866beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
18876beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Another undo removes the original typing.
18886beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18896beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
1890277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        });
1891277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mInstrumentation.waitForIdleSync();
1892277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    }
1893277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
18946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
1895a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1896c530472a02205f0b7d87f9f06140c56ca0849816James Cook    public void testUndo_noCursor() {
1897c530472a02205f0b7d87f9f06140c56ca0849816James Cook        initTextViewForTyping();
1898c530472a02205f0b7d87f9f06140c56ca0849816James Cook
18996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Append some text to create an undo operation. There is no cursor present.
19006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.append("cat");
1901c530472a02205f0b7d87f9f06140c56ca0849816James Cook
19026beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Place the cursor at the end of the text so the undo will have to change it.
19036beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.setSelection((Spannable) mTextView.getText(), 3);
1904c530472a02205f0b7d87f9f06140c56ca0849816James Cook
19056beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Undo the append. This should not crash, despite not having a valid cursor
19066beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // position in the undo operation.
19076beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.undo);
1908c530472a02205f0b7d87f9f06140c56ca0849816James Cook    }
1909c530472a02205f0b7d87f9f06140c56ca0849816James Cook
1910a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
19114b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testUndo_textWatcher() throws Throwable {
19126beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
1913277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1914277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        // Add a TextWatcher that converts the text to spaces on each change.
1915277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mTextView.addTextChangedListener(new ConvertToSpacesTextWatcher());
1916277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1917277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        // Type some text.
1918b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "abc");
19199560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
19206beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // TextWatcher altered the text.
19216beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("   ", mTextView.getText().toString());
1922277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
19236beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo reverses both changes in one step.
19246beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
19256beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
1926277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        });
1927277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mInstrumentation.waitForIdleSync();
1928c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook    }
1929c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook
19306beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
1931a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
1932c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook    public void testUndo_textWatcherDirectAppend() {
1933c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook        initTextViewForTyping();
1934c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook
1935c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook        // Add a TextWatcher that converts the text to spaces on each change.
1936c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook        mTextView.addTextChangedListener(new ConvertToSpacesTextWatcher());
1937c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook
19386beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Programmatically append some text. The TextWatcher changes it to spaces.
19396beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.append("abc");
19406beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("   ", mTextView.getText().toString());
1941c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook
19426beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Undo reverses both changes in one step.
19436beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.undo);
19446beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("", mTextView.getText().toString());
194528715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    }
194628715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
1947a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
19484b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testUndo_shortcuts() throws Throwable {
19496beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
195028715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
195128715a6877392e4e63cb2b0170c1592fb50079dcJames Cook        // Type some text.
1952b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "abc");
19539560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
19546beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Pressing Control-Z triggers undo.
19556beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            KeyEvent control = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_Z, 0,
19566beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.META_CTRL_LEFT_ON);
19576beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertTrue(mTextView.onKeyShortcut(KeyEvent.KEYCODE_Z, control));
19586beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
19596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
19606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Pressing Control-Shift-Z triggers redo.
19616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            KeyEvent controlShift = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_Z,
19626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    0, KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_SHIFT_LEFT_ON);
19636beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertTrue(mTextView.onKeyShortcut(KeyEvent.KEYCODE_Z, controlShift));
19646beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abc", mTextView.getText().toString());
19655b51f77b99861d48fec1c327252416f726b3b01aJames Cook        });
19665b51f77b99861d48fec1c327252416f726b3b01aJames Cook        mInstrumentation.waitForIdleSync();
19675b51f77b99861d48fec1c327252416f726b3b01aJames Cook    }
19685b51f77b99861d48fec1c327252416f726b3b01aJames Cook
1969a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
19704b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testUndo_saveInstanceState() throws Throwable {
19716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
19725b51f77b99861d48fec1c327252416f726b3b01aJames Cook
19735b51f77b99861d48fec1c327252416f726b3b01aJames Cook        // Type some text to create an undo operation.
1974b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "abc");
19759560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
19766beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Parcel and unparcel the TextView.
19776beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Parcelable state = mTextView.onSaveInstanceState();
19786beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onRestoreInstanceState(state);
19795b51f77b99861d48fec1c327252416f726b3b01aJames Cook        });
19805b51f77b99861d48fec1c327252416f726b3b01aJames Cook        mInstrumentation.waitForIdleSync();
19815b51f77b99861d48fec1c327252416f726b3b01aJames Cook
19825b51f77b99861d48fec1c327252416f726b3b01aJames Cook        // Delete a character to create a new undo operation.
1983b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_DEL);
19849560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
19856beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("ab", mTextView.getText().toString());
19865b51f77b99861d48fec1c327252416f726b3b01aJames Cook
19876beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo the delete.
19886beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
19896beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abc", mTextView.getText().toString());
19905b51f77b99861d48fec1c327252416f726b3b01aJames Cook
19916beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo the typing, which verifies that the original undo operation was parceled
19926beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // correctly.
19936beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
19946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
19955f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook
19966beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Parcel and unparcel the undo stack (which is empty but has been used and may
19976beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // contain other state).
19986beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Parcelable state = mTextView.onSaveInstanceState();
19996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onRestoreInstanceState(state);
20005f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        });
20015f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        mInstrumentation.waitForIdleSync();
20025f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook    }
20035f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook
2004a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
20054b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testUndo_saveInstanceStateEmpty() throws Throwable {
20066beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
20075f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook
20085f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        // Type and delete to create two new undo operations.
2009b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "a");
2010b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_DEL);
20119560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
20126beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Empty the undo stack then parcel and unparcel the TextView. While the undo
20136beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // stack contains no operations it may contain other state.
20146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
20156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
20166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Parcelable state = mTextView.onSaveInstanceState();
20176beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onRestoreInstanceState(state);
20185f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        });
20195f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        mInstrumentation.waitForIdleSync();
20205f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook
20215f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        // Create two more undo operations.
2022b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "b");
2023b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_DEL);
20249560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
20256beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Verify undo still works.
20266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
20276beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("b", mTextView.getText().toString());
20286beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
20296beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
20305b51f77b99861d48fec1c327252416f726b3b01aJames Cook        });
20315b51f77b99861d48fec1c327252416f726b3b01aJames Cook        mInstrumentation.waitForIdleSync();
20325b51f77b99861d48fec1c327252416f726b3b01aJames Cook    }
20335b51f77b99861d48fec1c327252416f726b3b01aJames Cook
20346beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
2035a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2036b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    public void testCopyAndPaste() {
2037b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        initTextViewForTyping();
20386beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20396beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setText("abcd", BufferType.EDITABLE);
20406beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setSelected(true);
20416beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20426beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Copy "bc".
20436beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.setSelection((Spannable) mTextView.getText(), 1, 3);
20446beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.copy);
20456beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20466beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Paste "bc" between "b" and "c".
20476beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.setSelection((Spannable) mTextView.getText(), 2, 2);
20486beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.paste);
20496beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("abbccd", mTextView.getText().toString());
20506beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20516beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Select entire text and paste "bc".
20526beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.selectAll((Spannable) mTextView.getText());
20536beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.paste);
20546beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("bc", mTextView.getText().toString());
2055b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    }
2056b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi
2057a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
20584b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testCopyAndPaste_byKey() throws Throwable {
20596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
206049279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
206149279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Type "abc".
2062b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "abc");
20639560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
20646beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Select "bc"
20656beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 1, 3);
206649279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
206749279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
206849279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Copy "bc"
2069b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_COPY);
207049279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
20719560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
20726beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Set cursor between 'b' and 'c'.
20736beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 2, 2);
207449279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
207549279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
207649279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Paste "bc"
2077b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_PASTE);
207849279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        assertEquals("abbcc", mTextView.getText().toString());
207949279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
20809560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
20816beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.selectAll((Spannable) mTextView.getText());
20826beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            KeyEvent copyWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
20836beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.KEYCODE_COPY, 0, KeyEvent.META_SHIFT_LEFT_ON);
20846beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Shift + copy doesn't perform copy.
20856beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_COPY, copyWithMeta);
20866beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
20876beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.paste);
20886beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bcabbcc", mTextView.getText().toString());
20896beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20906beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.selectAll((Spannable) mTextView.getText());
20916beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            copyWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_COPY, 0,
20926beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.META_CTRL_LEFT_ON);
20936beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Control + copy doesn't perform copy.
20946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_COPY, copyWithMeta);
20956beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
20966beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.paste);
20976beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bcbcabbcc", mTextView.getText().toString());
20986beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.selectAll((Spannable) mTextView.getText());
21006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            copyWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_COPY, 0,
21016beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_CTRL_LEFT_ON);
21026beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Control + Shift + copy doesn't perform copy.
21036beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_COPY, copyWithMeta);
21046beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
21056beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.paste);
21066beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bcbcbcabbcc", mTextView.getText().toString());
210749279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
21088e9fc4a5b2274a1279261f1a36c5396b9884042dKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
210949279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi    }
211049279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
21116beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
2112a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2113b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    public void testCutAndPaste() {
2114b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        initTextViewForTyping();
21156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
21166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setText("abcd", BufferType.EDITABLE);
21176beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setSelected(true);
21186beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
21196beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Cut "bc".
21206beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.setSelection((Spannable) mTextView.getText(), 1, 3);
21216beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.cut);
21226beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("ad", mTextView.getText().toString());
21236beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
21246beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Cut "ad".
21256beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.setSelection((Spannable) mTextView.getText(), 0, 2);
21266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.cut);
21276beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("", mTextView.getText().toString());
21286beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
21296beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Paste "ad".
21306beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.paste);
21316beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("ad", mTextView.getText().toString());
2132b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    }
2133b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi
2134a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
21354b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testCutAndPaste_byKey() throws Throwable {
21366beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
213749279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
213849279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Type "abc".
2139b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "abc");
21409560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
21416beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Select "bc"
21426beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 1, 3);
214349279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
214449279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
214549279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Cut "bc"
2146b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_CUT);
214749279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
21489560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
21496beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("a", mTextView.getText().toString());
21506beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Move cursor to the head
21516beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
215249279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
215349279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
215449279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Paste "bc"
2155b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_PASTE);
215649279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        assertEquals("bca", mTextView.getText().toString());
215749279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
21584b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> {
21596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.selectAll((Spannable) mTextView.getText());
21606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            KeyEvent cutWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
21616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.KEYCODE_CUT, 0, KeyEvent.META_SHIFT_LEFT_ON);
21626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Shift + cut doesn't perform cut.
21636beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_CUT, cutWithMeta);
21646beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bca", mTextView.getText().toString());
21656beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
21666beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            cutWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_CUT, 0,
21676beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.META_CTRL_LEFT_ON);
21686beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Control + cut doesn't perform cut.
21696beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_CUT, cutWithMeta);
21706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bca", mTextView.getText().toString());
21716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
21726beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            cutWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_CUT, 0,
21736beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_CTRL_LEFT_ON);
21746beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Control + Shift + cut doesn't perform cut.
21756beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_CUT, cutWithMeta);
21766beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bca", mTextView.getText().toString());
217749279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
21782de5a65a1540ec0b1ed03ec75c49ff9c242331baSiyamed Sinir        mInstrumentation.waitForIdleSync();
217949279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi    }
218049279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
2181b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    private static boolean hasSpansAtMiddleOfText(final TextView textView, final Class<?> type) {
2182b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        final Spannable spannable = (Spannable)textView.getText();
2183b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        final int at = spannable.length() / 2;
2184b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        return spannable.getSpans(at, at, type).length > 0;
2185b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    }
2186b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi
21876beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
2188a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2189b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    public void testCutAndPaste_withAndWithoutStyle() {
2190b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        initTextViewForTyping();
21916beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
21926beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setText("example", BufferType.EDITABLE);
21936beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setSelected(true);
21946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
21956beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Set URLSpan.
21966beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        final Spannable spannable = (Spannable) mTextView.getText();
21976beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        spannable.setSpan(new URLSpan("http://example.com"), 0, spannable.length(), 0);
21986beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertTrue(hasSpansAtMiddleOfText(mTextView, URLSpan.class));
21996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
22006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Cut entire text.
22016beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.selectAll((Spannable) mTextView.getText());
22026beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.cut);
22036beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("", mTextView.getText().toString());
22046beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
22056beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Paste without style.
22066beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.pasteAsPlainText);
22076beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("example", mTextView.getText().toString());
22086beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Check that the text doesn't have URLSpan.
22096beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertFalse(hasSpansAtMiddleOfText(mTextView, URLSpan.class));
22106beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
22116beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Paste with style.
22126beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.selectAll((Spannable) mTextView.getText());
22136beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.paste);
22146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("example", mTextView.getText().toString());
22156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Check that the text has URLSpan.
22166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertTrue(hasSpansAtMiddleOfText(mTextView, URLSpan.class));
2217b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    }
2218b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi
2219fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
2220a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
22214ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien    public void testSaveInstanceState() {
2222baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // should save text when freezesText=true
22234ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        TextView originalTextView = new TextView(mActivity);
22244ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        final String text = "This is a string";
22254ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        originalTextView.setText(text);
22264ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        originalTextView.setFreezesText(true);  // needed to actually save state
22274ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        Parcelable state = originalTextView.onSaveInstanceState();
22284ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien
22294ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        TextView restoredTextView = new TextView(mActivity);
22304ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        restoredTextView.onRestoreInstanceState(state);
22314ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        assertEquals(text, restoredTextView.getText().toString());
22324ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien    }
22334ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien
22344ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien    @UiThreadTest
2235a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2236baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    public void testOnSaveInstanceState_whenFreezesTextIsFalse() {
22374ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        final String text = "This is a string";
2238baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        { // should not save text when freezesText=false
2239baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            // prepare TextView for before saveInstanceState
2240baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            TextView textView1 = new TextView(mActivity);
2241baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView1.setFreezesText(false);
2242baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView1.setText(text);
22434ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien
2244baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            // prepare TextView for after saveInstanceState
2245baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            TextView textView2 = new TextView(mActivity);
2246baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView2.setFreezesText(false);
2247baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2248baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView2.onRestoreInstanceState(textView1.onSaveInstanceState());
2249baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2250baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            assertEquals("", textView2.getText().toString());
2251baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        }
2252baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2253baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        { // should not save text even when textIsSelectable=true
2254baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            // prepare TextView for before saveInstanceState
2255baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            TextView textView1 = new TextView(mActivity);
2256baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView1.setFreezesText(false);
2257baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView1.setTextIsSelectable(true);
2258baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView1.setText(text);
2259baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2260baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            // prepare TextView for after saveInstanceState
2261baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            TextView textView2 = new TextView(mActivity);
2262baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView2.setFreezesText(false);
2263baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView2.setTextIsSelectable(true);
2264baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2265baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView2.onRestoreInstanceState(textView1.onSaveInstanceState());
2266baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2267baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            assertEquals("", textView2.getText().toString());
2268baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        }
2269baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    }
2270baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2271baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @UiThreadTest
2272baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @SmallTest
2273a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2274baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    public void testOnSaveInstanceState_doesNotSaveSelectionWhenDoesNotExist() {
2275baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for before saveInstanceState
2276baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        final String text = "This is a string";
2277baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView1 = new TextView(mActivity);
2278baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setFreezesText(true);
2279baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setText(text);
2280baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2281baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for after saveInstanceState
2282baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView2 = new TextView(mActivity);
2283baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.setFreezesText(true);
2284baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2285baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.onRestoreInstanceState(textView1.onSaveInstanceState());
2286baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2287baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(-1, textView2.getSelectionStart());
2288baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(-1, textView2.getSelectionEnd());
2289baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    }
2290baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2291baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @UiThreadTest
2292baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @SmallTest
2293a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2294baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    public void testOnSaveInstanceState_doesNotRestoreSelectionWhenTextIsAbsent() {
2295baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for before saveInstanceState
2296baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        final String text = "This is a string";
2297baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView1 = new TextView(mActivity);
2298baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setFreezesText(false);
2299baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setTextIsSelectable(true);
2300baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setText(text);
2301baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        Selection.setSelection((Spannable) textView1.getText(), 2, text.length() - 2);
2302baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2303baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for after saveInstanceState
2304baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView2 = new TextView(mActivity);
2305baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.setFreezesText(false);
2306baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.setTextIsSelectable(true);
2307baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2308baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.onRestoreInstanceState(textView1.onSaveInstanceState());
2309baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2310baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals("", textView2.getText().toString());
2311baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        //when textIsSelectable, selection start and end are initialized to 0
2312baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(0, textView2.getSelectionStart());
2313baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(0, textView2.getSelectionEnd());
2314baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    }
2315baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2316baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @UiThreadTest
2317baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @SmallTest
2318a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2319baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    public void testOnSaveInstanceState_savesSelectionWhenExists() {
2320baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        final String text = "This is a string";
2321baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for before saveInstanceState
2322baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView1 = new TextView(mActivity);
2323baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setFreezesText(true);
2324baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setTextIsSelectable(true);
2325baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setText(text);
2326baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        Selection.setSelection((Spannable) textView1.getText(), 2, text.length() - 2);
2327baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2328baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for after saveInstanceState
2329baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView2 = new TextView(mActivity);
2330baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.setFreezesText(true);
2331baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.setTextIsSelectable(true);
2332baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2333baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.onRestoreInstanceState(textView1.onSaveInstanceState());
2334baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2335baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(textView1.getSelectionStart(), textView2.getSelectionStart());
2336baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(textView1.getSelectionEnd(), textView2.getSelectionEnd());
23374ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien    }
23384ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien
23394ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien    @UiThreadTest
2340a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2341fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetText() {
2342fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView tv = findTextView(R.id.textview_text);
2343fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2344fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int resId = R.string.text_view_hint;
2345fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String result = mActivity.getResources().getString(resId);
2346fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2347fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(resId, BufferType.EDITABLE);
2348fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(result, tv.getText().toString());
2349fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Editable);
2350fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2351fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(resId, BufferType.SPANNABLE);
2352fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(result, tv.getText().toString());
2353fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Spannable);
2354fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2355fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
2356fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            tv.setText(-1, BufferType.EDITABLE);
2357fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception with illegal id");
2358fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NotFoundException e) {
2359fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
2360fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2361fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2362fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
2363a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2364fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessHint() {
2365fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.setContentView(R.layout.textview_hint_linksclickable_freezestext);
2366fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2367fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_linksClickable_freezesText_default);
2368fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getHint());
2369fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2370fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_blank);
2371fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", mTextView.getHint());
2372fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2373fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_string);
2374fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getString(R.string.text_view_simple_hint),
2375fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getHint());
2376fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2377fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_resid);
2378fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getString(R.string.text_view_hint),
2379fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getHint());
2380fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2381fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHint("This is hint");
2382fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("This is hint", mTextView.getHint().toString());
2383fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2384fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHint(R.string.text_view_hello);
2385fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getString(R.string.text_view_hello),
2386fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getHint().toString());
2387fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2388fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Non-exist resid
2389fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
2390fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.setHint(-1);
2391fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception if id is illegal");
2392fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NotFoundException e) {
2393fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
2394fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2395fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2396a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
23974b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testAccessError() throws Throwable {
2398fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2399fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getError());
2400fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
240153b55f734fb3cf52df49a79cf76d410a77fbe8f5Craig Mautner        final String errorText = "Oops! There is an error";
2402fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
24039560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setError(null));
2404fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2405fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getError());
2406fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2407a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable icon = TestUtils.getDrawable(mActivity, R.drawable.failed);
24089560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setError(errorText, icon));
2409fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2410fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(errorText, mTextView.getError().toString());
2411fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // can not check whether the drawable is set correctly
2412fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
24139560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setError(null, null));
2414fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2415fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getError());
2416fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
24179560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
24186beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setKeyListener(DigitsKeyListener.getInstance(""));
24196beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("", BufferType.EDITABLE);
24206beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setError(errorText);
24216beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
2422fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2423fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2424fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2425fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(errorText, mTextView.getError().toString());
2426fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2427b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "a");
2428fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // a key event that will not change the TextView's text
2429fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", mTextView.getText().toString());
2430fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // The icon and error message will not be reset to null
243153b55f734fb3cf52df49a79cf76d410a77fbe8f5Craig Mautner        assertEquals(errorText, mTextView.getError().toString());
2432fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
24339560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
24346beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setKeyListener(DigitsKeyListener.getInstance());
24356beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("", BufferType.EDITABLE);
24366beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setError(errorText);
24376beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
2438300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        });
2439300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        mInstrumentation.waitForIdleSync();
2440300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu
2441b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "1");
2442fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // a key event cause changes to the TextView's text
2443fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("1", mTextView.getText().toString());
2444fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the error message and icon will be cleared.
2445fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getError());
2446fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2447fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2448a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
24494b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testAccessFilters() throws Throwable {
2450fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final InputFilter[] expected = { new InputFilter.AllCaps(),
2451fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new InputFilter.LengthFilter(2) };
2452fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2453fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final QwertyKeyListener qwertyKeyListener
2454fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                = QwertyKeyListener.getInstance(false, Capitalize.NONE);
24559560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
24566beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = findTextView(R.id.textview_text);
24576beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setKeyListener(qwertyKeyListener);
24586beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("", BufferType.EDITABLE);
24596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setFilters(expected);
24606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
2461fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2462fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2463fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2464fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(expected, mTextView.getFilters());
2465fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2466b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "a");
2467fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the text is capitalized by InputFilter.AllCaps
2468fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("A", mTextView.getText().toString());
2469b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "b");
2470fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the text is capitalized by InputFilter.AllCaps
2471fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("AB", mTextView.getText().toString());
2472b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "c");
2473fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 'C' could not be accepted, because there is a length filter.
2474fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("AB", mTextView.getText().toString());
2475fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2476fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
2477fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.setFilters(null);
2478fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw IllegalArgumentException!");
2479fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (IllegalArgumentException e) {
2480fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
2481fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2482fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2483a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
24844b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testGetFocusedRect() throws Throwable {
2485fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Rect rc = new Rect();
2486fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2487fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        // Basic
24889560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = new TextView(mActivity));
24899560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
2490fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.getFocusedRect(rc);
2491fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollX(), rc.left);
2492fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollX() + mTextView.getWidth(), rc.right);
2493fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollY(), rc.top);
2494fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollY() + mTextView.getHeight(), rc.bottom);
2495fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2496fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        // Single line
2497fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2498fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.getFocusedRect(rc);
2499fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollX(), rc.left);
2500fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollX() + mTextView.getWidth(), rc.right);
2501fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollY(), rc.top);
2502fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollY() + mTextView.getHeight(), rc.bottom);
2503fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
25049560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
25056beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setSelected(true);
25066beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            SpannableString text = new SpannableString(mTextView.getText());
25076beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection(text, 3, 13);
25086beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text);
2509fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2510fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2511fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.getFocusedRect(rc);
2512fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(mTextView.getLayout());
2513fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        /* Cursor coordinates from getPrimaryHorizontal() may have a fractional
2514fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien         * component, while the result of getFocusedRect is in int coordinates.
2515fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien         * It's not practical for these to match exactly, so we compare that the
2516fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien         * integer components match - there can be a fractional pixel
2517fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien         * discrepancy, which should be okay for all practical applications. */
2518fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(3), rc.left);
2519fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(13), rc.right);
2520fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineTop(0), rc.top);
2521fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineBottom(0), rc.bottom);
2522fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio
25239560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
25246beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setSelected(true);
25256beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            SpannableString text = new SpannableString(mTextView.getText());
25266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection(text, 13, 3);
25276beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text);
2528fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        });
2529fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mInstrumentation.waitForIdleSync();
2530fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView.getFocusedRect(rc);
2531fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertNotNull(mTextView.getLayout());
2532fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(3) - 2, rc.left);
2533fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(3) + 2, rc.right);
2534fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineTop(0), rc.top);
2535fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineBottom(0), rc.bottom);
2536fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio
2537fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        // Multi lines
2538fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView = findTextView(R.id.textview_text_two_lines);
2539fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView.getFocusedRect(rc);
2540fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getScrollX(), rc.left);
2541fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getScrollX() + mTextView.getWidth(), rc.right);
2542fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getScrollY(), rc.top);
2543fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getScrollY() + mTextView.getHeight(), rc.bottom);
2544fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio
25459560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
25466beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setSelected(true);
25476beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            SpannableString text = new SpannableString(mTextView.getText());
25486beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection(text, 2, 4);
25496beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text);
2550fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        });
2551fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mInstrumentation.waitForIdleSync();
2552fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView.getFocusedRect(rc);
2553fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertNotNull(mTextView.getLayout());
2554fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(2), rc.left);
2555fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(4), rc.right);
2556fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineTop(0), rc.top);
2557fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineBottom(0), rc.bottom);
2558fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio
25599560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
25606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setSelected(true);
25616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            SpannableString text = new SpannableString(mTextView.getText());
25626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection(text, 2, 10); // cross the "\n" and two lines
25636beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text);
2564fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        });
2565fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mInstrumentation.waitForIdleSync();
2566fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView.getFocusedRect(rc);
2567fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        Path path = new Path();
2568fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView.getLayout().getSelectionPath(2, 10, path);
2569fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        RectF rcf = new RectF();
2570fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        path.computeBounds(rcf, true);
2571fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertNotNull(mTextView.getLayout());
2572a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(rcf.left - 1, (float) rc.left, 0.0f);
2573a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(rcf.right + 1, (float) rc.right, 0.0f);
2574fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getLayout().getLineTop(0), rc.top);
2575fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineBottom(1), rc.bottom);
2576fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2577fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Exception
2578fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
2579fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.getFocusedRect(null);
2580fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw NullPointerException!");
2581fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e) {
2582fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
2583fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2584fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2585a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
25869560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testGetLineCount() throws Throwable {
25879560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = findTextView(R.id.textview_text));
25889560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
2589fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // this is an one line text with default setting.
2590fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
2591fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2592fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // make it multi-lines
2593fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMaxWidth(mTextView.getWidth() / 3);
2594fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(1 < mTextView.getLineCount());
2595fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2596fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // make it to an one line
2597fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMaxWidth(Integer.MAX_VALUE);
2598fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
2599fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2600fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // set min lines don't effect the lines count for actual text.
2601fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinLines(12);
2602fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
2603fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
26049560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = new TextView(mActivity));
26059560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
2606fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the internal Layout has not been built.
2607fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getLayout());
2608fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getLineCount());
2609fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2610fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2611a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
26124b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testGetLineBounds() throws Throwable {
2613fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Rect rc = new Rect();
26149560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = new TextView(mActivity));
26159560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
2616fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getLineBounds(0, null));
2617fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2618fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getLineBounds(0, rc));
2619fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.left);
2620fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.right);
2621fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.top);
2622fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.bottom);
2623fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2624fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2625fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getBaseline(), mTextView.getLineBounds(0, null));
2626fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2627fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getBaseline(), mTextView.getLineBounds(0, rc));
2628fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.left);
2629fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getWidth(), rc.right);
2630fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.top);
2631fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getHeight(), rc.bottom);
2632fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
26339560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
26346beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setPadding(1, 2, 3, 4);
26356beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.BOTTOM);
2636fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2637fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2638fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getBaseline(), mTextView.getLineBounds(0, rc));
2639fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getTotalPaddingLeft(), rc.left);
2640fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getWidth() - mTextView.getTotalPaddingRight(), rc.right);
2641fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getTotalPaddingTop(), rc.top);
2642fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getHeight() - mTextView.getTotalPaddingBottom(), rc.bottom);
2643fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2644fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2645a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
26464b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testGetBaseLine() throws Throwable {
26479560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = new TextView(mActivity));
26489560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
2649fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getBaseline());
2650fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2651fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2652fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getLayout().getLineBaseline(0), mTextView.getBaseline());
2653fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
26549560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
26556beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setPadding(1, 2, 3, 4);
26566beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.BOTTOM);
2657fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2658fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2659fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int expected = mTextView.getTotalPaddingTop() + mTextView.getLayout().getLineBaseline(0);
2660fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(expected, mTextView.getBaseline());
2661fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2662fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2663a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
26644b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testPressKey() throws Throwable {
26656beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
2666fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2667b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "a");
2668fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("a", mTextView.getText().toString());
2669b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendString(mInstrumentation, mTextView, "b");
2670fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("ab", mTextView.getText().toString());
2671b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, KeyEvent.KEYCODE_DEL);
2672fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("a", mTextView.getText().toString());
2673fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2674fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2675a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
26764b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testSetIncludeFontPadding() throws Throwable {
2677fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2678ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertTrue(mTextView.getIncludeFontPadding());
26799560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
26806beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setWidth(mTextView.getWidth() / 3);
26816beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setPadding(1, 2, 3, 4);
26826beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.BOTTOM);
2683fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2684fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2685fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2686fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int oldHeight = mTextView.getHeight();
26879560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setIncludeFontPadding(false));
2688fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2689fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2690fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getHeight() < oldHeight);
2691ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertFalse(mTextView.getIncludeFontPadding());
2692fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2693fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
26949560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
2695a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2696fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testScroll() {
2697fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
2698fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2699fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getScrollX());
2700fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getScrollY());
2701fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2702fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //don't set the Scroller, nothing changed.
2703fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.computeScroll();
2704fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getScrollX());
2705fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getScrollY());
2706fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2707fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //set the Scroller
2708fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Scroller s = new Scroller(mActivity);
2709fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(s);
2710fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        s.startScroll(0, 0, 320, 480, 0);
2711fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        s.abortAnimation();
2712fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        s.forceFinished(false);
2713fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setScroller(s);
2714fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2715fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.computeScroll();
2716fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(320, mTextView.getScrollX());
2717fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(480, mTextView.getScrollY());
2718fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2719fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2720a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
27219560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testDebug() throws Throwable {
27229560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
27239560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView = new TextView(mActivity);
27249560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.debug(0);
27259560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setText("Hello!");
27269560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        });
27279560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
2728fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2729fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        layout(mTextView);
2730fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.debug(1);
2731fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2732fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
27339560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
2734a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
27359560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testSelection() throws Throwable {
2736fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
2737fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String text = "This is the content";
2738fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.SPANNABLE);
2739fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.hasSelection());
2740fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2741fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.selectAll((Spannable) mTextView.getText());
2742fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionStart());
2743fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(text.length(), mTextView.getSelectionEnd());
2744fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.hasSelection());
2745fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2746fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int selectionStart = 5;
2747fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int selectionEnd = 7;
2748fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), selectionStart);
2749fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, mTextView.getSelectionStart());
2750fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, mTextView.getSelectionEnd());
2751fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.hasSelection());
2752fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2753fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), selectionStart, selectionEnd);
2754fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, mTextView.getSelectionStart());
2755fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionEnd, mTextView.getSelectionEnd());
2756fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.hasSelection());
2757fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2758fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2759a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
27609560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testOnSelectionChangedIsTriggeredWhenSelectionChanges() throws Throwable {
27616a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final String text = "any text";
27629560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = spy(new MockTextView(mActivity)));
27639560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
27649560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setText(text, BufferType.SPANNABLE);
27656a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
27666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // assert that there is currently no selection
27679560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertFalse(mTextView.hasSelection());
27686a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
27696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // select all
27709560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        Selection.selectAll((Spannable) mTextView.getText());
2771b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        // After selectAll OnSelectionChanged should have been called
27729560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ((MockTextView) verify(mTextView, times(1))).onSelectionChanged(0, text.length());
27736a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
27749560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        reset(mTextView);
27756a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // change selection
27769560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        Selection.setSelection((Spannable) mTextView.getText(), 1, 5);
27779560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ((MockTextView) verify(mTextView, times(1))).onSelectionChanged(1, 5);
27786a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
27799560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        reset(mTextView);
27806a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // clear selection
27819560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        Selection.removeSelection((Spannable) mTextView.getText());
27829560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ((MockTextView) verify(mTextView, times(1))).onSelectionChanged(-1, -1);
27836a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
27846a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
2785fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
2786a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
2787fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessEllipsize() {
2788fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.setContentView(R.layout.textview_ellipsize);
2789fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2790fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.ellipsize_default);
2791fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getEllipsize());
2792fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2793fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.ellipsize_none);
2794fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getEllipsize());
2795fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2796fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.ellipsize_start);
2797fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TruncateAt.START, mTextView.getEllipsize());
2798fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2799fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.ellipsize_middle);
2800fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TruncateAt.MIDDLE, mTextView.getEllipsize());
2801fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2802fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.ellipsize_end);
2803fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TruncateAt.END, mTextView.getEllipsize());
2804fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2805fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setEllipsize(TextUtils.TruncateAt.START);
2806fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TextUtils.TruncateAt.START, mTextView.getEllipsize());
2807fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2808fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setEllipsize(TextUtils.TruncateAt.MIDDLE);
2809fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TextUtils.TruncateAt.MIDDLE, mTextView.getEllipsize());
2810fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2811fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setEllipsize(TextUtils.TruncateAt.END);
2812fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TextUtils.TruncateAt.END, mTextView.getEllipsize());
2813fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2814fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setEllipsize(null);
2815fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getEllipsize());
2816fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2817fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setWidth(10);
2818fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setEllipsize(TextUtils.TruncateAt.START);
2819fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText("ThisIsAVeryLongVeryLongVeryLongVeryLongVeryLongWord");
2820fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.invalidate();
2821fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2822fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TextUtils.TruncateAt.START, mTextView.getEllipsize());
2823fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no method to check if '...yLongVeryLongWord' is painted in the screen.
2824fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2825fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2826a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
282792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir    public void testEllipsizeAndMaxLinesForSingleLine() throws Throwable {
282892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        // no maxline or ellipsize set, single line text
282992cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        final TextView tvNoMaxLine = new TextView(mActivity);
283092cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvNoMaxLine.setLineSpacing(0, 1.5f);
283192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvNoMaxLine.setText("a");
283292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
283392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        // maxline set, no ellipsize, text with two lines
283492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        final TextView tvEllipsizeNone = new TextView(mActivity);
283592cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeNone.setMaxLines(1);
283692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeNone.setLineSpacing(0, 1.5f);
283792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeNone.setText("a\na");
283892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
283992cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        // maxline set, ellipsize end, text with two lines
284092cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        final TextView tvEllipsizeEnd = new TextView(mActivity);
284192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setEllipsize(TruncateAt.END);
284292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setMaxLines(1);
284392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setLineSpacing(0, 1.5f);
284492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setText("a\na");
28452deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
284692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
284792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
284892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT,
284992cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT);
285092cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        layout.addView(tvEllipsizeEnd, layoutParams);
285192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        layout.addView(tvEllipsizeNone, layoutParams);
285292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        layout.addView(tvNoMaxLine, layoutParams);
285392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
285492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        mActivityRule.runOnUiThread(() -> mActivity.setContentView(layout,
285592cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                new ViewGroup.LayoutParams(
285692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                        ViewGroup.LayoutParams.MATCH_PARENT,
285792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                        ViewGroup.LayoutParams.MATCH_PARENT)));
28589560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
28592deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
286092cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        assertEquals(tvEllipsizeEnd.getHeight(), tvEllipsizeNone.getHeight());
286192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
286292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        assertEquals(tvEllipsizeEnd.getHeight(), tvNoMaxLine.getHeight());
286392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
286492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        assertEquals(tvEllipsizeEnd.getLayout().getLineBaseline(0),
286592cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                tvEllipsizeNone.getLayout().getLineBaseline(0));
286692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
286792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        assertEquals(tvEllipsizeEnd.getLayout().getLineBaseline(0),
286892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                tvNoMaxLine.getLayout().getLineBaseline(0));
286992cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir    }
287092cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
287192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir    @Test
287292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir    public void testEllipsizeAndMaxLinesForMultiLine() throws Throwable {
287392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        // no maxline, no ellipsize, text with two lines
287492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        final TextView tvNoMaxLine = new TextView(mActivity);
287592cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvNoMaxLine.setLineSpacing(0, 1.5f);
287692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvNoMaxLine.setText("a\na");
287792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
287892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        // maxline set, no ellipsize, text with three lines
287992cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        final TextView tvEllipsizeNone = new TextView(mActivity);
288092cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeNone.setMaxLines(2);
288192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeNone.setLineSpacing(0, 1.5f);
288292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeNone.setText("a\na\na");
288392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
288492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        // maxline set, ellipsize end, text with three lines
288592cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        final TextView tvEllipsizeEnd = new TextView(mActivity);
288692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setEllipsize(TruncateAt.END);
288792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setMaxLines(2);
288892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setLineSpacing(0, 1.5f);
288992cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setText("a\na\na");
28906031df7acadcd35236309edcbb046847735bda65Siyamed Sinir
28912deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
28922deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
289392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT,
289492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT);
28952deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
289692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        layout.addView(tvNoMaxLine, layoutParams);
289792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        layout.addView(tvEllipsizeEnd, layoutParams);
289892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        layout.addView(tvEllipsizeNone, layoutParams);
289992cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
290092cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        mActivityRule.runOnUiThread(() ->  mActivity.setContentView(layout,
290192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                new ViewGroup.LayoutParams(
290292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                        ViewGroup.LayoutParams.MATCH_PARENT,
290392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                        ViewGroup.LayoutParams.MATCH_PARENT)));
2904a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.waitForIdleSync();
29052deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
290692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        assertEquals(tvEllipsizeEnd.getHeight(), tvEllipsizeNone.getHeight());
290792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
290892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        assertEquals(tvEllipsizeEnd.getHeight(), tvNoMaxLine.getHeight());
290992cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
291092cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        for (int i = 0; i < tvEllipsizeEnd.getLineCount(); i++) {
291192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir            assertEquals("Should have the same baseline for line " + i,
291292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                    tvEllipsizeEnd.getLayout().getLineBaseline(i),
291392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                    tvEllipsizeNone.getLayout().getLineBaseline(i));
291492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
291592cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir            assertEquals("Should have the same baseline for line " + i,
291692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                    tvEllipsizeEnd.getLayout().getLineBaseline(i),
291792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                    tvNoMaxLine.getLayout().getLineBaseline(i));
291892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        }
29192deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir    }
29202deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
2921a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
292292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir    public void testEllipsizeAndMaxLinesForHint() throws Throwable {
292392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        // no maxline, no ellipsize, hint with two lines
292492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        final TextView tvTwoLines = new TextView(mActivity);
292592cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvTwoLines.setLineSpacing(0, 1.5f);
292692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvTwoLines.setHint("a\na");
29272deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
292892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        // no maxline, no ellipsize, hint with three lines
292992cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        final TextView tvThreeLines = new TextView(mActivity);
293092cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvThreeLines.setLineSpacing(0, 1.5f);
293192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvThreeLines.setHint("a\na\na");
293292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
293392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        // maxline set, ellipsize end, hint with three lines
293492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        final TextView tvEllipsizeEnd = new TextView(mActivity);
293592cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setEllipsize(TruncateAt.END);
293692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setMaxLines(2);
293792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setLineSpacing(0, 1.5f);
293892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeEnd.setHint("a\na\na");
29392deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
294092cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        // maxline set, no ellipsize, hint with three lines
294192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        final TextView tvEllipsizeNone = new TextView(mActivity);
294292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeNone.setMaxLines(2);
294392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeNone.setLineSpacing(0, 1.5f);
294492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        tvEllipsizeNone.setHint("a\na\na");
29456031df7acadcd35236309edcbb046847735bda65Siyamed Sinir
29462deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
29472deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
294892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT,
294992cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT);
29502deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
295192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        layout.addView(tvTwoLines, layoutParams);
295292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        layout.addView(tvEllipsizeEnd, layoutParams);
295392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        layout.addView(tvEllipsizeNone, layoutParams);
295492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        layout.addView(tvThreeLines, layoutParams);
29552deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
295692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        mActivityRule.runOnUiThread(() ->  mActivity.setContentView(layout,
295792cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                new ViewGroup.LayoutParams(
295892cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                        ViewGroup.LayoutParams.MATCH_PARENT,
295992cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                        ViewGroup.LayoutParams.MATCH_PARENT)));
2960a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.waitForIdleSync();
29612deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
296292cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        assertEquals("Non-ellipsized hint should not crop text at maxLines",
296392cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                tvThreeLines.getHeight(), tvEllipsizeNone.getHeight());
296492cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
296592cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir        assertEquals("Ellipsized hint should crop text at maxLines",
296692cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir                tvTwoLines.getHeight(), tvEllipsizeEnd.getHeight());
29672deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir    }
29682deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
2969a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
29704b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testTextViewInWeigthenedLayoutChangesWidthAfterSetText() throws Throwable {
29719560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
29729560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView = new TextView(mActivity);
29739560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setEllipsize(TruncateAt.END);
29749560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setSingleLine(true);
29759560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setText("a");
2976672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
29779560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mSecondTextView = new TextView(mActivity);
29789560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mSecondTextView.setSingleLine(true);
29799560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mSecondTextView.setText("any");
29809560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        });
29819560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
2982672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2983672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        final LinearLayout layout = new LinearLayout(mActivity);
2984672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        layout.setOrientation(LinearLayout.HORIZONTAL);
2985672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2986672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        // TextView under test has weight 1, and width 0
29879560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        layout.addView(mTextView, new LinearLayout.LayoutParams(0,
2988672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
2989672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2990672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        // other TextView has default weight
29919560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        layout.addView(mSecondTextView, new LinearLayout.LayoutParams(
2992672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT,
2993672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT));
2994672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2995672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        // main layout params
2996672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        layout.setLayoutParams(new ViewGroup.LayoutParams(
2997672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
2998672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
29999560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mActivity.setContentView(layout));
3000a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.waitForIdleSync();
3001672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
30029560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        int oldWidth = mTextView.getWidth();
3003672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
30049560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setText("aaa"));
3005a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.waitForIdleSync();
3006672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
3007672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        assertTrue("TextView should have larger width after a longer text is set",
30089560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                mTextView.getWidth() > oldWidth);
3009672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir    }
3010672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
301192cd9119d1dbcb9664a830f216920d5bbde961a1Siyamed Sinir
30129560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
3013a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3014354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    public void testAccessCursorVisible() {
3015fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
3016fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3017fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCursorVisible(true);
3018354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(mTextView.isCursorVisible());
3019fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCursorVisible(false);
3020354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertFalse(mTextView.isCursorVisible());
3021fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3022fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3023fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3024a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3025fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testPerformLongClick() {
3026fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3027fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText("This is content");
3028938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
3029938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        View.OnLongClickListener mockOnLongClickListener = mock(View.OnLongClickListener.class);
3030938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        when(mockOnLongClickListener.onLongClick(any(View.class))).thenReturn(Boolean.TRUE);
3031938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
3032938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        View.OnCreateContextMenuListener mockOnCreateContextMenuListener =
3033938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                mock(View.OnCreateContextMenuListener.class);
30344e47d86641f4cbf8269723cca1a2ca1250f9aa02Kirill Grouchnikov        doAnswer((InvocationOnMock invocation) -> {
30354e47d86641f4cbf8269723cca1a2ca1250f9aa02Kirill Grouchnikov            ((ContextMenu) invocation.getArguments() [0]).add("menu item");
30364e47d86641f4cbf8269723cca1a2ca1250f9aa02Kirill Grouchnikov            return null;
3037938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        }).when(mockOnCreateContextMenuListener).onCreateContextMenu(
3038938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                any(ContextMenu.class), any(View.class), any(ContextMenuInfo.class));
3039938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
3040938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        mTextView.setOnLongClickListener(mockOnLongClickListener);
3041938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        mTextView.setOnCreateContextMenuListener(mockOnCreateContextMenuListener);
3042fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.performLongClick());
3043938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verify(mockOnLongClickListener, times(1)).onLongClick(mTextView);
3044938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verifyZeroInteractions(mockOnCreateContextMenuListener);
3045fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3046938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        reset(mockOnLongClickListener);
3047938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        when(mockOnLongClickListener.onLongClick(any(View.class))).thenReturn(Boolean.FALSE);
3048fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.performLongClick());
3049938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verify(mockOnLongClickListener, times(1)).onLongClick(mTextView);
3050938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verify(mockOnCreateContextMenuListener, times(1)).onCreateContextMenu(
3051938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                any(ContextMenu.class), eq(mTextView), any(ContextMenuInfo.class));
3052fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3053938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        reset(mockOnCreateContextMenuListener);
3054fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setOnLongClickListener(null);
3055938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        doNothing().when(mockOnCreateContextMenuListener).onCreateContextMenu(
3056938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                any(ContextMenu.class), any(View.class), any(ContextMenuInfo.class));
3057fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.performLongClick());
3058938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verifyNoMoreInteractions(mockOnLongClickListener);
3059938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verify(mockOnCreateContextMenuListener, times(1)).onCreateContextMenu(
3060938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                any(ContextMenu.class), eq(mTextView), any(ContextMenuInfo.class));
3061fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3062fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3063fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3064a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3065fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testTextAttr() {
3066fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_textAttr);
3067fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // getText
3068fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getString(R.string.text_view_hello), mTextView.getText().toString());
3069fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3070fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // getCurrentTextColor
3071fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.black),
3072fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentTextColor());
3073fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.red),
3074fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentHintTextColor());
3075fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.red),
3076fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getHintTextColors().getDefaultColor());
3077fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.blue),
3078fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getLinkTextColors().getDefaultColor());
3079fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3080fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // getTextScaleX
3081fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1.2f, mTextView.getTextScaleX(), 0.01f);
3082fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3083fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // setTextScaleX
3084fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextScaleX(2.4f);
3085fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2.4f, mTextView.getTextScaleX(), 0.01f);
3086fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3087fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextScaleX(0f);
3088fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0f, mTextView.getTextScaleX(), 0.01f);
3089fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3090fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextScaleX(- 2.4f);
3091fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(- 2.4f, mTextView.getTextScaleX(), 0.01f);
3092fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3093fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // getTextSize
3094fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(20f, mTextView.getTextSize(), 0.01f);
3095fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3096fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // getTypeface
3097119351956fc53fdd61bfbfb0d1ab43857cf7a6d7Peter Eliasson        // getTypeface will be null if android:typeface is set to normal,
3098c02a9f453c5c1255d668bbd8970f4585ab5ff494Alan Viverette        // and android:style is not set or is set to normal, and
3099c02a9f453c5c1255d668bbd8970f4585ab5ff494Alan Viverette        // android:fontFamily is not set
3100fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getTypeface());
3101fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3102fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTypeface(Typeface.DEFAULT);
3103fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(Typeface.DEFAULT, mTextView.getTypeface());
3104fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // null type face
3105fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTypeface(null);
3106fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getTypeface());
3107fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3108fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // default type face, bold style, note: the type face will be changed
3109fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // after call set method
3110fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
3111fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(Typeface.BOLD, mTextView.getTypeface().getStyle());
3112fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3113fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // null type face, BOLD style
3114fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTypeface(null, Typeface.BOLD);
3115fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(Typeface.BOLD, mTextView.getTypeface().getStyle());
3116fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3117fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // old type face, null style
3118fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTypeface(Typeface.DEFAULT, 0);
3119fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Typeface.NORMAL, mTextView.getTypeface().getStyle());
3120fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3121fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3122fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3123a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3124fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAppend() {
3125fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
3126fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3127fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 1: check the original length, should be blank as initialised.
3128fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getText().length());
3129fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3130fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 2: append a string use append(CharSquence) into the original blank
3131fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // buffer, check the content. And upgrading it to BufferType.EDITABLE if it was
3132fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // not already editable.
3133fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getText() instanceof Editable);
3134fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.append("Append.");
3135fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("Append.", mTextView.getText().toString());
3136fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
3137fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3138fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 3: append a string from 0~3.
3139fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.append("Append", 0, 3);
3140fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("Append.App", mTextView.getText().toString());
3141fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
3142fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3143fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 4: append a string from 0~0, nothing will be append as expected.
3144fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.append("Append", 0, 0);
3145fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("Append.App", mTextView.getText().toString());
3146fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
3147fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3148fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 5: append a string from -3~3. check the wrong left edge.
3149fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
3150fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.append("Append", -3, 3);
3151fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw StringIndexOutOfBoundsException");
3152fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (StringIndexOutOfBoundsException e) {
3153fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
3154fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3155fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 6: append a string from 3~10. check the wrong right edge.
3156fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
3157fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.append("Append", 3, 10);
3158fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw StringIndexOutOfBoundsException");
3159fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (StringIndexOutOfBoundsException e) {
3160fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
3161fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3162fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 7: append a null string.
3163fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
3164fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.append(null);
3165fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw NullPointerException");
3166fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e) {
3167fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
3168fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3169fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3170f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
3171a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3172f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_doesNotAddLinksWhenAppendedTextDoesNotContainLinks() {
3173f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3174f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
3175f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text without URL");
3176f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3177f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(" another text without URL");
3178f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3179f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
3180f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
3181f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be zero", 0, urlSpans.length);
3182f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("text without URL another text without URL", text.toString());
3183f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3184f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3185f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
3186a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3187f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_doesNotAddLinksWhenAutoLinkIsNotEnabled() {
3188f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3189f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text without URL");
3190f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3191f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(" text with URL http://android.com");
3192f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3193f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
3194f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
3195f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be zero", 0, urlSpans.length);
3196f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("text without URL text with URL http://android.com", text.toString());
3197f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3198f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3199f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
3200a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3201f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_addsLinksWhenAutoLinkIsEnabled() {
3202f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3203f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
3204f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text without URL");
3205f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3206f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(" text with URL http://android.com");
3207f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3208f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
3209f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
3210f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be one after appending a URL", 1, urlSpans.length);
3211f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan URL should be same as the appended URL",
3212f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[0].getURL(), "http://android.com");
3213f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("text without URL text with URL http://android.com", text.toString());
3214f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3215f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3216f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
3217a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3218f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_addsLinksEvenWhenThereAreUrlsSetBefore() {
3219f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3220f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
3221f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text with URL http://android.com/before");
3222f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3223f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(" text with URL http://android.com");
3224f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3225f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
3226f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
3227f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be two after appending another URL", 2, urlSpans.length);
3228f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("First URLSpan URL should be same",
3229f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[0].getURL(), "http://android.com/before");
3230f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan URL should be same as the appended URL",
3231f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[1].getURL(), "http://android.com");
3232f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("text with URL http://android.com/before text with URL http://android.com",
3233f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                text.toString());
3234f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3235f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3236f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
3237a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3238f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_setsMovementMethodWhenTextContainsUrlAndAutoLinkIsEnabled() {
3239f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3240f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
3241f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text without a URL");
3242f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3243f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(" text with a url: http://android.com");
3244f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3245f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertNotNull("MovementMethod should not be null when text contains url",
3246f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                mTextView.getMovementMethod());
3247f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertTrue("MovementMethod should be instance of LinkMovementMethod when text contains url",
3248f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                mTextView.getMovementMethod() instanceof LinkMovementMethod);
3249f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3250f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3251f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
3252a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3253f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_addsLinksWhenTextIsSpannableAndContainsUrlAndAutoLinkIsEnabled() {
3254f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3255f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
3256f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text without a URL");
3257f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3258f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(new SpannableString(" text with a url: http://android.com"));
3259f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3260f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
3261f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
3262f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be one after appending a URL", 1, urlSpans.length);
3263f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan URL should be same as the appended URL",
3264f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[0].getURL(), "http://android.com");
3265f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3266f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3267f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
3268a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3269f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_addsLinkIfAppendedTextCompletesPartialUrlAtTheEndOfExistingText() {
3270f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3271f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
3272f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text with a partial url android.");
3273f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3274f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append("com");
3275f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3276f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
3277f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
3278f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be one after appending to partial URL",
3279f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                1, urlSpans.length);
3280f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan URL should be same as the appended URL",
3281f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[0].getURL(), "http://android.com");
3282f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3283f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3284f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
3285a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3286f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_addsLinkIfAppendedTextUpdatesUrlAtTheEndOfExistingText() {
3287f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3288f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
3289f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text with a url http://android.com");
3290f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3291f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append("/textview");
3292f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3293f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
3294f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
3295f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should still be one after extending a URL", 1, urlSpans.length);
3296f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan URL should be same as the new URL",
3297f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[0].getURL(), "http://android.com/textview");
3298f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3299f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
33009560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
3301a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
33026a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testGetLetterSpacing_returnsValueThatWasSet() {
33036a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView = new TextView(mActivity);
33046a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setLetterSpacing(2f);
33056a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("getLetterSpacing should return the value that was set",
3306a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov                2f, mTextView.getLetterSpacing(), 0.0f);
33076a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
33086a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
3309a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
33109560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testSetLetterSpacingChangesTextWidth() throws Throwable {
33119560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
33129560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView = new TextView(mActivity);
33139560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setText("aa");
33149560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setLetterSpacing(0f);
33159560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setTextSize(8f);
33169560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        });
33179560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
33186a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33196a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
33206a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
33216a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT,
33226a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT);
33239560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        layout.addView(mTextView, layoutParams);
33246a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.setLayoutParams(layoutParams);
33256a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33269560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mActivity.setContentView(layout));
3327a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.waitForIdleSync();
33286a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33296a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // measure text with zero letter spacing
33309560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final float zeroSpacing = mTextView.getLayout().getLineWidth(0);
33316a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33329560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setLetterSpacing(1f));
3333a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.waitForIdleSync();
33346a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33356a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // measure text with single letter spacing
33369560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final float singleSpacing = mTextView.getLayout().getLineWidth(0);
33376a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33389560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setLetterSpacing(2f));
3339a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.waitForIdleSync();
33406a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33416a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // measure text with double letter spacing
33429560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final float doubleSpacing = mTextView.getLayout().getLineWidth(0);
33436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33446a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("Double spacing should have two times the spacing of single spacing",
33456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                doubleSpacing - zeroSpacing, 2f * (singleSpacing - zeroSpacing), 1f);
33466a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
33476a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33489560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
3349a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
33506a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testGetFontFeatureSettings_returnsValueThatWasSet() {
33516a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView = new TextView(mActivity);
33526a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setFontFeatureSettings("\"smcp\" on");
33536a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("getFontFeatureSettings should return the value that was set",
33546a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                "\"smcp\" on", mTextView.getFontFeatureSettings());
33556a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
33566a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
3357a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
33589560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testGetOffsetForPositionSingleLineLtr() throws Throwable {
33596a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // asserts getOffsetPosition returns correct values for a single line LTR text
33609560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final String text = "aaaaa";
33619560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
33629560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView = new TextView(mActivity);
33639560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setText(text);
33649560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setTextSize(8f);
33659560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setSingleLine(true);
33669560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        });
33679560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
33686a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // add a compound drawable to TextView to make offset calculation more interesting
3370a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable drawable = TestUtils.getDrawable(mActivity, R.drawable.red);
33716a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawable.setBounds(0, 0, 10, 10);
33729560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setCompoundDrawables(drawable, drawable, drawable, drawable);
33736a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33746a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
33756a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
33766a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT,
33776a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT);
33789560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        layout.addView(mTextView, layoutParams);
33796a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.setLayoutParams(layoutParams);
33806a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33814b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> mActivity.setContentView(layout));
3382023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        mInstrumentation.waitForIdleSync();
33836a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33846a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int firstOffset = 0;
33856a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int lastOffset = text.length() - 1;
33866a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int midOffset = text.length() / 2;
33876a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33886a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view
33896a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        float x = 0f;
33909560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        float y = mTextView.getHeight() / 2f;
33919560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(firstOffset, mTextView.getOffsetForPosition(x, y));
33926a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33936a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of text
33949560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        x = mTextView.getLayout().getLineWidth(0) - 1f;
33959560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(lastOffset, mTextView.getOffsetForPosition(x, y));
33966a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33976a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of view
33989560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        x = mTextView.getWidth();
33999560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(lastOffset + 1, mTextView.getOffsetForPosition(x, y));
34006a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34016a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view - out of bounds
34026a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = -1f;
34039560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(firstOffset, mTextView.getOffsetForPosition(x, y));
34046a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34056a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // horizontal center of text
34069560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        x = (float) Math.floor(mTextView.getLayout().getLineWidth(0) / 2f + 0.5f);
34079560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(midOffset, mTextView.getOffsetForPosition(x, y));
34086a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
34096a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
3410a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
34119560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testGetOffsetForPositionMultiLineLtr() throws Throwable {
3412023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        final String line = "aaa\n";
34136a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final String threeLines = line + line + line;
34149560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
34159560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView = new TextView(mActivity);
34169560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setText(threeLines);
34179560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setTextSize(8f);
34189560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setLines(2);
34199560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        });
34209560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
34216a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34226a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // add a compound drawable to TextView to make offset calculation more interesting
3423a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable drawable = TestUtils.getDrawable(mActivity, R.drawable.red);
34246a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawable.setBounds(0, 0, 10, 10);
34259560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setCompoundDrawables(drawable, drawable, drawable, drawable);
34266a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34276a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
34286a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
34296a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT,
34306a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT);
34319560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        layout.addView(mTextView, layoutParams);
34326a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.setLayoutParams(layoutParams);
34336a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34344b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> mActivity.setContentView(layout));
3435023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        mInstrumentation.waitForIdleSync();
34366a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34376a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final Rect lineBounds = new Rect();
34389560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.getLayout().getLineBounds(0, lineBounds);
34396a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34406a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view at first line
34416a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        float x = 0f;
34426a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        float y = lineBounds.height() / 2f;
34439560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(0, mTextView.getOffsetForPosition(x, y));
34446a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of view at first line
34469560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        x = mTextView.getWidth() - 1f;
34479560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(line.length() - 1, mTextView.getOffsetForPosition(x, y));
34486a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34496a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // update lineBounds to be the second line
34509560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.getLayout().getLineBounds(1, lineBounds);
34516a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        y = lineBounds.top + lineBounds.height() / 2;
34526a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34536a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view at second line
34546a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = 0f;
34559560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(line.length(), mTextView.getOffsetForPosition(x, y));
34566a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34576a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of text at second line
34589560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        x = mTextView.getLayout().getLineWidth(1) - 1f;
34599560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
34606a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34616a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of view at second line
34629560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        x = mTextView.getWidth() - 1f;
34639560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
34646a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34656a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // horizontal center of text at second line
34669560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        x = (float) Math.floor(mTextView.getLayout().getLineWidth(1) / 2f + 0.5f);
34676beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // second line mid offset should not include next line, therefore subtract one
34689560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(line.length() + (line.length() - 1) / 2, mTextView.getOffsetForPosition(x, y));
34696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
34706a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
3471a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
34729560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testGetOffsetForPositionMultiLineRtl() throws Throwable {
3473023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        final String line = "\u0635\u0635\u0635\n";
34746a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final String threeLines = line + line + line;
34759560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
34769560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView = new TextView(mActivity);
34779560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setText(threeLines);
34789560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setTextSize(8f);
34799560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setLines(2);
34809560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        });
34819560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
34826a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34836a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // add a compound drawable to TextView to make offset calculation more interesting
3484a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable drawable = TestUtils.getDrawable(mActivity, R.drawable.red);
34856a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawable.setBounds(0, 0, 10, 10);
34869560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setCompoundDrawables(drawable, drawable, drawable, drawable);
34876a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34886a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
34899560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final LayoutParams layoutParams = new LayoutParams(
34909560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                LayoutParams.MATCH_PARENT,
34919560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                LayoutParams.WRAP_CONTENT);
34929560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        layout.addView(mTextView, layoutParams);
34936a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.setLayoutParams(layoutParams);
34946a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34954b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> mActivity.setContentView(layout));
3496023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        mInstrumentation.waitForIdleSync();
34976a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34986a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final Rect lineBounds = new Rect();
34999560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.getLayout().getLineBounds(0, lineBounds);
35006a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35016a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of view at first line
35029560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        float x = mTextView.getWidth() - 1f;
35036a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        float y = lineBounds.height() / 2f;
35049560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(0, mTextView.getOffsetForPosition(x, y));
35056a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35066a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view at first line
35076a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = 0f;
35089560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(line.length() - 1, mTextView.getOffsetForPosition(x, y));
35096a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35106a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // update lineBounds to be the second line
35119560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.getLayout().getLineBounds(1, lineBounds);
35126a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        y = lineBounds.top + lineBounds.height() / 2f;
35136a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35146a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of view at second line
35159560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        x = mTextView.getWidth() - 1f;
35169560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(line.length(), mTextView.getOffsetForPosition(x, y));
35176a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35186a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view at second line
35196a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = 0f;
35209560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
35216a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35226a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of text at second line
35239560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        x = mTextView.getWidth() - mTextView.getLayout().getLineWidth(1) + 1f;
35249560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
35256a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35266a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // horizontal center of text at second line
35279560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        x = mTextView.getWidth() - (float) Math.floor(
35289560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                mTextView.getLayout().getLineWidth(1) / 2f + 0.5f);
35296beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // second line mid offset should not include next line, therefore subtract one
35309560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(line.length() + (line.length() - 1) / 2, mTextView.getOffsetForPosition(x, y));
35316a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
35326a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35339560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
3534a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
35356a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testIsTextSelectable_returnsFalseByDefault() {
3536a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        final TextView textView = new TextView(mActivity);
35376a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setText("any text");
35386a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isTextSelectable());
35396a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
35406a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35419560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
3542a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
35436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testIsTextSelectable_returnsTrueIfSetTextIsSelectableCalledWithTrue() {
3544a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        final TextView textView = new TextView(mActivity);
35456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setText("any text");
35466a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setTextIsSelectable(true);
35476a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isTextSelectable());
35486a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
35496a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35509560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
3551a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
35526a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testSetIsTextSelectable() {
3553a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        final TextView textView = new TextView(mActivity);
35546a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35556a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isTextSelectable());
35566a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isFocusable());
35576a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isFocusableInTouchMode());
35586a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isClickable());
35596a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isLongClickable());
35606a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35616a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setTextIsSelectable(true);
35626a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
35636a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isTextSelectable());
35646a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isFocusable());
35656a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isFocusableInTouchMode());
35666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isClickable());
35676a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isLongClickable());
35686a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(textView.getMovementMethod());
35696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
3570f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3571a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
35724b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testAccessTransformationMethod() throws Throwable {
3573fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // check the password attribute in xml
3574fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_password);
3575fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(mTextView);
3576fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(PasswordTransformationMethod.getInstance(),
3577fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTransformationMethod());
3578fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3579fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // check the singleLine attribute in xml
3580fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_singleLine);
3581fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(mTextView);
3582fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(SingleLineTransformationMethod.getInstance(),
3583fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTransformationMethod());
3584fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3585fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final QwertyKeyListener qwertyKeyListener = QwertyKeyListener.getInstance(false,
3586fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                Capitalize.NONE);
3587fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final TransformationMethod method = PasswordTransformationMethod.getInstance();
3588fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change transformation method by function
35899560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
35906beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setKeyListener(qwertyKeyListener);
35916beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setTransformationMethod(method);
35926beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTransformedText = method.getTransformation(mTextView.getText(), mTextView);
3593fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
35946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
3595fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
3596fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
3597fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(PasswordTransformationMethod.getInstance(),
3598fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTransformationMethod());
3599fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3600b6d441382890b4cd603124ee8dd0e7af3dca5454Andrei Stingaceanu        CtsKeyEventUtil.sendKeys(mInstrumentation, mTextView, "H E 2*L O");
36019560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.append(" "));
3602fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
3603fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3604354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // It will get transformed after a while
3605354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // We're waiting for transformation to "******"
3606354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        PollingCheck.waitFor(TIMEOUT, () -> mTransformedText.toString()
3607354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov                .equals("\u2022\u2022\u2022\u2022\u2022\u2022"));
3608fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3609fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // set null
36109560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setTransformationMethod(null));
3611fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
3612fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getTransformationMethod());
3613fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3614fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3615fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3616a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3617fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testCompound() {
3618fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
3619fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int padding = 3;
3620fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Drawable[] drawables = mTextView.getCompoundDrawables();
3621fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[0]);
3622fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[1]);
3623fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[2]);
3624fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[3]);
3625fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3626fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // test setCompoundDrawablePadding and getCompoundDrawablePadding
3627fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawablePadding(padding);
3628fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(padding, mTextView.getCompoundDrawablePadding());
3629fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3630fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // using resid, 0 represents null
3631fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.start, R.drawable.pass,
3632fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                R.drawable.failed, 0);
3633fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        drawables = mTextView.getCompoundDrawables();
3634fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3635fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableLeft
3636a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        WidgetTestUtils.assertEquals(TestUtils.getBitmap(mActivity, R.drawable.start),
3637fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                ((BitmapDrawable) drawables[0]).getBitmap());
3638fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableTop
3639a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        WidgetTestUtils.assertEquals(TestUtils.getBitmap(mActivity, R.drawable.pass),
3640fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                ((BitmapDrawable) drawables[1]).getBitmap());
3641fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableRight
3642a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        WidgetTestUtils.assertEquals(TestUtils.getBitmap(mActivity, R.drawable.failed),
3643fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                ((BitmapDrawable) drawables[2]).getBitmap());
3644fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableBottom
3645fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[3]);
3646fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3647a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable left = TestUtils.getDrawable(mActivity, R.drawable.blue);
3648a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable right = TestUtils.getDrawable(mActivity, R.drawable.yellow);
3649a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable top = TestUtils.getDrawable(mActivity, R.drawable.red);
3650fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3651fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // using drawables directly
3652fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawablesWithIntrinsicBounds(left, top, right, null);
3653fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        drawables = mTextView.getCompoundDrawables();
3654fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3655fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableLeft
3656fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(left, drawables[0]);
3657fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableTop
3658fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(top, drawables[1]);
3659fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableRight
3660fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(right, drawables[2]);
3661fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableBottom
3662fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[3]);
3663fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3664fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // check compound padding
3665fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingLeft() + padding + left.getIntrinsicWidth(),
3666fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingLeft());
3667fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingTop() + padding + top.getIntrinsicHeight(),
3668fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingTop());
3669fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingRight() + padding + right.getIntrinsicWidth(),
3670fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingRight());
3671fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingBottom(), mTextView.getCompoundPaddingBottom());
3672fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3673fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // set bounds to drawables and set them again.
3674fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        left.setBounds(0, 0, 1, 2);
3675fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        right.setBounds(0, 0, 3, 4);
3676fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        top.setBounds(0, 0, 5, 6);
3677fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // usinf drawables
3678fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawables(left, top, right, null);
3679fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        drawables = mTextView.getCompoundDrawables();
3680fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3681fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableLeft
3682fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(left, drawables[0]);
3683fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableTop
3684fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(top, drawables[1]);
3685fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableRight
3686fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(right, drawables[2]);
3687fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableBottom
3688fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[3]);
3689fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3690fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // check compound padding
3691fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingLeft() + padding + left.getBounds().width(),
3692fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingLeft());
3693fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingTop() + padding + top.getBounds().height(),
3694fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingTop());
3695fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingRight() + padding + right.getBounds().width(),
3696fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingRight());
3697fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingBottom(), mTextView.getCompoundPaddingBottom());
3698fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3699fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
37006a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @UiThreadTest
3701a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
37026a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testGetCompoundDrawablesRelative() {
37036a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // prepare textview
37046a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView = new TextView(mActivity);
37056a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
37066a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // prepare drawables
3707a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable start = TestUtils.getDrawable(mActivity, R.drawable.blue);
3708a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable end = TestUtils.getDrawable(mActivity, R.drawable.yellow);
3709a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable top = TestUtils.getDrawable(mActivity, R.drawable.red);
3710a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable bottom = TestUtils.getDrawable(mActivity, R.drawable.black);
37116a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(start);
37126a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(end);
37136a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(top);
37146a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(bottom);
37156a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
37166a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        Drawable[] drawables = mTextView.getCompoundDrawablesRelative();
37176a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(drawables);
37186a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(4, drawables.length);
37196a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[0]);
37206a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[1]);
37216a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[2]);
37226a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[3]);
37236a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
37246a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
37256a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setCompoundDrawablesRelative(start, top, end, bottom);
37266a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawables = mTextView.getCompoundDrawablesRelative();
37276a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
37286a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(drawables);
37296a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(4, drawables.length);
37306a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(start, drawables[0]);
37316a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(top, drawables[1]);
37326a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(end, drawables[2]);
37336a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(bottom, drawables[3]);
37346a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
37356a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
37366a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setCompoundDrawablesRelative(start, top, end, bottom);
37376a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawables = mTextView.getCompoundDrawablesRelative();
37386a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
37396a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(drawables);
37406a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(4, drawables.length);
37416a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(start, drawables[0]);
37426a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(top, drawables[1]);
37436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(end, drawables[2]);
37446a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(bottom, drawables[3]);
37456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
37466a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setCompoundDrawablesRelative(null, null, null, null);
37476a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawables = mTextView.getCompoundDrawablesRelative();
37486a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
37496a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(drawables);
37506a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(4, drawables.length);
37516a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[0]);
37526a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[1]);
37536a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[2]);
37546a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[3]);
37556a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
37566a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
3757a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
37584b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testSingleLine() throws Throwable {
37599560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = new TextView(mActivity));
37609560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
37619560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
37629560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        setSpannableText(mTextView, "This is a really long sentence"
3763013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu                + " which can not be placed in one line on the screen.");
3764013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu
3765013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        // Narrow layout assures that the text will get wrapped.
37666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final FrameLayout innerLayout = new FrameLayout(mActivity);
3767013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        innerLayout.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
37689560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        innerLayout.addView(mTextView);
3769013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu
3770013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        final FrameLayout layout = new FrameLayout(mActivity);
3771013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        layout.addView(innerLayout);
3772013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu
37739560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
37746beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mActivity.setContentView(layout);
37759560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setSingleLine(true);
3776013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        });
3777013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        mInstrumentation.waitForIdleSync();
3778fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3779fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(SingleLineTransformationMethod.getInstance(),
37809560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                mTextView.getTransformationMethod());
3781da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu
3782da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        int singleLineWidth = 0;
3783da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        int singleLineHeight = 0;
3784da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu
37859560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        if (mTextView.getLayout() != null) {
37869560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            singleLineWidth = mTextView.getLayout().getWidth();
37879560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            singleLineHeight = mTextView.getLayout().getHeight();
3788da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        }
3789fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
37909560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setSingleLine(false));
3791fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
37929560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(null, mTextView.getTransformationMethod());
3793da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu
37949560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        if (mTextView.getLayout() != null) {
37959560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            assertTrue(mTextView.getLayout().getHeight() > singleLineHeight);
37969560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            assertTrue(mTextView.getLayout().getWidth() < singleLineWidth);
3797da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        }
3798fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3799fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // same behaviours as setSingLine(true)
38009560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(mTextView::setSingleLine);
3801fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
3802fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(SingleLineTransformationMethod.getInstance(),
38039560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                mTextView.getTransformationMethod());
3804da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu
38059560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        if (mTextView.getLayout() != null) {
38069560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            assertEquals(singleLineHeight, mTextView.getLayout().getHeight());
38079560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            assertEquals(singleLineWidth, mTextView.getLayout().getWidth());
3808da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        }
3809fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3810fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3811fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3812a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
381398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov    public void testAccessMaxLines() {
3814fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
38156031df7acadcd35236309edcbb046847735bda65Siyamed Sinir        mTextView.setWidth((int) (mTextView.getPaint().measureText(LONG_TEXT) / 4));
3816fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(LONG_TEXT);
3817fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3818fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final int maxLines = 2;
3819fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLineCount() > maxLines);
3820fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3821fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setMaxLines(maxLines);
3822fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestLayout();
3823fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
382498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(2, mTextView.getMaxLines());
382598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMaxHeight());
3826fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getHeight() <= maxLines * mTextView.getLineHeight());
3827fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3828fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3829636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    @UiThreadTest
3830a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3831636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    public void testHyphenationNotHappen_frequencyNone() {
3832636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        final int[] BREAK_STRATEGIES = {
3833636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            Layout.BREAK_STRATEGY_SIMPLE, Layout.BREAK_STRATEGY_HIGH_QUALITY,
3834636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            Layout.BREAK_STRATEGY_BALANCED };
3835636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3836636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        mTextView = findTextView(R.id.textview_text);
3837636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3838636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        for (int breakStrategy : BREAK_STRATEGIES) {
3839636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            for (int charWidth = 10; charWidth < 120; charWidth += 5) {
3840636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                // Change the text view's width to charWidth width.
38416031df7acadcd35236309edcbb046847735bda65Siyamed Sinir                final String substring = LONG_TEXT.substring(0, charWidth);
38426031df7acadcd35236309edcbb046847735bda65Siyamed Sinir                mTextView.setWidth((int) Math.ceil(mTextView.getPaint().measureText(substring)));
3843636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3844636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setText(LONG_TEXT);
3845636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setBreakStrategy(breakStrategy);
3846636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3847636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE);
3848636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3849636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.requestLayout();
3850636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.onPreDraw();  // For freezing the layout.
3851636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                Layout layout = mTextView.getLayout();
3852636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3853636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                final int lineCount = layout.getLineCount();
3854636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                for (int line = 0; line < lineCount; ++line) {
3855636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    final int lineEnd = layout.getLineEnd(line);
3856636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    // In any width, any break strategy, hyphenation should not happen if
3857636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    // HYPHENATION_FREQUENCY_NONE is specified.
3858636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    assertTrue(lineEnd == LONG_TEXT.length() ||
3859636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                            Character.isWhitespace(LONG_TEXT.charAt(lineEnd - 1)));
3860636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                }
3861636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            }
3862636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        }
3863636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    }
3864636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3865636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    @UiThreadTest
3866a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3867636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    public void testHyphenationNotHappen_breakStrategySimple() {
3868636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        final int[] HYPHENATION_FREQUENCIES = {
3869636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            Layout.HYPHENATION_FREQUENCY_NORMAL, Layout.HYPHENATION_FREQUENCY_FULL,
3870636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            Layout.HYPHENATION_FREQUENCY_NONE };
3871636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3872636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        mTextView = findTextView(R.id.textview_text);
3873636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3874636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        for (int hyphenationFrequency: HYPHENATION_FREQUENCIES) {
3875636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            for (int charWidth = 10; charWidth < 120; charWidth += 5) {
3876636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                // Change the text view's width to charWidth width.
38776031df7acadcd35236309edcbb046847735bda65Siyamed Sinir                final String substring = LONG_TEXT.substring(0, charWidth);
38786031df7acadcd35236309edcbb046847735bda65Siyamed Sinir                mTextView.setWidth((int) Math.ceil(mTextView.getPaint().measureText(substring)));
3879636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3880636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setText(LONG_TEXT);
3881636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
3882636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3883636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setHyphenationFrequency(hyphenationFrequency);
3884636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3885636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.requestLayout();
3886636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.onPreDraw();  // For freezing the layout.
3887636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                Layout layout = mTextView.getLayout();
3888636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3889636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                final int lineCount = layout.getLineCount();
3890636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                for (int line = 0; line < lineCount; ++line) {
3891636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    final int lineEnd = layout.getLineEnd(line);
3892636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    // In any width, any hyphenation frequency, hyphenation should not happen if
3893636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    // BREAK_STRATEGY_SIMPLE is specified.
3894636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    assertTrue(lineEnd == LONG_TEXT.length() ||
3895636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                            Character.isWhitespace(LONG_TEXT.charAt(lineEnd - 1)));
3896636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                }
3897636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            }
3898636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        }
3899636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    }
3900636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3901fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3902a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3903fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetMaxLinesException() {
390472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = new TextView(mActivity);
390572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mActivity.setContentView(mTextView);
3906fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setWidth(mTextView.getWidth() >> 3);
390772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setMaxLines(-1);
3908fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3909fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3910a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
39114b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testAccessMinLines() throws Throwable {
3912fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3913fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setWidth(mTextView.getWidth() >> 3);
3914fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int originalLines = mTextView.getLineCount();
3915fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3916fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinLines(originalLines - 1);
3917fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue((originalLines - 1) * mTextView.getLineHeight() <= mTextView.getHeight());
391898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalLines - 1, mTextView.getMinLines());
391998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinHeight());
3920fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3921fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinLines(originalLines + 1);
3922fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue((originalLines + 1) * mTextView.getLineHeight() <= mTextView.getHeight());
392398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalLines + 1, mTextView.getMinLines());
392498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinHeight());
3925fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3926fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3927a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
39284b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testSetLines() throws Throwable {
3929fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3930fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // make it multiple lines
3931fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setWidth(mTextView.getWidth() >> 3);
3932fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int originalLines = mTextView.getLineCount();
3933fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3934fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLines(originalLines - 1);
3935fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue((originalLines - 1) * mTextView.getLineHeight() <= mTextView.getHeight());
3936fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3937fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLines(originalLines + 1);
3938fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue((originalLines + 1) * mTextView.getLineHeight() <= mTextView.getHeight());
3939fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3940fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3941fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3942a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3943fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetLinesException() {
394472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = new TextView(mActivity);
394572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mActivity.setContentView(mTextView);
394672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setWidth(mTextView.getWidth() >> 3);
394772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setLines(-1);
3948fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3949fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3950fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3951a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3952fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetExtendedPaddingTop() {
3953fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3954fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
3955fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getExtendedPaddingTop());
3956fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3957fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
3958a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable top = TestUtils.getDrawable(mActivity, R.drawable.red);
3959fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        top.setBounds(0, 0, 100, 10);
3960fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawables(null, top, null, null);
3961fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingTop(), mTextView.getExtendedPaddingTop());
3962fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3963fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change line count
3964fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLines(mTextView.getLineCount() - 1);
3965fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.BOTTOM);
3966fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3967fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getExtendedPaddingTop() > 0);
3968fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3969fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3970fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3971a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
3972fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetExtendedPaddingBottom() {
3973fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3974fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
3975fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getExtendedPaddingBottom());
3976fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3977fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
3978a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable bottom = TestUtils.getDrawable(mActivity, R.drawable.red);
3979fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        bottom.setBounds(0, 0, 100, 10);
3980fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawables(null, null, null, bottom);
3981fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingBottom(), mTextView.getExtendedPaddingBottom());
3982fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3983fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change line count
3984fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLines(mTextView.getLineCount() - 1);
3985fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.CENTER_VERTICAL);
3986fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3987fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getExtendedPaddingBottom() > 0);
3988fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3989fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3990a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
39914b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testGetTotalPaddingTop() throws Throwable {
3992fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3993fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
3994fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getTotalPaddingTop());
3995fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3996fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
3997a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable top = TestUtils.getDrawable(mActivity, R.drawable.red);
3998fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        top.setBounds(0, 0, 100, 10);
39999560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
40006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setCompoundDrawables(null, top, null, null);
40016beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setLines(mTextView.getLineCount() - 1);
40026beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.BOTTOM);
4003fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
4004fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
4005fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getExtendedPaddingTop(), mTextView.getTotalPaddingTop());
4006fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4007fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change line count
4008fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLines(mTextView.getLineCount() + 1);
4009fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int expected = mTextView.getHeight()
4010fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                - mTextView.getExtendedPaddingBottom()
4011fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                - mTextView.getLayout().getLineTop(mTextView.getLineCount());
4012fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(expected, mTextView.getTotalPaddingTop());
4013fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4014fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4015a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
40164b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testGetTotalPaddingBottom() throws Throwable {
4017fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
4018fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
4019fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getTotalPaddingBottom());
4020fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4021fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
4022a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable bottom = TestUtils.getDrawable(mActivity, R.drawable.red);
4023fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        bottom.setBounds(0, 0, 100, 10);
40249560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
40256beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setCompoundDrawables(null, null, null, bottom);
40266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setLines(mTextView.getLineCount() - 1);
40276beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.CENTER_VERTICAL);
4028fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
4029fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
4030fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getExtendedPaddingBottom(), mTextView.getTotalPaddingBottom());
4031fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4032fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change line count
4033fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLines(mTextView.getLineCount() + 1);
4034fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int expected = ((mTextView.getHeight()
4035fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                - mTextView.getExtendedPaddingBottom()
4036fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                - mTextView.getExtendedPaddingTop()
4037fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                - mTextView.getLayout().getLineBottom(mTextView.getLineCount())) >> 1)
4038fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                + mTextView.getExtendedPaddingBottom();
4039fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(expected, mTextView.getTotalPaddingBottom());
4040fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4041fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4042fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
4043a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4044fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetTotalPaddingLeft() {
4045fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
4046fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
4047fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getTotalPaddingLeft());
4048fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4049fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
4050a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable left = TestUtils.getDrawable(mActivity, R.drawable.red);
4051fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        left.setBounds(0, 0, 10, 100);
4052fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawables(left, null, null, null);
4053fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.RIGHT);
4054fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingLeft(), mTextView.getTotalPaddingLeft());
4055fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4056fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change width
4057fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setWidth(Integer.MAX_VALUE);
4058fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingLeft(), mTextView.getTotalPaddingLeft());
4059fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4060fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4061fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
4062a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4063fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetTotalPaddingRight() {
4064fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
4065fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
4066fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getTotalPaddingRight());
4067fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4068fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
4069a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable right = TestUtils.getDrawable(mActivity, R.drawable.red);
4070fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        right.setBounds(0, 0, 10, 100);
4071fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawables(null, null, right, null);
4072fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.CENTER_HORIZONTAL);
4073fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingRight(), mTextView.getTotalPaddingRight());
4074fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4075fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change width
4076fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setWidth(Integer.MAX_VALUE);
4077fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingRight(), mTextView.getTotalPaddingRight());
4078fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4079fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
40809560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4081a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4082fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetUrls() {
4083fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
4084fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4085fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        URLSpan[] spans = mTextView.getUrls();
4086fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, spans.length);
4087fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4088fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String url = "http://www.google.com";
4089fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String email = "name@gmail.com";
4090fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String string = url + " mailto:" + email;
4091fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        SpannableString spannable = new SpannableString(string);
4092fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spannable.setSpan(new URLSpan(url), 0, url.length(), 0);
4093fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(spannable, BufferType.SPANNABLE);
4094fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spans = mTextView.getUrls();
4095fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, spans.length);
4096fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(url, spans[0].getURL());
4097fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4098fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spannable.setSpan(new URLSpan(email), 0, email.length(), 0);
4099fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(spannable, BufferType.SPANNABLE);
4100fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4101fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spans = mTextView.getUrls();
4102fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, spans.length);
4103fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(url, spans[0].getURL());
4104fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(email, spans[1].getURL());
4105fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4106fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // test the situation that param what is not a URLSpan
4107fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spannable.setSpan(new Object(), 0, 9, 0);
4108fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(spannable, BufferType.SPANNABLE);
4109fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spans = mTextView.getUrls();
4110fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, spans.length);
4111fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4112fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
41139560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4114a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4115fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetPadding() {
4116fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
4117fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4118fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setPadding(0, 1, 2, 4);
4119fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getPaddingLeft());
4120fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getPaddingTop());
4121fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, mTextView.getPaddingRight());
4122fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(4, mTextView.getPaddingBottom());
4123fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4124fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setPadding(10, 20, 30, 40);
4125fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(10, mTextView.getPaddingLeft());
4126fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(20, mTextView.getPaddingTop());
4127fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(30, mTextView.getPaddingRight());
4128fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(40, mTextView.getPaddingBottom());
4129fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4130fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
41319560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4132a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4133fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai    public void testDeprecatedSetTextAppearance() {
4134fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
4135fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4136fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextAppearance(mActivity, R.style.TextAppearance_All);
4137fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.black),
4138fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentTextColor());
4139fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(20f, mTextView.getTextSize(), 0.01f);
4140fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Typeface.BOLD, mTextView.getTypeface().getStyle());
4141fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.red),
4142fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentHintTextColor());
4143fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.blue),
4144fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getLinkTextColors().getDefaultColor());
4145fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4146fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextAppearance(mActivity, R.style.TextAppearance_Colors);
4147fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.black),
4148fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentTextColor());
4149fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.blue),
4150fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentHintTextColor());
4151fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.yellow),
4152fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getLinkTextColors().getDefaultColor());
4153fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4154fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextAppearance(mActivity, R.style.TextAppearance_NotColors);
4155fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(17f, mTextView.getTextSize(), 0.01f);
4156fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Typeface.NORMAL, mTextView.getTypeface().getStyle());
4157fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4158fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextAppearance(mActivity, R.style.TextAppearance_Style);
4159fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(null, mTextView.getTypeface());
4160fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4161fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
41629560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4163a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4164fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai    public void testSetTextAppearance() {
4165fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView = new TextView(mActivity);
4166fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
4167fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setTextAppearance(R.style.TextAppearance_All);
4168fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.black),
4169fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getCurrentTextColor());
4170fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(20f, mTextView.getTextSize(), 0.01f);
4171fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(Typeface.BOLD, mTextView.getTypeface().getStyle());
4172fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.red),
4173fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getCurrentHintTextColor());
4174fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.blue),
4175fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getLinkTextColors().getDefaultColor());
41766a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(mActivity.getResources().getColor(R.drawable.yellow),
41776a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                mTextView.getHighlightColor());
4178fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
4179fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setTextAppearance(R.style.TextAppearance_Colors);
4180fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.black),
4181fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getCurrentTextColor());
4182fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.blue),
4183fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getCurrentHintTextColor());
4184fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.yellow),
4185fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getLinkTextColors().getDefaultColor());
41866a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(mActivity.getResources().getColor(R.drawable.red),
41876a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                mTextView.getHighlightColor());
4188fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
4189fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setTextAppearance(R.style.TextAppearance_NotColors);
4190fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(17f, mTextView.getTextSize(), 0.01f);
4191fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(Typeface.NORMAL, mTextView.getTypeface().getStyle());
4192fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
4193fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setTextAppearance(R.style.TextAppearance_Style);
4194fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(null, mTextView.getTypeface());
4195fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai    }
4196fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
41979560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4198a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4199fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai    public void testAccessCompoundDrawableTint() {
4200fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView = new TextView(mActivity);
4201fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
4202fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        ColorStateList colors = ColorStateList.valueOf(Color.RED);
4203fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setCompoundDrawableTintList(colors);
4204fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setCompoundDrawableTintMode(PorterDuff.Mode.XOR);
4205fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertSame(colors, mTextView.getCompoundDrawableTintList());
4206fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(PorterDuff.Mode.XOR, mTextView.getCompoundDrawableTintMode());
4207f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette
4208f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        // Ensure the tint is preserved across drawable changes.
4209f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        mTextView.setCompoundDrawablesRelative(null, null, null, null);
4210f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertSame(colors, mTextView.getCompoundDrawableTintList());
4211f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertEquals(PorterDuff.Mode.XOR, mTextView.getCompoundDrawableTintMode());
4212f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette
4213f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        mTextView.setCompoundDrawables(null, null, null, null);
4214f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertSame(colors, mTextView.getCompoundDrawableTintList());
4215f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertEquals(PorterDuff.Mode.XOR, mTextView.getCompoundDrawableTintMode());
4216f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette
4217f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        ColorDrawable dr1 = new ColorDrawable(Color.RED);
4218f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        ColorDrawable dr2 = new ColorDrawable(Color.GREEN);
4219f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        ColorDrawable dr3 = new ColorDrawable(Color.BLUE);
4220f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        ColorDrawable dr4 = new ColorDrawable(Color.YELLOW);
4221f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        mTextView.setCompoundDrawables(dr1, dr2, dr3, dr4);
4222f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertSame(colors, mTextView.getCompoundDrawableTintList());
4223f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertEquals(PorterDuff.Mode.XOR, mTextView.getCompoundDrawableTintMode());
4224fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai    }
4225fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
4226a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
42274b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testSetHorizontallyScrolling() throws Throwable {
4228fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // make the text view has more than one line
4229fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
4230fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setWidth(mTextView.getWidth() >> 1);
4231fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLineCount() > 1);
4232fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4233fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setHorizontallyScrolling(true);
4234fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
4235fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4236fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setHorizontallyScrolling(false);
4237fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLineCount() > 1);
4238fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4239fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4240a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
42419560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testComputeHorizontalScrollRange() throws Throwable {
42429560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = new MockTextView(mActivity));
42439560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
4244fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // test when layout is null
42459560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getLayout());
42469560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(mTextView.getWidth(),
42479560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                ((MockTextView) mTextView).computeHorizontalScrollRange());
4248fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
42499560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> ((MockTextView) mTextView).setFrame(0, 0, 40, 50));
42509560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
42519560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(mTextView.getWidth(),
42529560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                ((MockTextView) mTextView).computeHorizontalScrollRange());
4253fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4254fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // set the layout
42559560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        layout(mTextView);
42569560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(mTextView.getLayout().getWidth(),
42579560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                ((MockTextView) mTextView).computeHorizontalScrollRange());
4258fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4259fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4260a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
42619560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testComputeVerticalScrollRange() throws Throwable {
42629560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = new MockTextView(mActivity));
42639560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
42649560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
4265fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // test when layout is null
42669560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getLayout());
42679560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(0, ((MockTextView) mTextView).computeVerticalScrollRange());
4268fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
42699560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> ((MockTextView) mTextView).setFrame(0, 0, 40, 50));
42709560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
42719560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(mTextView.getHeight(), ((MockTextView) mTextView).computeVerticalScrollRange());
4272fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4273fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //set the layout
42749560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        layout(mTextView);
42759560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(mTextView.getLayout().getHeight(),
42769560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                ((MockTextView) mTextView).computeVerticalScrollRange());
4277fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4278fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4279a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
42809560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testDrawableStateChanged() throws Throwable {
42819560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = spy(new MockTextView(mActivity)));
42829560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
42839560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        reset(mTextView);
42849560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.refreshDrawableState();
42859560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ((MockTextView) verify(mTextView, times(1))).drawableStateChanged();
4286fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4287fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
42889560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4289a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4290fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetDefaultEditable() {
42919560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView = new MockTextView(mActivity);
4292fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4293fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //the TextView#getDefaultEditable() does nothing, and always return false.
42949560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertFalse(((MockTextView) mTextView).getDefaultEditable());
4295fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4296fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
42979560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4298a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4299fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetDefaultMovementMethod() {
4300fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        MockTextView textView = new MockTextView(mActivity);
4301fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4302fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //the TextView#getDefaultMovementMethod() does nothing, and always return null.
4303fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getDefaultMovementMethod());
4304fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4305fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
43069560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4307a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4308fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetFrame() {
4309fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        MockTextView textView = new MockTextView(mActivity);
4310fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4311fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //Assign a new size to this view
4312fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.setFrame(0, 0, 320, 480));
4313b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(0, textView.getLeft());
4314b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(0, textView.getTop());
4315b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(320, textView.getRight());
4316b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(480, textView.getBottom());
4317fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4318fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //Assign a same size to this view
4319fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(textView.setFrame(0, 0, 320, 480));
4320fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4321fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //negative input
4322fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.setFrame(-1, -1, -1, -1));
4323b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(-1, textView.getLeft());
4324b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(-1, textView.getTop());
4325b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(-1, textView.getRight());
4326b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(-1, textView.getBottom());
4327fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4328fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4329a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
43304b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testMarquee() throws Throwable {
4331354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Both are pointing to the same object. This works around current limitation in CTS
4332354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // coverage report tool for properly reporting coverage of base class method calls.
43339560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
43349560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mSecondTextView = new MockTextView(mActivity);
4335354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
43369560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView = mSecondTextView;
43379560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setText(LONG_TEXT);
43389560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setSingleLine();
43399560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setEllipsize(TruncateAt.MARQUEE);
43409560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setLayoutParams(new LayoutParams(100, 100));
43419560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        });
43429560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
4343bed9d222439713a766c3d5c91fae1526b5bc35dcBrian Muramatsu
4344bed9d222439713a766c3d5c91fae1526b5bc35dcBrian Muramatsu        final FrameLayout layout = new FrameLayout(mActivity);
43459560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        layout.addView(mTextView);
4346bed9d222439713a766c3d5c91fae1526b5bc35dcBrian Muramatsu
4347fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // make the fading to be shown
43489560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setHorizontalFadingEdgeEnabled(true);
4349fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
43509560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mActivity.setContentView(layout));
4351fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
4352fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
43539560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        TestSelectedRunnable runnable = new TestSelectedRunnable(mTextView) {
4354fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            public void run() {
43559560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                mTextView.setMarqueeRepeatLimit(-1);
4356fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                // force the marquee to start
4357fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                saveIsSelected1();
43589560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                mTextView.setSelected(true);
4359fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                saveIsSelected2();
4360fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            }
4361fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        };
43629560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(runnable);
4363fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4364fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // wait for the marquee to run
4365fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // fading is shown on both sides if the marquee runs for a while
43669560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        PollingCheck.waitFor(TIMEOUT, () ->
43679560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                ((MockTextView) mSecondTextView).getLeftFadingEdgeStrength() > 0.0f
43689560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                        && ((MockTextView) mSecondTextView).getRightFadingEdgeStrength() > 0.0f);
4369fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
43700f095ca986d7558f9f5260c71a12cef4474d9da3Siyamed Sinir        // wait for left marquee to fully apply
43719560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        PollingCheck.waitFor(TIMEOUT, () ->
43729560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                ((MockTextView) mSecondTextView).getLeftFadingEdgeStrength() > 0.99f);
4373354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
4374fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(runnable.getIsSelected1());
4375fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(runnable.getIsSelected2());
43769560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(-1, mTextView.getMarqueeRepeatLimit());
4377fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
43789560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        runnable = new TestSelectedRunnable(mTextView) {
4379fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            public void run() {
43809560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                mTextView.setMarqueeRepeatLimit(0);
4381fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                // force the marquee to stop
4382fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                saveIsSelected1();
43839560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                mTextView.setSelected(false);
4384fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                saveIsSelected2();
43859560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                mTextView.setGravity(Gravity.LEFT);
4386fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            }
4387fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        };
4388fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // force the marquee to stop
43899560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(runnable);
4390fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
4391fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(runnable.getIsSelected1());
4392fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(runnable.getIsSelected2());
43939560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(0.0f, ((MockTextView) mSecondTextView).getLeftFadingEdgeStrength(), 0.01f);
43949560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(((MockTextView) mSecondTextView).getRightFadingEdgeStrength() > 0.0f);
43959560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(0, mTextView.getMarqueeRepeatLimit());
4396fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
43979560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setGravity(Gravity.RIGHT));
4398fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
43999560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(((MockTextView) mSecondTextView).getLeftFadingEdgeStrength() > 0.0f);
44009560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(0.0f, ((MockTextView) mSecondTextView).getRightFadingEdgeStrength(), 0.01f);
4401fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
44029560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setGravity(Gravity.CENTER_HORIZONTAL));
4403fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
4404fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no left fading (Is it correct?)
44059560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(0.0f, ((MockTextView) mSecondTextView).getLeftFadingEdgeStrength(), 0.01f);
44069560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(((MockTextView) mSecondTextView).getRightFadingEdgeStrength() > 0.0f);
4407fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4408fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
44099560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4410a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
44116a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testGetMarqueeRepeatLimit() {
44126a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final TextView textView = new TextView(mActivity);
44136a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
44146a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setMarqueeRepeatLimit(10);
44156a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(10, textView.getMarqueeRepeatLimit());
44166a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
44176a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
44189560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4419a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4420fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessInputExtras() throws XmlPullParserException, IOException {
44219560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView = new TextView(mActivity);
44229560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setText(null, BufferType.EDITABLE);
44239560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setInputType(InputType.TYPE_CLASS_TEXT);
4424fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4425fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // do not create the extras
44269560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getInputExtras(false));
4427fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4428fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // create if it does not exist
44299560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        Bundle inputExtras = mTextView.getInputExtras(true);
4430fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(inputExtras);
4431fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(inputExtras.isEmpty());
4432fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4433fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // it is created already
44349560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNotNull(mTextView.getInputExtras(false));
4435fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4436fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
44379560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setInputExtras(R.xml.input_extras);
4438fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw NullPointerException!");
4439fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e) {
4440fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
4441fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4442fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
44439560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4444a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4445fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessContentType() {
44469560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView = new TextView(mActivity);
44479560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setText(null, BufferType.EDITABLE);
44489560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setKeyListener(null);
44499560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setTransformationMethod(null);
4450fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
44519560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setInputType(InputType.TYPE_CLASS_DATETIME
4452fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_NORMAL);
4453fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
44549560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_DATETIME_VARIATION_NORMAL, mTextView.getInputType());
44559560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getKeyListener() instanceof DateTimeKeyListener);
4456fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
44579560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setInputType(InputType.TYPE_CLASS_DATETIME
4458fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_DATE);
4459fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
44609560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_DATETIME_VARIATION_DATE, mTextView.getInputType());
44619560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getKeyListener() instanceof DateKeyListener);
4462fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
44639560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setInputType(InputType.TYPE_CLASS_DATETIME
4464fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_TIME);
4465fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
44669560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_DATETIME_VARIATION_TIME, mTextView.getInputType());
44679560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getKeyListener() instanceof TimeKeyListener);
4468fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
44699560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setInputType(InputType.TYPE_CLASS_NUMBER
4470fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_DECIMAL
4471fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_SIGNED);
4472fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_NUMBER
4473fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_DECIMAL
44749560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_NUMBER_FLAG_SIGNED, mTextView.getInputType());
44759560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertSame(mTextView.getKeyListener(), DigitsKeyListener.getInstance(true, true));
4476fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
44779560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setInputType(InputType.TYPE_CLASS_PHONE);
44789560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(InputType.TYPE_CLASS_PHONE, mTextView.getInputType());
44799560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getKeyListener() instanceof DialerKeyListener);
4480fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
44819560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setInputType(InputType.TYPE_CLASS_TEXT
4482fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
4483fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
44849560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT, mTextView.getInputType());
44859560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertSame(mTextView.getKeyListener(), TextKeyListener.getInstance(true, Capitalize.NONE));
4486fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
44879560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setSingleLine();
44889560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getTransformationMethod() instanceof SingleLineTransformationMethod);
44899560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setInputType(InputType.TYPE_CLASS_TEXT
4490fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_MULTI_LINE
4491fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
4492fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
4493fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_MULTI_LINE
44949560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS, mTextView.getInputType());
44959560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertSame(mTextView.getKeyListener(),
4496fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                TextKeyListener.getInstance(false, Capitalize.CHARACTERS));
44979560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getTransformationMethod());
4498fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
44999560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setInputType(InputType.TYPE_CLASS_TEXT
4500fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
4501fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
45029560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_TEXT_FLAG_CAP_WORDS, mTextView.getInputType());
45039560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertSame(mTextView.getKeyListener(),
4504fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                TextKeyListener.getInstance(false, Capitalize.WORDS));
45059560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getTransformationMethod() instanceof SingleLineTransformationMethod);
4506fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45079560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setInputType(InputType.TYPE_CLASS_TEXT
4508fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
4509fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
45109560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES, mTextView.getInputType());
45119560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertSame(mTextView.getKeyListener(),
4512fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                TextKeyListener.getInstance(false, Capitalize.SENTENCES));
4513fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45149560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setInputType(InputType.TYPE_NULL);
45159560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(InputType.TYPE_NULL, mTextView.getInputType());
45169560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getKeyListener() instanceof TextKeyListener);
4517fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4518fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45199560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4520a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4521fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessRawContentType() {
45229560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView = new TextView(mActivity);
45239560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setText(null, BufferType.EDITABLE);
45249560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setKeyListener(null);
45259560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setTransformationMethod(null);
4526fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45279560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setRawInputType(InputType.TYPE_CLASS_DATETIME
4528fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_NORMAL);
4529fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
45309560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_DATETIME_VARIATION_NORMAL, mTextView.getInputType());
45319560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getTransformationMethod());
45329560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getKeyListener());
4533fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45349560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setRawInputType(InputType.TYPE_CLASS_DATETIME
4535fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_DATE);
4536fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
45379560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_DATETIME_VARIATION_DATE, mTextView.getInputType());
45389560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getTransformationMethod());
45399560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getKeyListener());
4540fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45419560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setRawInputType(InputType.TYPE_CLASS_DATETIME
4542fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_TIME);
4543fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
45449560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_DATETIME_VARIATION_TIME, mTextView.getInputType());
45459560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getTransformationMethod());
45469560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getKeyListener());
4547fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45489560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setRawInputType(InputType.TYPE_CLASS_NUMBER
4549fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_DECIMAL
4550fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_SIGNED);
4551fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_NUMBER
4552fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_DECIMAL
45539560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_NUMBER_FLAG_SIGNED, mTextView.getInputType());
45549560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getTransformationMethod());
45559560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getKeyListener());
4556fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45579560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setRawInputType(InputType.TYPE_CLASS_PHONE);
45589560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(InputType.TYPE_CLASS_PHONE, mTextView.getInputType());
45599560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getTransformationMethod());
45609560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getKeyListener());
4561fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45629560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setRawInputType(InputType.TYPE_CLASS_TEXT
4563fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
4564fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
45659560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT, mTextView.getInputType());
45669560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getTransformationMethod());
45679560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getKeyListener());
4568fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45699560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setSingleLine();
45709560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getTransformationMethod() instanceof SingleLineTransformationMethod);
45719560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setRawInputType(InputType.TYPE_CLASS_TEXT
4572fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_MULTI_LINE
4573fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
4574fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
4575fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_MULTI_LINE
45769560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS, mTextView.getInputType());
45779560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getTransformationMethod() instanceof SingleLineTransformationMethod);
45789560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getKeyListener());
4579fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45809560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setRawInputType(InputType.TYPE_CLASS_TEXT
4581fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
4582fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
45839560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_TEXT_FLAG_CAP_WORDS, mTextView.getInputType());
45849560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getTransformationMethod() instanceof SingleLineTransformationMethod);
45859560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getKeyListener());
4586fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45879560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setRawInputType(InputType.TYPE_CLASS_TEXT
4588fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
4589fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
45909560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES, mTextView.getInputType());
45919560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getTransformationMethod() instanceof SingleLineTransformationMethod);
45929560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getKeyListener());
4593fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45949560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setRawInputType(InputType.TYPE_NULL);
45959560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.getTransformationMethod() instanceof SingleLineTransformationMethod);
45969560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertNull(mTextView.getKeyListener());
4597fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4598fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
45999560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4600a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
460172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testVerifyDrawable() {
46029560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView = new MockTextView(mActivity);
460372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4604a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable d = TestUtils.getDrawable(mActivity, R.drawable.pass);
46059560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertFalse(((MockTextView ) mTextView).verifyDrawable(d));
460672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
46079560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setCompoundDrawables(null, d, null, null);
46089560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(((MockTextView ) mTextView).verifyDrawable(d));
460972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
461072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4611a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
461272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testAccessPrivateImeOptions() {
461372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
461472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertNull(mTextView.getPrivateImeOptions());
461572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
461672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setPrivateImeOptions("com.example.myapp.SpecialMode=3");
461772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals("com.example.myapp.SpecialMode=3", mTextView.getPrivateImeOptions());
461872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
461972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setPrivateImeOptions(null);
462072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertNull(mTextView.getPrivateImeOptions());
462172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
462272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4623a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
462472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testSetOnEditorActionListener() {
462572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
462672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
462798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final TextView.OnEditorActionListener mockOnEditorActionListener =
462898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                mock(TextView.OnEditorActionListener.class);
462998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verifyZeroInteractions(mockOnEditorActionListener);
463072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
463198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mTextView.setOnEditorActionListener(mockOnEditorActionListener);
463298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verifyZeroInteractions(mockOnEditorActionListener);
463372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
463472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.onEditorAction(EditorInfo.IME_ACTION_DONE);
463598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockOnEditorActionListener, times(1)).onEditorAction(mTextView,
463698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                EditorInfo.IME_ACTION_DONE, null);
463772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
463872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4639a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
464072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testAccessImeOptions() {
464172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
464272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(EditorInfo.IME_NULL, mTextView.getImeOptions());
464372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
464472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setImeOptions(EditorInfo.IME_ACTION_GO);
464572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(EditorInfo.IME_ACTION_GO, mTextView.getImeOptions());
464672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
464772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setImeOptions(EditorInfo.IME_ACTION_DONE);
464872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(EditorInfo.IME_ACTION_DONE, mTextView.getImeOptions());
464972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
465072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setImeOptions(EditorInfo.IME_NULL);
465172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(EditorInfo.IME_NULL, mTextView.getImeOptions());
465272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
465372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4654a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
465572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testAccessImeActionLabel() {
465672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
465772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertNull(mTextView.getImeActionLabel());
465872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(0, mTextView.getImeActionId());
465972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
466072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setImeActionLabel("pinyin", 1);
466172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals("pinyin", mTextView.getImeActionLabel().toString());
466272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(1, mTextView.getImeActionId());
466372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
466472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
46659560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4666a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4667d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa    public void testAccessImeHintLocales() {
4668d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        final TextView textView = new TextView(mActivity);
4669d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        textView.setText("", BufferType.EDITABLE);
4670d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        textView.setKeyListener(null);
4671d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        textView.setRawInputType(InputType.TYPE_CLASS_TEXT);
4672d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        assertNull(textView.getImeHintLocales());
4673d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        {
4674d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            final EditorInfo editorInfo = new EditorInfo();
4675d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            textView.onCreateInputConnection(editorInfo);
4676d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            assertNull(editorInfo.hintLocales);
4677d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        }
4678d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa
4679d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        final LocaleList localeList = LocaleList.forLanguageTags("en-PH,en-US");
4680d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        textView.setImeHintLocales(localeList);
4681d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        assertEquals(localeList, textView.getImeHintLocales());
4682d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        {
4683d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            final EditorInfo editorInfo = new EditorInfo();
4684d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            textView.onCreateInputConnection(editorInfo);
4685d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            assertEquals(localeList, editorInfo.hintLocales);
4686d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        }
4687d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa    }
4688d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa
4689c873101a88e7ba584065de5e912508237378ca99Victoria Lease    @UiThreadTest
4690a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
469172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testSetExtractedText() {
469272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
469372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(mActivity.getResources().getString(R.string.text_view_hello),
469472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach                mTextView.getText().toString());
469572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
469672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        ExtractedText et = new ExtractedText();
4697ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4698ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        // Update text and selection.
469972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        et.text = "test";
4700ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.selectionStart = 0;
4701ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.selectionEnd = 2;
470272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
470372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setExtractedText(et);
470472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals("test", mTextView.getText().toString());
4705ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(0, mTextView.getSelectionStart());
4706ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(2, mTextView.getSelectionEnd());
4707ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4708ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        // Use partialStartOffset and partialEndOffset
4709ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.partialStartOffset = 2;
4710ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.partialEndOffset = 3;
4711ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.text = "x";
4712ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.selectionStart = 2;
4713ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.selectionEnd = 3;
4714ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4715ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        mTextView.setExtractedText(et);
4716ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals("text", mTextView.getText().toString());
4717ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(2, mTextView.getSelectionStart());
4718ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(3, mTextView.getSelectionEnd());
4719ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4720ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        // Update text with spans.
4721ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        final SpannableString ss = new SpannableString("ex");
4722ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        ss.setSpan(new UnderlineSpan(), 0, 2, 0);
4723ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        ss.setSpan(new URLSpan("ctstest://TextView/test"), 1, 2, 0);
4724ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4725ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.text = ss;
4726ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.partialStartOffset = 1;
4727ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.partialEndOffset = 3;
4728ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        mTextView.setExtractedText(et);
4729ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4730ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals("text", mTextView.getText().toString());
4731ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        final Editable editable = mTextView.getEditableText();
4732ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        final UnderlineSpan[] underlineSpans = mTextView.getEditableText().getSpans(
4733ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi                0, editable.length(), UnderlineSpan.class);
4734ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(1, underlineSpans.length);
4735ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(1, editable.getSpanStart(underlineSpans[0]));
4736ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(3, editable.getSpanEnd(underlineSpans[0]));
4737ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4738ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        final URLSpan[] urlSpans = mTextView.getEditableText().getSpans(
4739ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi                0, editable.length(), URLSpan.class);
4740ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(1, urlSpans.length);
4741ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(2, editable.getSpanStart(urlSpans[0]));
4742ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(3, editable.getSpanEnd(urlSpans[0]));
4743ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals("ctstest://TextView/test", urlSpans[0].getURL());
474472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
474572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4746a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
474772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testMoveCursorToVisibleOffset() throws Throwable {
474872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
474972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
475072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        // not a spannable text
47514b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> assertFalse(mTextView.moveCursorToVisibleOffset()));
475272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mInstrumentation.waitForIdleSync();
475372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
475472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        // a selection range
475572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        final String spannableText = "text";
47566b02e92df9486b4b1723473987bf025dcd18a23dAndrei Stingaceanu        mActivityRule.runOnUiThread(() ->  mTextView = new TextView(mActivity));
47579560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
475872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
47594b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
4760a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov                () -> mTextView.setText(spannableText, BufferType.SPANNABLE));
476172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mInstrumentation.waitForIdleSync();
476272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        Selection.setSelection((Spannable) mTextView.getText(), 0, spannableText.length());
476372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
476472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(0, mTextView.getSelectionStart());
476572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(spannableText.length(), mTextView.getSelectionEnd());
47664b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> assertFalse(mTextView.moveCursorToVisibleOffset()));
476772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mInstrumentation.waitForIdleSync();
476872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
476972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        // a spannable without range
47704b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> {
47716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = findTextView(R.id.textview_text);
47726beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(spannableText, BufferType.SPANNABLE);
477372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        });
477472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mInstrumentation.waitForIdleSync();
477572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
47764b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> assertTrue(mTextView.moveCursorToVisibleOffset()));
477772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mInstrumentation.waitForIdleSync();
477872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
477972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4780a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
4781afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsu    public void testIsInputMethodTarget() throws Throwable {
478272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
478372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertFalse(mTextView.isInputMethodTarget());
478472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
478572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertFalse(mTextView.isFocused());
47864b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> {
47876beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setFocusable(true);
47886beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
47896beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu         });
4790afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsu        mInstrumentation.waitForIdleSync();
4791afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsu        assertTrue(mTextView.isFocused());
479204d12809ae731ea2aea678707bcc606f05efb23aBrian Muramatsu
4793b7724cefaf6067b1f6b59d3abae73828b48945c3Kirill Grouchnikov        PollingCheck.waitFor(mTextView::isInputMethodTarget);
479472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
479572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
47969560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4797a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
47986a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testBeginEndBatchEditAreNotCalledForNonEditableText() {
4799b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        final TextView mockTextView = spy(new TextView(mActivity));
4800b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir
4801b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        // TextView should not call onBeginBatchEdit or onEndBatchEdit during initialization
4802b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onBeginBatchEdit();
4803b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onEndBatchEdit();
48046a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
480572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
48066a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.beginBatchEdit();
4807b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        // Since TextView doesn't support editing, the callbacks should not be called
4808b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onBeginBatchEdit();
4809b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onEndBatchEdit();
48106a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
48116a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.endBatchEdit();
4812b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        // Since TextView doesn't support editing, the callbacks should not be called
4813b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onBeginBatchEdit();
4814b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onEndBatchEdit();
48156a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
48166a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
4817a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
48184b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testBeginEndBatchEditCallbacksAreCalledForEditableText() throws Throwable {
48199560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView = spy(new TextView(mActivity)));
48209560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
48216a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
4822a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        final FrameLayout layout = new FrameLayout(mActivity);
48236a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
48246a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT,
48256a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT);
48269560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        layout.addView(mTextView, layoutParams);
48276a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.setLayoutParams(layoutParams);
48286a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
48299560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mActivity.setContentView(layout));
48306a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mInstrumentation.waitForIdleSync();
48316a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
48329560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
48339560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setKeyListener(QwertyKeyListener.getInstance(false, Capitalize.NONE));
48349560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setText("", BufferType.EDITABLE);
48359560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.requestFocus();
48366a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        });
48376a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mInstrumentation.waitForIdleSync();
48386a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
48399560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        reset(mTextView);
48409560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertTrue(mTextView.hasFocus());
48419560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(mTextView, never()).onBeginBatchEdit();
48429560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(mTextView, never()).onEndBatchEdit();
48436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
48449560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.beginBatchEdit();
48456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
48469560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(mTextView, times(1)).onBeginBatchEdit();
48479560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(mTextView, never()).onEndBatchEdit();
4848b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir
48499560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        reset(mTextView);
48509560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.endBatchEdit();
48519560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(mTextView, never()).onBeginBatchEdit();
48529560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(mTextView, times(1)).onEndBatchEdit();
485372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
485472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
485572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    @UiThreadTest
4856a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
485772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testBringPointIntoView() throws Throwable {
485872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
485972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertFalse(mTextView.bringPointIntoView(1));
486072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
486172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.layout(0, 0, 100, 100);
486272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertFalse(mTextView.bringPointIntoView(2));
486372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
486472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4865a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
486672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testCancelLongPress() {
486772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
48689560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        CtsTouchUtils.emulateLongPressOnViewCenter(mInstrumentation, mTextView);
486972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.cancelLongPress();
487072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
487172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
487272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    @UiThreadTest
4873a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
487472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testClearComposingText() {
487572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
487672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setText("Hello world!", BufferType.SPANNABLE);
487772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        Spannable text = (Spannable) mTextView.getText();
487872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
487972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(-1, BaseInputConnection.getComposingSpanStart(text));
488072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(-1, BaseInputConnection.getComposingSpanStart(text));
488172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
488272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        BaseInputConnection.setComposingSpans((Spannable) mTextView.getText());
488372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(0, BaseInputConnection.getComposingSpanStart(text));
488472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(0, BaseInputConnection.getComposingSpanStart(text));
488572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
488672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.clearComposingText();
488772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(-1, BaseInputConnection.getComposingSpanStart(text));
488872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(-1, BaseInputConnection.getComposingSpanStart(text));
488972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
489072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
48919560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4892a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
489372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testComputeVerticalScrollExtent() {
48949560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView = new MockTextView(mActivity);
48959560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(0, ((MockTextView) mTextView).computeVerticalScrollExtent());
489672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4897a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable d = TestUtils.getDrawable(mActivity, R.drawable.pass);
48989560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.setCompoundDrawables(null, d, null, d);
489972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
49009560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        assertEquals(0, ((MockTextView) mTextView).computeVerticalScrollExtent());
490172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
490272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
490372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    @UiThreadTest
4904a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
490572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testDidTouchFocusSelect() {
4906c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        mTextView = new EditText(mActivity);
490772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertFalse(mTextView.didTouchFocusSelect());
490872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
490972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setFocusable(true);
491072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.requestFocus();
491172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertTrue(mTextView.didTouchFocusSelect());
491272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
491372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4914a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
49154b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testSelectAllJustAfterTap() throws Throwable {
49160ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        // Prepare an EditText with focus.
49179560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
49186beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = new EditText(mActivity);
49196beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mActivity.setContentView(mTextView);
49200ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
49216beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertFalse(mTextView.didTouchFocusSelect());
49226beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setFocusable(true);
49236beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
49246beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertTrue(mTextView.didTouchFocusSelect());
49250ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
49266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("Hello, World.", BufferType.SPANNABLE);
49270ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        });
49280ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        mInstrumentation.waitForIdleSync();
49290ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
49300ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        // Tap the view to show InsertPointController.
49319404cdc3d439d5a2d1b805934c53a8ba6dc68fa8Andrei Stingaceanu        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mTextView);
493283a70cb57c839148a4feff786cdbb3803828d484Bobby Wang        // bad workaround for waiting onStartInputView of LeanbackIme.apk done
493383a70cb57c839148a4feff786cdbb3803828d484Bobby Wang        try {
493483a70cb57c839148a4feff786cdbb3803828d484Bobby Wang            Thread.sleep(1000);
493583a70cb57c839148a4feff786cdbb3803828d484Bobby Wang        } catch (InterruptedException e) {
493683a70cb57c839148a4feff786cdbb3803828d484Bobby Wang            e.printStackTrace();
493783a70cb57c839148a4feff786cdbb3803828d484Bobby Wang        }
49380ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
49390ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        // Execute SelectAll context menu.
49409560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.onTextContextMenuItem(android.R.id.selectAll));
49410ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        mInstrumentation.waitForIdleSync();
49420ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
49430ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        // The selection must be whole of the text contents.
49440ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        assertEquals(0, mTextView.getSelectionStart());
494583a70cb57c839148a4feff786cdbb3803828d484Bobby Wang        assertEquals("Hello, World.", mTextView.getText().toString());
49460ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        assertEquals(mTextView.length(), mTextView.getSelectionEnd());
49470ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka    }
49480ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
49499560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
4950a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
495172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testExtractText() {
495272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = new TextView(mActivity);
495372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
495472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        ExtractedTextRequest request = new ExtractedTextRequest();
495572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        ExtractedText outText = new ExtractedText();
495672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
495772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        request.token = 0;
495872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        request.flags = 10;
495972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        request.hintMaxLines = 2;
496072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        request.hintMaxChars = 20;
496172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertTrue(mTextView.extractText(request, outText));
496272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
496372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
496472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertTrue(mTextView.extractText(request, outText));
496572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
496672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(mActivity.getResources().getString(R.string.text_view_hello),
496772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach                outText.text.toString());
4968c778c0d53d612a73b39cbf965f5068a3b0a10695Yoshiki Iguchi
4969c778c0d53d612a73b39cbf965f5068a3b0a10695Yoshiki Iguchi        // Tests for invalid arguments.
4970c778c0d53d612a73b39cbf965f5068a3b0a10695Yoshiki Iguchi        assertFalse(mTextView.extractText(request, null));
4971c778c0d53d612a73b39cbf965f5068a3b0a10695Yoshiki Iguchi        assertFalse(mTextView.extractText(null, outText));
4972c778c0d53d612a73b39cbf965f5068a3b0a10695Yoshiki Iguchi        assertFalse(mTextView.extractText(null, null));
497372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
497472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
497594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
4976a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
497794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testTextDirectionDefault() {
4978c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
49792a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getRawTextDirection());
498094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
498194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
498294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
4983a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
498494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testSetGetTextDirection() {
4985c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
498694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
498794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
49882a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getRawTextDirection());
498994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
499094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
49912a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getRawTextDirection());
499294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
499394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
49942a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getRawTextDirection());
499594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
499694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
49972a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getRawTextDirection());
499894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
499994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
50002a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getRawTextDirection());
500194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
500294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
50032a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getRawTextDirection());
500402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
500502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
500602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getRawTextDirection());
500702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
500802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
500902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getRawTextDirection());
501094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
501194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
501294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
5013a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
501494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testGetResolvedTextDirectionLtr() {
5015c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
501694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setText("this is a test");
501794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
50182a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
501994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
502094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
50212a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
502294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
502394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
50242a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
502594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
502694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
50272a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
502894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
502994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
50302a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
503194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
503294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
50332a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
503494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
503594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
50362a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
503702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
503802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
503902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
504002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
504102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
504202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
504394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
504494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
504594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
5046a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
504794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testGetResolvedTextDirectionLtrWithInheritance() {
5048c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        LinearLayout ll = new LinearLayout(mActivity);
504994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
505094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
5051c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
505294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setText("this is a test");
505394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.addView(tv);
505494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
505594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
50562a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
505794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
505894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
50592a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
506094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
506194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
50622a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
506394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
506494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
50652a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
506694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
506794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
50682a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
506994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
507094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
50712a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
507202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
507302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
507402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
507502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
507602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
507702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
507894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
507994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
508094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
5081a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
508294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testGetResolvedTextDirectionRtl() {
5083c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
508494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setText("\u05DD\u05DE"); // hebrew
508594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
50862a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
508794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
508894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
50892a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
509094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
509194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
50922a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
509394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
509494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
50952a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
509694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
509794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
50982a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
509994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
510094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
51012a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
510294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
510394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
51042a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
510502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
510602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
510702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
510802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
510902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
511002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
511194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
511294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
511394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
5114a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
511594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testGetResolvedTextDirectionRtlWithInheritance() {
5116c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        LinearLayout ll = new LinearLayout(mActivity);
511794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
511894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
5119c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
512094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setText("\u05DD\u05DE"); // hebrew
512194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.addView(tv);
512294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
512394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
51242a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
512594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
512694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
51272a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
512894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
512994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
51302a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
513194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
513294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
51332a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
513494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
513594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
51362a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
513794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
513894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
51392a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
514094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
514102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
514202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
514302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
514402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
514502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
514602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
514794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        // Force to RTL text direction on the layout
514894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.setTextDirection(View.TEXT_DIRECTION_RTL);
514994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
515094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
51512a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
515294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
515394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
51542a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
515594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
515694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
51572a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
515894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
515994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
51602a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
516194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
516294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
51632a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
516494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
516594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
51662a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
516702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
516802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
516902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
517002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
517102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
517202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
517394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
517494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
517594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
5176a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
517794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testResetTextDirection() {
5178c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        LinearLayout ll = (LinearLayout) mActivity.findViewById(R.id.layout_textviewtest);
5179c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = (TextView) mActivity.findViewById(R.id.textview_rtl);
518094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
518194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.setTextDirection(View.TEXT_DIRECTION_RTL);
518294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
51832a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
518494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
5185f0d2af33ae194bead489caef9b461f2bee6f45a6Fabrice Di Meglio        // No reset when we remove the view
518694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.removeView(tv);
5187f0d2af33ae194bead489caef9b461f2bee6f45a6Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
5188f0d2af33ae194bead489caef9b461f2bee6f45a6Fabrice Di Meglio
5189f0d2af33ae194bead489caef9b461f2bee6f45a6Fabrice Di Meglio        // Reset is done when we add the view
5190f0d2af33ae194bead489caef9b461f2bee6f45a6Fabrice Di Meglio        ll.addView(tv);
51912a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
519294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
519394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
519402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    @UiThreadTest
5195a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
519602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    public void testTextDirectionFirstStrongLtr() {
519702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
519802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is LTR, the paragraph direction is LTR.
519902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
520002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
520102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
520202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("this is a test");
520302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
520402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
520502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
520602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
520702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
520802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
520902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
521002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_LEFT_TO_RIGHT, layout.getParagraphDirection(0));
521102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
521202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
521302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is RTL, the paragraph direction is RTL.
521402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
521502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
521602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
521702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("\u05DD\u05DE"); // Hebrew
521802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
521902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
522002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
522102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
522202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
522302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
522402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
522502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_RIGHT_TO_LEFT, layout.getParagraphDirection(0));
522602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
522702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
522802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is not a strong directional character, the paragraph
522902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // direction is LTR.
523002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
523102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
523202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
523302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("\uFFFD");  // REPLACEMENT CHARACTER. Neutral direction.
523402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
523502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
523602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
523702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
523802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
523902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
524002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
524102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_LEFT_TO_RIGHT, layout.getParagraphDirection(0));
524202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
524302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    }
524402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
524502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    @UiThreadTest
5246a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
524702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    public void testTextDirectionFirstStrongRtl() {
524802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
524902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is LTR, the paragraph direction is LTR.
525002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
525102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
525202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
525302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("this is a test");
525402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
525502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
525602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
525702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
525802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
525902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
526002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
526102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_LEFT_TO_RIGHT, layout.getParagraphDirection(0));
526202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
526302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
526402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is RTL, the paragraph direction is RTL.
526502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
526602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
526702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
526802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("\u05DD\u05DE"); // Hebrew
526902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
527002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
527102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
527202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
527302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
527402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
527502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
527602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_RIGHT_TO_LEFT, layout.getParagraphDirection(0));
527702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
527802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
527902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is not a strong directional character, the paragraph
528002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // direction is RTL.
528102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
528202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
528302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
528402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("\uFFFD");  // REPLACEMENT CHARACTER. Neutral direction.
528502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
528602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
528702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
528802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
528902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
529002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
529102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
529202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_RIGHT_TO_LEFT, layout.getParagraphDirection(0));
529302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
529402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    }
529502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
52969560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
5297a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5298c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader    public void testTextLocales() {
5299c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        TextView tv = new TextView(mActivity);
5300c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(Locale.getDefault(), tv.getTextLocale());
5301c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(LocaleList.getDefault(), tv.getTextLocales());
5302c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
5303c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        tv.setTextLocale(Locale.CHINESE);
5304c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(Locale.CHINESE, tv.getTextLocale());
5305c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(new LocaleList(Locale.CHINESE), tv.getTextLocales());
5306c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
5307c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        tv.setTextLocales(LocaleList.forLanguageTags("en,ja"));
5308c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(Locale.forLanguageTag("en"), tv.getTextLocale());
5309c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(LocaleList.forLanguageTags("en,ja"), tv.getTextLocales());
5310c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
5311c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        try {
5312c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            tv.setTextLocale(null);
5313c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            fail("Setting the text locale to null should throw");
5314c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        } catch (Throwable e) {
5315c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            assertEquals(IllegalArgumentException.class, e.getClass());
5316c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        }
5317c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
5318c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        try {
5319c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            tv.setTextLocales(null);
5320c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            fail("Setting the text locales to null should throw");
5321c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        } catch (Throwable e) {
5322c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            assertEquals(IllegalArgumentException.class, e.getClass());
5323c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        }
5324c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
5325c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        try {
5326c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            tv.setTextLocales(new LocaleList());
5327c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            fail("Setting the text locale to an empty list should throw");
5328c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        } catch (Throwable e) {
5329c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            assertEquals(IllegalArgumentException.class, e.getClass());
5330c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        }
5331c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader    }
5332c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
53339560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
5334a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5335b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka    public void testAllCapsLocalization() {
5336b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        String testString = "abcdefghijklmnopqrstuvwxyz";
5337b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka
5338b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        // The capitalized characters of "i" on Turkish and Azerbaijani are different from English.
5339b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        Locale[] testLocales = {
5340b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka            new Locale("az", "AZ"),
5341b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka            new Locale("tr", "TR"),
5342b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka            new Locale("en", "US"),
5343b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        };
5344b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka
5345b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        TextView tv = new TextView(mActivity);
5346b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        tv.setAllCaps(true);
5347b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        for (Locale locale: testLocales) {
5348b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka            tv.setTextLocale(locale);
5349b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka            assertEquals("Locale: " + locale.getDisplayName(),
5350b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka                         testString.toUpperCase(locale),
5351b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka                         tv.getTransformationMethod().getTransformation(testString, tv).toString());
5352b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        }
5353b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka    }
5354b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka
5355dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    @UiThreadTest
5356a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5357dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    public void testTextAlignmentDefault() {
5358a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        TextView tv = new TextView(mActivity);
53597fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getRawTextAlignment());
5360dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        // resolved default text alignment is GRAVITY
53617fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
5362dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    }
5363dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5364dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    @UiThreadTest
5365a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5366dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    public void testSetGetTextAlignment() {
5367a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        TextView tv = new TextView(mActivity);
5368dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5369dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
53707fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getRawTextAlignment());
5371dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5372dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
53737fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getRawTextAlignment());
5374dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5375dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
53767fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_START, tv.getRawTextAlignment());
5377dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5378dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
53797fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_END, tv.getRawTextAlignment());
5380dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5381dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
53827fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_START, tv.getRawTextAlignment());
5383dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5384dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
53857fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_END, tv.getRawTextAlignment());
5386dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    }
5387dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5388dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    @UiThreadTest
5389a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5390dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    public void testGetResolvedTextAlignment() {
5391a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        TextView tv = new TextView(mActivity);
5392dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
53937fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
5394dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5395757ec4fdfd1798a8e28d050433c67e628a7f578dFabrice Di Meglio        // Test center alignment first so that we dont hit the default case
5396dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
53977fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5398dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5399757ec4fdfd1798a8e28d050433c67e628a7f578dFabrice Di Meglio        // Test the default case too
5400757ec4fdfd1798a8e28d050433c67e628a7f578dFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
5401757ec4fdfd1798a8e28d050433c67e628a7f578dFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
5402757ec4fdfd1798a8e28d050433c67e628a7f578dFabrice Di Meglio
5403dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
54047fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_START, tv.getTextAlignment());
5405dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5406dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
54077fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_END, tv.getTextAlignment());
5408dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5409dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
54107fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_START, tv.getTextAlignment());
5411dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5412dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
54137fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_END, tv.getTextAlignment());
5414dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    }
5415dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5416dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    @UiThreadTest
5417a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5418dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    public void testGetResolvedTextAlignmentWithInheritance() {
5419a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        LinearLayout ll = new LinearLayout(mActivity);
5420dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
5421dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5422a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        TextView tv = new TextView(mActivity);
5423dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.addView(tv);
5424dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5425dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        // check defaults
54267fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getRawTextAlignment());
5427dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
5428dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5429dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        // set inherit and check that child is following parent
5430dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_INHERIT);
54317fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_INHERIT, tv.getRawTextAlignment());
5432dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5433dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
54347fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5435dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5436dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
54377fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_START, tv.getTextAlignment());
5438dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5439dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
54407fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_END, tv.getTextAlignment());
5441dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5442dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
54437fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_START, tv.getTextAlignment());
5444dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5445dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
54467fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_END, tv.getTextAlignment());
5447dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5448dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        // now get rid of the inheritance but still change the parent
5449dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
5450dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5451dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
54527fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5453dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5454dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
54557fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5456dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5457dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
54587fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5459dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5460dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
54617fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5462dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5463dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
54647fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5465dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    }
5466dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5467dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    @UiThreadTest
5468a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5469dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    public void testResetTextAlignment() {
5470a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        LinearLayout ll = (LinearLayout) mActivity.findViewById(R.id.layout_textviewtest);
5471a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        TextView tv = (TextView) mActivity.findViewById(R.id.textview_rtl);
5472dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5473dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
5474dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_INHERIT);
54757fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5476dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
54774f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio        // No reset when we remove the view
5478dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.removeView(tv);
54794f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
54804f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio
54814f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio        // Reset is done when we add the view
54824f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio        // Default text alignment is GRAVITY
54834f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio        ll.addView(tv);
54847fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
5485dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    }
5486dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5487938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov    @UiThreadTest
5488a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5489938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov    public void testDrawableResolution() {
5490b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 1.1: left / right drawable defined in default LTR mode
5491938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        TextView tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_1);
5492a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5493938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5494a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, -1, -1,
5495938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5496b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5497b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 1.2: left / right drawable defined in default RTL mode
5498938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_2);
5499a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5500938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5501a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, -1, -1,
5502938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5503b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5504b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 2.1: start / end drawable defined in LTR mode
5505938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_2_1);
5506a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5507938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5508a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5509938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5510b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5511b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 2.2: start / end drawable defined in RTL mode
5512938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_2_2);
5513a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
5514938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5515a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5516938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5517b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5518b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 3.1: left / right / start / end drawable defined in LTR mode
5519938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_3_1);
5520a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5521938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5522a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5523938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5524b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5525b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 3.2: left / right / start / end drawable defined in RTL mode
5526938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_3_2);
5527a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
5528938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5529a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5530938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5531b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5532b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 4.1: start / end drawable defined in LTR mode inside a layout
5533b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // that defines the layout direction
5534938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_4_1);
5535a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5536938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5537a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5538938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5539b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5540b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 4.2: start / end drawable defined in RTL mode inside a layout
5541b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // that defines the layout direction
5542938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_4_2);
5543a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
5544938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5545a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5546938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5547b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5548b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 5.1: left / right / start / end drawable defined in LTR mode inside a layout
5549b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // that defines the layout direction
5550938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_5_1);
5551a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5552938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5553a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5554938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5555b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5556b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 5.2: left / right / start / end drawable defined in RTL mode inside a layout
5557b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // that defines the layout direction
5558938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_5_2);
5559a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
5560938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5561a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5562938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5563b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio    }
5564b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
55659776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio    @UiThreadTest
5566a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
55679776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio    public void testDrawableResolution2() {
55689776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio        // Case 1.1: left / right drawable defined in default LTR mode
5569938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        TextView tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_1);
5570a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5571938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
55729776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5573a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        tv.setCompoundDrawables(null, null,
5574a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov                TestUtils.getDrawable(mActivity, R.drawable.icon_yellow), null);
5575a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, -1, R.drawable.icon_yellow, -1, -1);
55769776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5577938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_2);
5578a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5579938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
55809776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5581a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        tv.setCompoundDrawables(TestUtils.getDrawable(mActivity, R.drawable.icon_yellow), null,
5582a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov                null, null);
5583a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_yellow, -1, -1, -1);
55849776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5585938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_ltr);
5586a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, -1, -1, -1, -1);
55879776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5588a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        tv.setCompoundDrawables(TestUtils.getDrawable(mActivity, R.drawable.icon_blue), null,
5589a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov                TestUtils.getDrawable(mActivity, R.drawable.icon_red), null);
5590a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red, -1, -1);
55919776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5592a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        tv.setCompoundDrawablesRelative(TestUtils.getDrawable(mActivity, R.drawable.icon_yellow),
5593a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov                null, null, null);
5594a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_yellow, -1, -1, -1);
5595938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov    }
5596938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
5597a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5598938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov    public void testCompoundAndTotalPadding() {
5599938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final Resources res = mActivity.getResources();
5600938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int drawablePadding = res.getDimensionPixelSize(R.dimen.textview_drawable_padding);
5601938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int paddingLeft = res.getDimensionPixelSize(R.dimen.textview_padding_left);
5602938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int paddingRight = res.getDimensionPixelSize(R.dimen.textview_padding_right);
5603938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int paddingTop = res.getDimensionPixelSize(R.dimen.textview_padding_top);
5604938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int paddingBottom = res.getDimensionPixelSize(R.dimen.textview_padding_bottom);
5605938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int iconSize = TestUtils.dpToPx(mActivity, 32);
5606938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
5607938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final TextView textViewLtr = (TextView) mActivity.findViewById(
5608938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.id.textview_compound_drawable_ltr);
5609938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int combinedPaddingLeftLtr = paddingLeft + drawablePadding + iconSize;
5610938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int combinedPaddingRightLtr = paddingRight + drawablePadding + iconSize;
5611938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftLtr, textViewLtr.getCompoundPaddingLeft());
5612938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftLtr, textViewLtr.getCompoundPaddingStart());
5613938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftLtr, textViewLtr.getTotalPaddingLeft());
5614938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftLtr, textViewLtr.getTotalPaddingStart());
5615938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightLtr, textViewLtr.getCompoundPaddingRight());
5616938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightLtr, textViewLtr.getCompoundPaddingEnd());
5617938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightLtr, textViewLtr.getTotalPaddingRight());
5618938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightLtr, textViewLtr.getTotalPaddingEnd());
5619938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(paddingTop + drawablePadding + iconSize,
5620938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                textViewLtr.getCompoundPaddingTop());
5621938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(paddingBottom + drawablePadding + iconSize,
5622938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                textViewLtr.getCompoundPaddingBottom());
5623938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
5624938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final TextView textViewRtl = (TextView) mActivity.findViewById(
5625938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.id.textview_compound_drawable_rtl);
5626938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int combinedPaddingLeftRtl = paddingLeft + drawablePadding + iconSize;
5627938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int combinedPaddingRightRtl = paddingRight + drawablePadding + iconSize;
5628938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftRtl, textViewRtl.getCompoundPaddingLeft());
5629938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftRtl, textViewRtl.getCompoundPaddingEnd());
5630938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftRtl, textViewRtl.getTotalPaddingLeft());
5631938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftRtl, textViewRtl.getTotalPaddingEnd());
5632938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightRtl, textViewRtl.getCompoundPaddingRight());
5633938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightRtl, textViewRtl.getCompoundPaddingStart());
5634938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightRtl, textViewRtl.getTotalPaddingRight());
5635938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightRtl, textViewRtl.getTotalPaddingStart());
5636938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(paddingTop + drawablePadding + iconSize,
5637938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                textViewRtl.getCompoundPaddingTop());
5638938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(paddingBottom + drawablePadding + iconSize,
5639938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                textViewRtl.getCompoundPaddingBottom());
56409776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio    }
56419776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
56429560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
5643a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5644e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka    public void testSetGetBreakStrategy() {
5645e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        TextView tv = new TextView(mActivity);
5646e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5647a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        final PackageManager pm = mInstrumentation.getTargetContext().getPackageManager();
56482751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka
5649d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        // The default value is from the theme, here the default is BREAK_STRATEGY_HIGH_QUALITY for
56502751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka        // TextView except for Android Wear. The default value for Android Wear is
56512751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka        // BREAK_STRATEGY_BALANCED.
56522751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka        if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
56532751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka            // Android Wear
56542751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka            assertEquals(Layout.BREAK_STRATEGY_BALANCED, tv.getBreakStrategy());
56552751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka        } else {
56562751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka            // All other form factor.
56572751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka            assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY, tv.getBreakStrategy());
56582751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka        }
5659e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5660e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
5661e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.BREAK_STRATEGY_SIMPLE, tv.getBreakStrategy());
5662e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5663e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY);
5664e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY, tv.getBreakStrategy());
5665e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5666e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
5667e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.BREAK_STRATEGY_BALANCED, tv.getBreakStrategy());
5668d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi
5669d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        EditText et = new EditText(mActivity);
5670d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi
5671d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        // The default value is from the theme, here the default is BREAK_STRATEGY_SIMPLE for
5672d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        // EditText.
5673d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        assertEquals(Layout.BREAK_STRATEGY_SIMPLE, et.getBreakStrategy());
5674d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi
5675d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        et.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
5676d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        assertEquals(Layout.BREAK_STRATEGY_SIMPLE, et.getBreakStrategy());
5677d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi
5678d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        et.setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY);
5679d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY, et.getBreakStrategy());
5680d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi
5681d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        et.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
5682d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        assertEquals(Layout.BREAK_STRATEGY_BALANCED, et.getBreakStrategy());
5683e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka    }
5684e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
56859560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @UiThreadTest
5686a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
5687e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka    public void testSetGetHyphenationFrequency() {
5688e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        TextView tv = new TextView(mActivity);
5689e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5690d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        assertEquals(Layout.HYPHENATION_FREQUENCY_NORMAL, tv.getHyphenationFrequency());
5691e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5692e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE);
5693e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.HYPHENATION_FREQUENCY_NONE, tv.getHyphenationFrequency());
5694e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5695e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
5696e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.HYPHENATION_FREQUENCY_NORMAL, tv.getHyphenationFrequency());
5697e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5698e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
5699e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.HYPHENATION_FREQUENCY_FULL, tv.getHyphenationFrequency());
5700e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka    }
5701e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5702a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka    @UiThreadTest
5703a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka    @Test
5704a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka    public void testSetGetJustify() {
5705a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka        TextView tv = new TextView(mActivity);
5706a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka
5707a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka        assertFalse(tv.getJustify());
5708a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka        tv.setJustify(true);
5709a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka        assertTrue(tv.getJustify());
5710a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka        tv.setJustify(false);
5711a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka        assertFalse(tv.getJustify());
5712a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka    }
5713a3cf2598fa76975e1051852c12fffe208cdfb52cSeigo Nonaka
5714a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
57154b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testSetAndGetCustomSelectionActionModeCallback() throws Throwable {
571632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        final String text = "abcde";
57179560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
57186beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = new EditText(mActivity);
57196beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mActivity.setContentView(mTextView);
57206beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text, BufferType.SPANNABLE);
57216beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setTextIsSelectable(true);
57226beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
57236beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setSelected(true);
572432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        });
572532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
572632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
572732944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        // Check default value.
572832944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        assertNull(mTextView.getCustomSelectionActionModeCallback());
572932944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
573098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final ActionMode.Callback mockActionModeCallback = mock(ActionMode.Callback.class);
573198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
573298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                thenReturn(Boolean.FALSE);
573398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mTextView.setCustomSelectionActionModeCallback(mockActionModeCallback);
573498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(mockActionModeCallback,
573532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi                mTextView.getCustomSelectionActionModeCallback());
573632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
57379560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
57386beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Set selection and try to start action mode.
57396beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            final Bundle args = new Bundle();
57406beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            args.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
57416beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            args.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, text.length());
57426beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.performAccessibilityAction(
57436beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    AccessibilityNodeInfo.ACTION_SET_SELECTION, args);
574432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        });
574532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
574632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
574798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockActionModeCallback, times(1)).onCreateActionMode(
574898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                any(ActionMode.class), any(Menu.class));
574932944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
57509560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
57516beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Remove selection and stop action mode.
57526beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.copy);
575332944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        });
575432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
575532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
575632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        // Action mode was blocked.
575798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockActionModeCallback, never()).onDestroyActionMode(any(ActionMode.class));
575832944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
575998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        // Reset and reconfigure callback.
576098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockActionModeCallback);
576198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
576298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                thenReturn(Boolean.TRUE);
576398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(mockActionModeCallback, mTextView.getCustomSelectionActionModeCallback());
576432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
57659560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
57666beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Set selection and try to start action mode.
57676beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            final Bundle args = new Bundle();
57686beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            args.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
57696beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            args.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, text.length());
57706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.performAccessibilityAction(
57716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    AccessibilityNodeInfo.ACTION_SET_SELECTION, args);
577232944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
577332944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        });
577432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
577532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
577698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockActionModeCallback, times(1)).onCreateActionMode(
577798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                any(ActionMode.class), any(Menu.class));
577832944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
57799560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
57806beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Remove selection and stop action mode.
57816beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.copy);
578232944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        });
578332944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
578432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
578532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        // Action mode was started
578698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockActionModeCallback, times(1)).onDestroyActionMode(any(ActionMode.class));
578732944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi    }
578832944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
57896beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
5790a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
579198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov    public void testSetAndGetCustomInsertionActionMode() {
579232944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        initTextViewForTyping();
579332944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        // Check default value.
579432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        assertNull(mTextView.getCustomInsertionActionModeCallback());
579532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
579698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final ActionMode.Callback mockActionModeCallback = mock(ActionMode.Callback.class);
579798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
579898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                thenReturn(Boolean.FALSE);
579998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mTextView.setCustomInsertionActionModeCallback(mockActionModeCallback);
580098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(mockActionModeCallback, mTextView.getCustomInsertionActionModeCallback());
580132944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        // TODO(Bug: 22033189): Tests the set callback is actually used.
580232944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi    }
580332944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
5804a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
58059560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    public void testTextShadows() throws Throwable {
580698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final TextView textViewWithConfiguredShadow =
580798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                (TextView) mActivity.findViewById(R.id.textview_with_shadow);
5808a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(1.0f, textViewWithConfiguredShadow.getShadowDx(), 0.0f);
5809a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(2.0f, textViewWithConfiguredShadow.getShadowDy(), 0.0f);
5810a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(3.0f, textViewWithConfiguredShadow.getShadowRadius(), 0.0f);
581198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(Color.GREEN, textViewWithConfiguredShadow.getShadowColor());
581232944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
581398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
5814a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(0.0f, textView.getShadowDx(), 0.0f);
5815a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(0.0f, textView.getShadowDy(), 0.0f);
5816a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(0.0f, textView.getShadowRadius(), 0.0f);
581732944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
58189560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> textView.setShadowLayer(5.0f, 3.0f, 4.0f, Color.RED));
581998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mInstrumentation.waitForIdleSync();
5820a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(3.0f, textView.getShadowDx(), 0.0f);
5821a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(4.0f, textView.getShadowDy(), 0.0f);
5822a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(5.0f, textView.getShadowRadius(), 0.0f);
582398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(Color.RED, textView.getShadowColor());
582472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
582572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
5826a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
58274b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testFontFeatureSettings() throws Throwable {
5828354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
5829354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(TextUtils.isEmpty(textView.getFontFeatureSettings()));
5830354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
58319560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> textView.setFontFeatureSettings("smcp"));
5832354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
5833354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals("smcp", textView.getFontFeatureSettings());
5834354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
58359560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> textView.setFontFeatureSettings("frac"));
5836354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
5837354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals("frac", textView.getFontFeatureSettings());
5838354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    }
5839354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5840354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    private static class SoftInputResultReceiver extends ResultReceiver {
5841354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        private boolean mIsDone;
5842354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        private int mResultCode;
5843354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5844354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        public SoftInputResultReceiver(Handler handler) {
5845354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            super(handler);
5846354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        }
5847354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5848354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        @Override
5849354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        protected void onReceiveResult(int resultCode, Bundle resultData) {
5850354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            mResultCode = resultCode;
5851354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            mIsDone = true;
5852354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        }
5853354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5854354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        public void reset() {
5855354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            mIsDone = false;
5856354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        }
5857354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    }
5858354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5859a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
58604b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testAccessShowSoftInputOnFocus() throws Throwable {
5861354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        if (!mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS)) {
5862354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            return;
5863354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        }
5864354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5865354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Scroll down to our EditText
5866354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        final ScrollView scrollView = (ScrollView) mActivity.findViewById(R.id.scroller);
5867354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mTextView = findTextView(R.id.editview_text);
58689560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> scrollView.fullScroll(View.FOCUS_DOWN));
5869354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
5870354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5871354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Mark it to show soft input on focus
58729560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setShowSoftInputOnFocus(true));
5873354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
5874354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(mTextView.getShowSoftInputOnFocus());
5875354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5876354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // And emulate click on it
58779404cdc3d439d5a2d1b805934c53a8ba6dc68fa8Andrei Stingaceanu        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mTextView);
5878354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5879354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Verify that input method manager is active and accepting text
5880354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        final InputMethodManager imManager = (InputMethodManager) mActivity
5881354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov                .getSystemService(Context.INPUT_METHOD_SERVICE);
5882b7724cefaf6067b1f6b59d3abae73828b48945c3Kirill Grouchnikov        PollingCheck.waitFor(imManager::isActive);
5883354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(imManager.isAcceptingText());
5884354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(imManager.isActive(mTextView));
5885354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5886354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Since there is no API to check that soft input is showing, we're going to ask
5887354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // the input method manager to show soft input, passing our custom result receiver.
5888354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // We're expecting to get UNCHANGED_SHOWN, indicating that the soft input was already
5889354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // showing before showSoftInput was called.
5890354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        SoftInputResultReceiver receiver = new SoftInputResultReceiver(mHandler);
5891354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        imManager.showSoftInput(mTextView, 0, receiver);
5892354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        PollingCheck.waitFor(() -> receiver.mIsDone);
5893354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(InputMethodManager.RESULT_UNCHANGED_SHOWN, receiver.mResultCode);
5894354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5895354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Close soft input
5896a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
5897354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5898354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Reconfigure our edit text to not show soft input on focus
58999560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setShowSoftInputOnFocus(false));
5900354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
5901354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertFalse(mTextView.getShowSoftInputOnFocus());
5902354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5903354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Emulate click on it
59049404cdc3d439d5a2d1b805934c53a8ba6dc68fa8Andrei Stingaceanu        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mTextView);
5905354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5906354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Ask input method manager to show soft input again. This time we're expecting to get
5907354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // SHOWN, indicating that the soft input was not showing before showSoftInput was called.
5908354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        receiver.reset();
5909354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        imManager.showSoftInput(mTextView, 0, receiver);
5910354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        PollingCheck.waitFor(() -> receiver.mIsDone);
5911354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(InputMethodManager.RESULT_SHOWN, receiver.mResultCode);
5912354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5913354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Close soft input
5914a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
5915354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    }
5916354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5917a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
59184b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testIsSuggestionsEnabled() throws Throwable {
591941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView = findTextView(R.id.textview_text);
592041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
592141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Anything without InputType.TYPE_CLASS_TEXT doesn't have suggestions enabled
59224b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> mTextView.setInputType(InputType.TYPE_CLASS_DATETIME));
592341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
592441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59254b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> mTextView.setInputType(InputType.TYPE_CLASS_PHONE));
592641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
592741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59284b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(() -> mTextView.setInputType(InputType.TYPE_CLASS_NUMBER));
592941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
593041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
593141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // From this point our text view has InputType.TYPE_CLASS_TEXT
593241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
593341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Anything with InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS doesn't have suggestions enabled
59344b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
593541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
593641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
593741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
593841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59394b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
594041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
594141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL |
594241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                                InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
594341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
594441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59454b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
594641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
594741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS |
594841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                                InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
594941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
595041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
595141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Otherwise suggestions are enabled for specific type variations enumerated in the
595241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // documentation of TextView.isSuggestionsEnabled
59534b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
595441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
595541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL));
595641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertTrue(mTextView.isSuggestionsEnabled());
595741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59584b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
595941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
596041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT));
596141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertTrue(mTextView.isSuggestionsEnabled());
596241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59634b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
596441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
596541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE));
596641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertTrue(mTextView.isSuggestionsEnabled());
596741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59684b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
596941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
597041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE));
597141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertTrue(mTextView.isSuggestionsEnabled());
597241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59734b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
597441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
597541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT));
597641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertTrue(mTextView.isSuggestionsEnabled());
597741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
597841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // and not on any other type variation
59794b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
598041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
598141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS));
598241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
598341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59844b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
598541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
598641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_FILTER));
598741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
598841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59894b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
599041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
599141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD));
599241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
599341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59944b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
599541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
599641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PERSON_NAME));
599741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
599841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
59994b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
600041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
600141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PHONETIC));
600241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
600341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
60044b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
600541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
600641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS));
600741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
600841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
60094b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
601041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
601141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI));
601241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
601341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
60144b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
601541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
601641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT |
601741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                                InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD));
601841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
601941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
60204b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
602141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
602241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT |
602341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                                InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS));
602441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
602541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
60264b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        mActivityRule.runOnUiThread(
602741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
602841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD));
602941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
603041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    }
603141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
6032a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
60334b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testAccessLetterSpacing() throws Throwable {
603441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView = findTextView(R.id.textview_text);
6035a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(0.0f, mTextView.getLetterSpacing(), 0.0f);
603641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
603741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final CharSequence text = mTextView.getText();
603841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int textLength = text.length();
603941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
604041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Get advance widths of each character at the default letter spacing
604141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final float[] initialWidths = new float[textLength];
604241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView.getPaint().getTextWidths(text.toString(), initialWidths);
604341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
604441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Get advance widths of each character at letter spacing = 1.0f
60454b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView,
604641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setLetterSpacing(1.0f));
6047a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(1.0f, mTextView.getLetterSpacing(), 0.0f);
604841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final float[] singleWidths = new float[textLength];
604941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView.getPaint().getTextWidths(text.toString(), singleWidths);
605041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
605141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Get advance widths of each character at letter spacing = 2.0f
60524b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView,
605341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setLetterSpacing(2.0f));
6054a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov        assertEquals(2.0f, mTextView.getLetterSpacing(), 0.0f);
605541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final float[] doubleWidths = new float[textLength];
605641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView.getPaint().getTextWidths(text.toString(), doubleWidths);
605741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
605841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Since letter spacing setter treats the parameter as EM units, and we don't have
605941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // a way to convert EMs into pixels, go over the three arrays of advance widths and
606041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // test that the extra advance width at letter spacing 2.0f is double the extra
606141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // advance width at letter spacing 1.0f.
606241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        for (int i = 0; i < textLength; i++) {
606341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            float singleWidthDelta = singleWidths[i] - initialWidths[i];
606441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            float doubleWidthDelta = doubleWidths[i] - initialWidths[i];
606541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            assertEquals("At index " + i + " initial is " + initialWidths[i] +
606641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                ", single is " + singleWidths[i] + " and double is " + doubleWidths[i],
606741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                    singleWidthDelta * 2.0f, doubleWidthDelta, 0.05f);
606841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        }
606941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    }
607041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
6071a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
60724b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testTextIsSelectableFocusAndOnClick() throws Throwable {
6073288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        // Prepare a focusable TextView with an onClickListener attached.
6074288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        final View.OnClickListener mockOnClickListener = mock(View.OnClickListener.class);
6075d25d1649c5d744044a0174a734e38ec22cdc7d25Andrei Stingaceanu        final int safeDoubleTapTimeout = ViewConfiguration.getDoubleTapTimeout() + 1;
60769560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
6077288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu            mTextView = new TextView(mActivity);
607852e5d256861edd0ff4f58da581b8bbd9df1c1d99Siyamed Sinir            mTextView.setText("...text 11:11. some more text is in here...");
6079288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu            mTextView.setFocusable(true);
6080288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu            mTextView.setOnClickListener(mockOnClickListener);
6081288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu            mActivity.setContentView(mTextView);
6082288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        });
6083288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
6084288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isFocusable());
6085288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isTextSelectable());
6086288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isFocusableInTouchMode());
6087288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isFocused());
6088288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isInTouchMode());
6089288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu
6090288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        // First tap on the view triggers onClick() but does not focus the TextView.
60918bd3e888824438c3bc8ae24ca8842d9248b33924Andrei Stingaceanu        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mTextView);
6092d25d1649c5d744044a0174a734e38ec22cdc7d25Andrei Stingaceanu        SystemClock.sleep(safeDoubleTapTimeout);
6093288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isInTouchMode());
6094288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isFocused());
6095288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        verify(mockOnClickListener, times(1)).onClick(mTextView);
6096288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        reset(mockOnClickListener);
6097d25d1649c5d744044a0174a734e38ec22cdc7d25Andrei Stingaceanu        // So does the second tap.
60988bd3e888824438c3bc8ae24ca8842d9248b33924Andrei Stingaceanu        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mTextView);
6099d25d1649c5d744044a0174a734e38ec22cdc7d25Andrei Stingaceanu        SystemClock.sleep(safeDoubleTapTimeout);
6100288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isInTouchMode());
6101288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isFocused());
6102288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        verify(mockOnClickListener, times(1)).onClick(mTextView);
6103288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu
61049560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setTextIsSelectable(true));
6105288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
6106288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isFocusable());
6107288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isTextSelectable());
6108288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isFocusableInTouchMode());
6109288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isFocused());
6110288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu
6111288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        // First tap on the view focuses the TextView but does not trigger onClick().
6112288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        reset(mockOnClickListener);
61138bd3e888824438c3bc8ae24ca8842d9248b33924Andrei Stingaceanu        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mTextView);
6114d25d1649c5d744044a0174a734e38ec22cdc7d25Andrei Stingaceanu        SystemClock.sleep(safeDoubleTapTimeout);
6115288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isInTouchMode());
6116288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isFocused());
6117288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        verify(mockOnClickListener, never()).onClick(mTextView);
6118288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        reset(mockOnClickListener);
6119d25d1649c5d744044a0174a734e38ec22cdc7d25Andrei Stingaceanu        // The second tap triggers onClick() and keeps the focus.
61208bd3e888824438c3bc8ae24ca8842d9248b33924Andrei Stingaceanu        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mTextView);
6121d25d1649c5d744044a0174a734e38ec22cdc7d25Andrei Stingaceanu        SystemClock.sleep(safeDoubleTapTimeout);
6122288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isInTouchMode());
6123288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isFocused());
6124288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        verify(mockOnClickListener, times(1)).onClick(mTextView);
6125288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu    }
6126288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu
612741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    private void verifyGetOffsetForPosition(final int x, final int y) {
612841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int actual = mTextView.getOffsetForPosition(x, y);
612941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
613041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final Layout layout = mTextView.getLayout();
613141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        if (layout == null) {
613241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            assertEquals("For [" + x + ", " + y + "]", -1, actual);
613341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            return;
613441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        }
613541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
613641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Get the line which corresponds to the Y position
613741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int line = layout.getLineForVertical(y + mTextView.getScrollY());
613841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Get the offset in that line that corresponds to the X position
613941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int expected = layout.getOffsetForHorizontal(line, x + mTextView.getScrollX());
614041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertEquals("For [" + x + ", " + y + "]", expected, actual);
614141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    }
614241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
6143a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
61444b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    public void testGetOffsetForPosition() throws Throwable {
614541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView = findTextView(R.id.textview_text);
61464b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView, () -> {
614741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            mTextView.setText(LONG_TEXT);
614841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            mTextView.setPadding(0, 0, 0, 0);
614941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        });
615041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
615141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertNotNull(mTextView.getLayout());
615241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int viewWidth = mTextView.getWidth();
615341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int viewHeight = mTextView.getHeight();
615441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int lineHeight = mTextView.getLineHeight();
615541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
615641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        verifyGetOffsetForPosition(0, 0);
615741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        verifyGetOffsetForPosition(0, viewHeight / 2);
615841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        verifyGetOffsetForPosition(viewWidth / 3, lineHeight / 2);
615941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        verifyGetOffsetForPosition(viewWidth / 2, viewHeight / 2);
616041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        verifyGetOffsetForPosition(viewWidth, viewHeight);
616141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    }
616241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
616357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri    @UiThreadTest
6164a75fb03266b58562af9ed30eff91f2a67d177adcKirill Grouchnikov    @Test
616557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri    public void testOnResolvePointerIcon() throws InterruptedException {
616657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final TextView selectableTextView = findTextView(R.id.textview_pointer);
616757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final MotionEvent event = createMouseHoverEvent(selectableTextView);
616857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
616957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        // A selectable view shows the I beam
617057c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        selectableTextView.setTextIsSelectable(true);
617157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
617257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT),
617357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                selectableTextView.onResolvePointerIcon(event, 0));
617457c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        selectableTextView.setTextIsSelectable(false);
617557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
617657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        // A clickable view shows the hand
617757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        selectableTextView.setLinksClickable(true);
617857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        SpannableString builder = new SpannableString("hello world");
617957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        selectableTextView.setText(builder, BufferType.SPANNABLE);
618057c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        Spannable text = (Spannable) selectableTextView.getText();
618157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        text.setSpan(
618257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                new ClickableSpan() {
618357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                    @Override
618457c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                    public void onClick(View widget) {
618557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
618657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                    }
618757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                }, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
618857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
618957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_HAND),
619057c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                selectableTextView.onResolvePointerIcon(event, 0));
619157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
619257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        // A selectable & clickable view shows hand
619357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        selectableTextView.setTextIsSelectable(true);
619457c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
619557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_HAND),
619657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                selectableTextView.onResolvePointerIcon(event, 0));
619757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
619857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        // An editable view shows the I-beam
619957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final TextView editableTextView = new EditText(mActivity);
620057c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
620157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT),
620257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                editableTextView.onResolvePointerIcon(event, 0));
620357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri    }
620457c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
62059560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @Test
62066b02e92df9486b4b1723473987bf025dcd18a23dAndrei Stingaceanu    public void testClickableSpanOnClickSingleTapInside() throws Throwable {
62079560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ClickableSpanTestDetails spanDetails = prepareAndRetrieveClickableSpanDetails();
62089560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        CtsTouchUtils.emulateTapOnView(mInstrumentation, mTextView, spanDetails.mXPosInside,
62099560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                spanDetails.mYPosInside);
62109560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        SystemClock.sleep(ViewConfiguration.getDoubleTapTimeout() + 1);
62119560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(spanDetails.mClickableSpan, times(1)).onClick(mTextView);
62129560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    }
62139560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
62149560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @Test
62156b02e92df9486b4b1723473987bf025dcd18a23dAndrei Stingaceanu    public void testClickableSpanOnClickDoubleTapInside() throws Throwable {
62169560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ClickableSpanTestDetails spanDetails = prepareAndRetrieveClickableSpanDetails();
62179560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        CtsTouchUtils.emulateDoubleTapOnView(mInstrumentation, mTextView, spanDetails.mXPosInside,
62189560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                spanDetails.mYPosInside);
62199560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(spanDetails.mClickableSpan, never()).onClick(mTextView);
62209560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    }
62219560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
62229560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @Test
62236b02e92df9486b4b1723473987bf025dcd18a23dAndrei Stingaceanu    public void testClickableSpanOnClickSingleTapOutside() throws Throwable {
62249560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ClickableSpanTestDetails spanDetails = prepareAndRetrieveClickableSpanDetails();
62259560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        CtsTouchUtils.emulateTapOnView(mInstrumentation, mTextView, spanDetails.mXPosOutside,
62269560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                spanDetails.mYPosOutside);
62279560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        SystemClock.sleep(ViewConfiguration.getDoubleTapTimeout() + 1);
62289560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(spanDetails.mClickableSpan, never()).onClick(mTextView);
62299560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    }
62309560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
62319560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @Test
62326b02e92df9486b4b1723473987bf025dcd18a23dAndrei Stingaceanu    public void testClickableSpanOnClickDragOutside() throws Throwable {
62339560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ClickableSpanTestDetails spanDetails = prepareAndRetrieveClickableSpanDetails();
62349560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final int[] viewOnScreenXY = new int[2];
62359560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.getLocationOnScreen(viewOnScreenXY);
62369560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
62379560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        SparseArray<Point> swipeCoordinates = new SparseArray<>();
62389560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        swipeCoordinates.put(0, new Point(viewOnScreenXY[0] + spanDetails.mXPosOutside,
62399560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                viewOnScreenXY[1] + spanDetails.mYPosOutside));
62409560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        swipeCoordinates.put(1, new Point(viewOnScreenXY[0] + spanDetails.mXPosOutside + 50,
62419560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                viewOnScreenXY[1] + spanDetails.mYPosOutside + 50));
62429560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        CtsTouchUtils.emulateDragGesture(mInstrumentation, swipeCoordinates);
62439560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(spanDetails.mClickableSpan, never()).onClick(mTextView);
62449560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    }
62459560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
62469560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @Test
62476b02e92df9486b4b1723473987bf025dcd18a23dAndrei Stingaceanu    public void testClickableSpanOnClickDragInsideFromOutside() throws Throwable {
62489560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ClickableSpanTestDetails spanDetails = prepareAndRetrieveClickableSpanDetails();
62499560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final int[] viewOnScreenXY = new int[2];
62509560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.getLocationOnScreen(viewOnScreenXY);
62519560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
62529560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        SparseArray<Point> swipeCoordinates = new SparseArray<>();
62539560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        swipeCoordinates.put(0, new Point(viewOnScreenXY[0] + spanDetails.mXPosOutside,
62549560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                viewOnScreenXY[1] + spanDetails.mYPosOutside));
62559560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        swipeCoordinates.put(1, new Point(viewOnScreenXY[0] + spanDetails.mXPosInside,
62569560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                viewOnScreenXY[1] + spanDetails.mYPosInside));
62579560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        CtsTouchUtils.emulateDragGesture(mInstrumentation, swipeCoordinates);
62589560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(spanDetails.mClickableSpan, never()).onClick(mTextView);
62599560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    }
62609560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
62619560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @Test
62626b02e92df9486b4b1723473987bf025dcd18a23dAndrei Stingaceanu    public void testClickableSpanOnClickDragInsideOutsideInside() throws Throwable {
62639560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ClickableSpanTestDetails spanDetails = prepareAndRetrieveClickableSpanDetails();
62649560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final int[] viewOnScreenXY = new int[2];
62659560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mTextView.getLocationOnScreen(viewOnScreenXY);
62669560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
62679560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        // Drag outside from within the clickable span and come back within the clickable span
62689560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        // (without lifting the finger)
62699560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        SparseArray<Point> swipeCoordinates = new SparseArray<>();
62709560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        swipeCoordinates.put(0, new Point(viewOnScreenXY[0] + spanDetails.mXPosInside,
62719560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                viewOnScreenXY[1] + spanDetails.mYPosInside));
62729560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        swipeCoordinates.put(1, new Point(viewOnScreenXY[0] + spanDetails.mXPosOutside,
62739560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                viewOnScreenXY[1] + spanDetails.mYPosOutside));
62749560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        swipeCoordinates.put(2, new Point(viewOnScreenXY[0] + spanDetails.mXPosInside,
62759560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                viewOnScreenXY[1] + spanDetails.mYPosInside));
62769560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        CtsTouchUtils.emulateDragGesture(mInstrumentation, swipeCoordinates);
62779560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(spanDetails.mClickableSpan, never()).onClick(mTextView);
62789560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    }
62799560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
62809560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    @Test
62816b02e92df9486b4b1723473987bf025dcd18a23dAndrei Stingaceanu    public void testClickableSpanOnClickLongPress() throws Throwable {
62829560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ClickableSpanTestDetails spanDetails = prepareAndRetrieveClickableSpanDetails();
62839560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        CtsTouchUtils.emulateLongPressOnView(mInstrumentation, mTextView, spanDetails.mXPosInside,
62849560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                spanDetails.mYPosInside);
62859560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        verify(spanDetails.mClickableSpan, never()).onClick(mTextView);
62869560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    }
62879560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
62885b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu    @Test
62895b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu    public void testAutoSizeXY_obtainStyledAttributes() {
62905b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu        DisplayMetrics metrics = mActivity.getResources().getDisplayMetrics();
62915b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu        TextView autoSizeTextViewXY = (TextView) mActivity.findViewById(R.id.textview_autosize_xy);
62925b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu
62935b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu        // The size has been set to 50dp in the layout but this being an AUTO_SIZE_TYPE_XY TextView,
62945b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu        // the size is considered max size thus the value returned by getSize() in this case should
62955b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu        // be lower than the one set (given that there is not much available space and the font size
62965b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu        // is very high). In theory the values could be equal for a different TextView
62975b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu        // configuration.
62985b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu        final float sizeSetInPixels = TypedValue.applyDimension(
62995b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu                TypedValue.COMPLEX_UNIT_DIP, 50f, metrics);
63005b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu        assertTrue(autoSizeTextViewXY.getTextSize() < sizeSetInPixels);
63015b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu    }
63025b44d230a4e966f12488126d75b1c0ea57072748Andrei Stingaceanu
63039560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    /**
63049560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu     * Removes all existing views from the layout and adds a basic TextView (for exercising the
63059560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu     * ClickableSpan onClick() behavior) in order to prevent scrolling. Adds a ClickableSpan to the
63069560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu     * TextView and returns the ClickableSpan and position details about it to be used in individual
63079560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu     * tests.
63089560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu     */
63096b02e92df9486b4b1723473987bf025dcd18a23dAndrei Stingaceanu    private ClickableSpanTestDetails prepareAndRetrieveClickableSpanDetails() throws Throwable {
63106b02e92df9486b4b1723473987bf025dcd18a23dAndrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
63119560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            LinearLayout ll = (LinearLayout) mActivity.findViewById(R.id.layout_textviewtest);
63129560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            ll.removeAllViews();
63139560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView = new TextView(mActivity);
63149560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            ll.addView(mTextView);
63159560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        });
63169560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
63179560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
63189560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ClickableSpan mockTextLink = mock(ClickableSpan.class);
63199560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        StringBuilder textViewContent = new StringBuilder();
63209560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        String clickableString = "clickMe!";
63219560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        textViewContent.append(clickableString);
63229560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final int startPos = 0;
63239560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
63249560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        // Insert more characters to make some room for swiping.
63259560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        for (int i = 0; i < 200; i++) {
63269560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            textViewContent.append(" text");
63279560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        }
63289560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        SpannableString spannableString = new SpannableString(textViewContent);
63299560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        final int endPos = clickableString.length();
63309560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        spannableString.setSpan(mockTextLink, startPos, endPos, 0);
63316b02e92df9486b4b1723473987bf025dcd18a23dAndrei Stingaceanu        mActivityRule.runOnUiThread(() -> {
63329560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setText(spannableString);
63339560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mTextView.setMovementMethod(LinkMovementMethod.getInstance());
63349560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        });
63359560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
63369560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
63379560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        return new ClickableSpanTestDetails(mockTextLink, mTextView, startPos, endPos);
63389560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    }
63399560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
63409560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    private static final class ClickableSpanTestDetails {
63419560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ClickableSpan mClickableSpan;
63429560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        int mXPosInside;
63439560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        int mYPosInside;
63449560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        int mXPosOutside;
63459560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        int mYPosOutside;
63469560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
63479560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        private int mStartCharPos;
63489560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        private int mEndCharPos;
63499560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        private TextView mParent;
63509560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
63519560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        ClickableSpanTestDetails(ClickableSpan clickableSpan, TextView parent,
63529560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu                int startCharPos, int endCharPos) {
63539560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mClickableSpan = clickableSpan;
63549560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mParent = parent;
63559560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mStartCharPos = startCharPos;
63569560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mEndCharPos = endCharPos;
63579560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
63589560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            calculatePositions();
63599560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        }
63609560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
63619560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        private void calculatePositions() {
63629560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            int xStart = (int) mParent.getLayout().getPrimaryHorizontal(mStartCharPos, true);
63639560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            int xEnd = (int) mParent.getLayout().getPrimaryHorizontal(mEndCharPos, true);
63649560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            int line = mParent.getLayout().getLineForOffset(mEndCharPos);
63659560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            int yTop = mParent.getLayout().getLineTop(line);
63669560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            int yBottom = mParent.getLayout().getLineBottom(line);
63679560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
63689560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mXPosInside = (xStart + xEnd) / 2;
63699560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mYPosInside = (yTop + yBottom) / 2;
63709560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mXPosOutside = xEnd + 1;
63719560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu            mYPosOutside = yBottom + 1;
63729560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        }
63739560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    }
63749560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu
637557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri    private MotionEvent createMouseHoverEvent(View view) {
637657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final int[] xy = new int[2];
637757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        view.getLocationOnScreen(xy);
637857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final int viewWidth = view.getWidth();
637957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final int viewHeight = view.getHeight();
638057c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        float x = xy[0] + viewWidth / 2.0f;
638157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        float y = xy[1] + viewHeight / 2.0f;
638257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        long eventTime = SystemClock.uptimeMillis();
638357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[1];
638457c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        pointerCoords[0] = new MotionEvent.PointerCoords();
638557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        pointerCoords[0].x = x;
638657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        pointerCoords[0].y = y;
638757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final int[] pointerIds = new int[1];
638857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        pointerIds[0] = 0;
638957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        return MotionEvent.obtain(0, eventTime, MotionEvent.ACTION_HOVER_MOVE, 1, pointerIds,
639057c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                pointerCoords, 0, 0, 0, 0, 0, InputDevice.SOURCE_MOUSE, 0);
639157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri    }
639257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
63939560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    private void layout(final TextView textView) throws Throwable {
63949560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mActivity.setContentView(textView));
6395fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6396fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6397fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
63989560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    private void layout(final int layoutId) throws Throwable {
63999560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mActivity.setContentView(layoutId));
6400fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6401fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6402fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6403fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private TextView findTextView(int id) {
6404fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        return (TextView) mActivity.findViewById(id);
6405fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6406fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6407fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private int getAutoLinkMask(int id) {
6408fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        return findTextView(id).getAutoLinkMask();
6409fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6410fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64119560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    private void setMaxLines(final int lines) throws Throwable {
64129560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setMaxLines(lines));
64136a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mInstrumentation.waitForIdleSync();
64146a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
64156a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
64169560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    private void setMaxWidth(final int pixels) throws Throwable {
64179560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setMaxWidth(pixels));
6418fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6419fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6420fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64219560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    private void setMinWidth(final int pixels) throws Throwable {
64229560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setMinWidth(pixels));
6423fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6424fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6425fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64269560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    private void setMaxHeight(final int pixels) throws Throwable {
64279560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setMaxHeight(pixels));
6428fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6429fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6430fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64319560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    private void setMinHeight(final int pixels) throws Throwable {
64329560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setMinHeight(pixels));
6433fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6434fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6435fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64369560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    private void setMinLines(final int minLines) throws Throwable {
64379560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setMinLines(minLines));
6438fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6439fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6440fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6441fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    /**
6442fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     * Convenience for {@link TextView#setText(CharSequence, BufferType)}. And
6443fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     * the buffer type is fixed to SPANNABLE.
6444fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     *
6445fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     * @param tv the text view
6446fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     * @param content the content
6447fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     */
64489560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu    private void setSpannableText(final TextView tv, final String content) throws Throwable {
64499560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> tv.setText(content, BufferType.SPANNABLE));
6450fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6451fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6452fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64534b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    private void setLines(final int lines) throws Throwable {
64549560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setLines(lines));
6455fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6456fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6457fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64584b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    private void setHorizontallyScrolling(final boolean whether) throws Throwable {
64599560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setHorizontallyScrolling(whether));
6460fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6461fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6462fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64634b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    private void setWidth(final int pixels) throws Throwable {
64649560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setWidth(pixels));
6465fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6466fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6467fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64684b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    private void setHeight(final int pixels) throws Throwable {
64699560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setHeight(pixels));
6470fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6471fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6472fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64734b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    private void setMinEms(final int ems) throws Throwable {
64749560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setMinEms(ems));
6475fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6476fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6477fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64784b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    private void setMaxEms(final int ems) throws Throwable {
64799560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setMaxEms(ems));
6480fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6481fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6482fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64834b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    private void setEms(final int ems) throws Throwable {
64849560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setEms(ems));
6485fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6486fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6487fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
64884b645d615abed9d92ce586a135ad0c8f2e08bd48Kirill Grouchnikov    private void setLineSpacing(final float add, final float mult) throws Throwable {
64899560fd0bff8ebc15f71898067d514cf1e2d3ad09Andrei Stingaceanu        mActivityRule.runOnUiThread(() -> mTextView.setLineSpacing(add, mult));
6490fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
6491fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6492fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6493fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private static abstract class TestSelectedRunnable implements Runnable {
6494fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private TextView mTextView;
6495fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private boolean mIsSelected1;
6496fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private boolean mIsSelected2;
6497fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6498fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public TestSelectedRunnable(TextView textview) {
6499fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView = textview;
6500fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6501fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6502fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public boolean getIsSelected1() {
6503fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mIsSelected1;
6504fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6505fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6506fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public boolean getIsSelected2() {
6507fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mIsSelected2;
6508fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6509fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6510fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void saveIsSelected1() {
6511fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mIsSelected1 = mTextView.isSelected();
6512fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6513fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6514fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void saveIsSelected2() {
6515fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mIsSelected2 = mTextView.isSelected();
6516fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6517fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6518fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6519fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private static abstract class TestLayoutRunnable implements Runnable {
6520fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private TextView mTextView;
6521fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private Layout mLayout;
6522fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6523fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public TestLayoutRunnable(TextView textview) {
6524fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView = textview;
6525fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6526fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6527fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public Layout getLayout() {
6528fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mLayout;
6529fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6530fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6531fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void saveLayout() {
6532fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mLayout = mTextView.getLayout();
6533fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6534fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6535fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6536fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private static class MockTextWatcher implements TextWatcher {
6537fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private boolean mHasCalledAfterTextChanged;
6538fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private boolean mHasCalledBeforeTextChanged;
6539fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private boolean mHasOnTextChanged;
6540fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6541fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void reset(){
6542fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasCalledAfterTextChanged = false;
6543fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasCalledBeforeTextChanged = false;
6544fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasOnTextChanged = false;
6545fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6546fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6547fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public boolean hasCalledAfterTextChanged() {
6548fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mHasCalledAfterTextChanged;
6549fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6550fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6551fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public boolean hasCalledBeforeTextChanged() {
6552fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mHasCalledBeforeTextChanged;
6553fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6554fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6555fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public boolean hasCalledOnTextChanged() {
6556fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mHasOnTextChanged;
6557fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6558fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6559fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void afterTextChanged(Editable s) {
6560fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasCalledAfterTextChanged = true;
6561fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6562fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6563fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
6564fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasCalledBeforeTextChanged = true;
6565fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6566fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6567fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void onTextChanged(CharSequence s, int start, int before, int count) {
6568fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasOnTextChanged = true;
6569fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6570fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6571fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6572fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    /**
6573277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook     * A TextWatcher that converts the text to spaces whenever the text changes.
6574277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook     */
6575277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    private static class ConvertToSpacesTextWatcher implements TextWatcher {
6576277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        boolean mChangingText;
6577277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
6578277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        @Override
6579277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
6580277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        }
6581277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
6582277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        @Override
6583277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        public void onTextChanged(CharSequence s, int start, int before, int count) {
6584277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        }
6585277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
6586277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        @Override
6587277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        public void afterTextChanged(Editable s) {
6588277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            // Avoid infinite recursion.
6589277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            if (mChangingText) {
6590277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook                return;
6591277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            }
6592277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            mChangingText = true;
6593277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            // Create a string of s.length() spaces.
6594277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            StringBuilder builder = new StringBuilder(s.length());
6595277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            for (int i = 0; i < s.length(); i++) {
6596277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook                builder.append(' ');
6597277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            }
6598277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            s.replace(0, s.length(), builder.toString());
6599277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            mChangingText = false;
6600277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        }
6601277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    }
6602fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su}
6603