• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.xtremelabs.robolectric.shadows;
2 
3 import android.app.Activity;
4 import android.graphics.Typeface;
5 import android.text.*;
6 import android.text.method.ArrowKeyMovementMethod;
7 import android.text.method.MovementMethod;
8 import android.text.style.URLSpan;
9 import android.view.Gravity;
10 import android.view.KeyEvent;
11 import android.view.MotionEvent;
12 import android.view.inputmethod.EditorInfo;
13 import android.widget.TextView;
14 import com.xtremelabs.robolectric.R;
15 import com.xtremelabs.robolectric.Robolectric;
16 import com.xtremelabs.robolectric.WithTestDefaultsRunner;
17 import junit.framework.Assert;
18 import org.hamcrest.CoreMatchers;
19 import org.junit.Before;
20 import org.junit.Test;
21 import org.junit.runner.RunWith;
22 
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Random;
26 
27 import static com.xtremelabs.robolectric.Robolectric.shadowOf;
28 import static java.util.Arrays.asList;
29 import static junit.framework.Assert.assertFalse;
30 import static org.hamcrest.CoreMatchers.*;
31 import static org.junit.Assert.*;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.verify;
34 
35 @RunWith(WithTestDefaultsRunner.class)
36 public class TextViewTest {
37 
38     private static final String INITIAL_TEXT = "initial text";
39     private static final String NEW_TEXT = "new text";
40     private TextView textView;
41 
42     @Before
setUp()43     public void setUp() throws Exception {
44         textView = new TextView(new Activity());
45     }
46 
47     @Test
shouldTriggerTheImeListener()48     public void shouldTriggerTheImeListener() {
49         TextView textView = new TextView(null);
50         TestOnEditorActionListener actionListener = new TestOnEditorActionListener();
51         textView.setOnEditorActionListener(actionListener);
52 
53         shadowOf(textView).triggerEditorAction(EditorInfo.IME_ACTION_GO);
54 
55         assertThat(actionListener.textView, is(textView));
56         assertThat(actionListener.sentImeId, equalTo(EditorInfo.IME_ACTION_GO));
57     }
58 
59     @Test
testGetUrls()60     public void testGetUrls() throws Exception {
61         textView.setText("here's some text http://google.com/\nblah\thttp://another.com/123?456 blah");
62 
63         assertThat(urlStringsFrom(textView.getUrls()), equalTo(asList(
64                 "http://google.com/",
65                 "http://another.com/123?456"
66         )));
67     }
68 
69     @Test
testGetGravity()70     public void testGetGravity() throws Exception {
71         assertThat(textView.getGravity(), not(equalTo(Gravity.CENTER)));
72         textView.setGravity(Gravity.CENTER);
73         assertThat(textView.getGravity(), equalTo(Gravity.CENTER));
74     }
75 
76     @Test
testMovementMethod()77     public void testMovementMethod() {
78         MovementMethod movement = new ArrowKeyMovementMethod();
79 
80         assertNull(textView.getMovementMethod());
81         textView.setMovementMethod(movement);
82         assertThat(textView.getMovementMethod(), sameInstance(movement));
83     }
84 
85     @Test
testLinksClickable()86     public void testLinksClickable() {
87         assertThat(textView.getLinksClickable(), equalTo(false));
88 
89         textView.setLinksClickable(true);
90         assertThat(textView.getLinksClickable(), equalTo(true));
91 
92         textView.setLinksClickable(false);
93         assertThat(textView.getLinksClickable(), equalTo(false));
94     }
95 
96     @Test
testGetTextAppearanceId()97     public void testGetTextAppearanceId() throws Exception {
98         TextView textView = new TextView(null);
99         textView.setTextAppearance(null, 5);
100 
101         assertThat(shadowOf(textView).getTextAppearanceId(), equalTo(5));
102     }
103 
104     @Test
shouldSetTextAndTextColorWhileInflatingXmlLayout()105     public void shouldSetTextAndTextColorWhileInflatingXmlLayout() throws Exception {
106         Activity activity = new Activity();
107         activity.setContentView(R.layout.text_views);
108 
109         TextView black = (TextView) activity.findViewById(R.id.black_text_view);
110         assertThat(black.getText().toString(), equalTo("Black Text"));
111         assertThat(shadowOf(black).getTextColorHexValue(), equalTo(0));
112 
113         TextView white = (TextView) activity.findViewById(R.id.white_text_view);
114         assertThat(white.getText().toString(), equalTo("White Text"));
115         assertThat(shadowOf(white).getTextColorHexValue(), equalTo(activity.getResources().getColor(android.R.color.white)));
116 
117         TextView grey = (TextView) activity.findViewById(R.id.grey_text_view);
118         assertThat(grey.getText().toString(), equalTo("Grey Text"));
119         assertThat(shadowOf(grey).getTextColorHexValue(), equalTo(activity.getResources().getColor(R.color.grey42)));
120     }
121 
122     @Test
shouldSetHintAndHintColorWhileInflatingXmlLayout()123     public void shouldSetHintAndHintColorWhileInflatingXmlLayout() throws Exception {
124         Activity activity = new Activity();
125         activity.setContentView(R.layout.text_views_hints);
126 
127         TextView black = (TextView) activity.findViewById(R.id.black_text_view_hint);
128         assertThat(black.getHint().toString(), equalTo("Black Hint"));
129         assertThat(shadowOf(black).getHintColorHexValue(), equalTo(0));
130 
131         TextView white = (TextView) activity.findViewById(R.id.white_text_view_hint);
132         assertThat(white.getHint().toString(), equalTo("White Hint"));
133         assertThat(shadowOf(white).getHintColorHexValue(), equalTo(activity.getResources().getColor(android.R.color.white)));
134 
135         TextView grey = (TextView) activity.findViewById(R.id.grey_text_view_hint);
136         assertThat(grey.getHint().toString(), equalTo("Grey Hint"));
137         assertThat(shadowOf(grey).getHintColorHexValue(), equalTo(activity.getResources().getColor(R.color.grey42)));
138     }
139 
140     @Test
shouldNotHaveTransformationMethodByDefault()141     public void shouldNotHaveTransformationMethodByDefault() {
142         ShadowTextView view = new ShadowTextView();
143         assertThat(view.getTransformationMethod(), is(CoreMatchers.<Object>nullValue()));
144     }
145 
146     @Test
shouldAllowSettingATransformationMethod()147     public void shouldAllowSettingATransformationMethod() {
148         ShadowTextView view = new ShadowTextView();
149         view.setTransformationMethod(new ShadowPasswordTransformationMethod());
150         assertEquals(view.getTransformationMethod().getClass(), ShadowPasswordTransformationMethod.class);
151     }
152 
153     @Test
testGetInputType()154     public void testGetInputType() throws Exception {
155         assertThat(textView.getInputType(), not(equalTo(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD)));
156         textView.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
157         assertThat(textView.getInputType(), equalTo(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD));
158     }
159 
160     @Test
givenATextViewWithATextWatcherAdded_WhenSettingTextWithTextResourceId_ShouldNotifyTextWatcher()161     public void givenATextViewWithATextWatcherAdded_WhenSettingTextWithTextResourceId_ShouldNotifyTextWatcher() {
162         MockTextWatcher mockTextWatcher = new MockTextWatcher();
163         textView.addTextChangedListener(mockTextWatcher);
164 
165         textView.setText(R.string.hello);
166 
167         assertEachTextWatcherEventWasInvoked(mockTextWatcher);
168     }
169 
170     @Test
givenATextViewWithATextWatcherAdded_WhenSettingTextWithCharSequence_ShouldNotifyTextWatcher()171     public void givenATextViewWithATextWatcherAdded_WhenSettingTextWithCharSequence_ShouldNotifyTextWatcher() {
172         MockTextWatcher mockTextWatcher = new MockTextWatcher();
173         textView.addTextChangedListener(mockTextWatcher);
174 
175         textView.setText("text");
176 
177         assertEachTextWatcherEventWasInvoked(mockTextWatcher);
178     }
179 
180     @Test
givenATextViewWithATextWatcherAdded_WhenSettingNullText_ShouldNotifyTextWatcher()181     public void givenATextViewWithATextWatcherAdded_WhenSettingNullText_ShouldNotifyTextWatcher() {
182         MockTextWatcher mockTextWatcher = new MockTextWatcher();
183         textView.addTextChangedListener(mockTextWatcher);
184 
185         textView.setText(null);
186 
187         assertEachTextWatcherEventWasInvoked(mockTextWatcher);
188     }
189 
190     @Test
givenATextViewWithMultipleTextWatchersAdded_WhenSettingText_ShouldNotifyEachTextWatcher()191     public void givenATextViewWithMultipleTextWatchersAdded_WhenSettingText_ShouldNotifyEachTextWatcher() {
192         List<MockTextWatcher> mockTextWatchers = anyNumberOfTextWatchers();
193         for (MockTextWatcher textWatcher : mockTextWatchers) {
194             textView.addTextChangedListener(textWatcher);
195         }
196 
197         textView.setText("text");
198 
199         for (MockTextWatcher textWatcher : mockTextWatchers) {
200             assertEachTextWatcherEventWasInvoked(textWatcher);
201         }
202     }
203 
204     @Test
whenSettingText_ShouldFireBeforeTextChangedWithCorrectArguments()205     public void whenSettingText_ShouldFireBeforeTextChangedWithCorrectArguments() {
206         textView.setText(INITIAL_TEXT);
207         TextWatcher mockTextWatcher = mock(TextWatcher.class);
208         textView.addTextChangedListener(mockTextWatcher);
209 
210         textView.setText(NEW_TEXT);
211 
212         verify(mockTextWatcher).beforeTextChanged(INITIAL_TEXT, 0, INITIAL_TEXT.length(), NEW_TEXT.length());
213     }
214 
215     @Test
whenSettingText_ShouldFireOnTextChangedWithCorrectArguments()216     public void whenSettingText_ShouldFireOnTextChangedWithCorrectArguments() {
217         textView.setText(INITIAL_TEXT);
218         TextWatcher mockTextWatcher = mock(TextWatcher.class);
219         textView.addTextChangedListener(mockTextWatcher);
220 
221         textView.setText(NEW_TEXT);
222 
223         verify(mockTextWatcher).onTextChanged(NEW_TEXT, 0, INITIAL_TEXT.length(), NEW_TEXT.length());
224     }
225 
226     @Test
whenSettingText_ShouldFireAfterTextChangedWithCorrectArgument()227     public void whenSettingText_ShouldFireAfterTextChangedWithCorrectArgument() {
228         MockTextWatcher mockTextWatcher = new MockTextWatcher();
229         textView.addTextChangedListener(mockTextWatcher);
230 
231         textView.setText(NEW_TEXT);
232 
233         assertThat(mockTextWatcher.afterTextChangeArgument.toString(), equalTo(NEW_TEXT));
234     }
235 
236     @Test
whenAppendingText_ShouldAppendNewTextAfterOldOne()237     public void whenAppendingText_ShouldAppendNewTextAfterOldOne() {
238         textView.setText(INITIAL_TEXT);
239         textView.append(NEW_TEXT);
240 
241         assertEquals(INITIAL_TEXT + NEW_TEXT, textView.getText());
242     }
243 
244     @Test
whenAppendingText_ShouldFireBeforeTextChangedWithCorrectArguments()245     public void whenAppendingText_ShouldFireBeforeTextChangedWithCorrectArguments() {
246         textView.setText(INITIAL_TEXT);
247         TextWatcher mockTextWatcher = mock(TextWatcher.class);
248         textView.addTextChangedListener(mockTextWatcher);
249 
250         textView.append(NEW_TEXT);
251 
252         verify(mockTextWatcher).beforeTextChanged(INITIAL_TEXT, 0, INITIAL_TEXT.length(), INITIAL_TEXT.length() + NEW_TEXT.length());
253     }
254 
255     @Test
whenAppendingText_ShouldFireOnTextChangedWithCorrectArguments()256     public void whenAppendingText_ShouldFireOnTextChangedWithCorrectArguments() {
257         textView.setText(INITIAL_TEXT);
258         TextWatcher mockTextWatcher = mock(TextWatcher.class);
259         textView.addTextChangedListener(mockTextWatcher);
260 
261         textView.append(NEW_TEXT);
262 
263         verify(mockTextWatcher).onTextChanged(INITIAL_TEXT + NEW_TEXT, 0, INITIAL_TEXT.length(), INITIAL_TEXT.length() + NEW_TEXT.length());
264     }
265 
266     @Test
whenAppendingText_ShouldFireAfterTextChangedWithCorrectArgument()267     public void whenAppendingText_ShouldFireAfterTextChangedWithCorrectArgument() {
268         textView.setText(INITIAL_TEXT);
269         MockTextWatcher mockTextWatcher = new MockTextWatcher();
270         textView.addTextChangedListener(mockTextWatcher);
271 
272         textView.append(NEW_TEXT);
273 
274         assertThat(mockTextWatcher.afterTextChangeArgument.toString(), equalTo(INITIAL_TEXT + NEW_TEXT));
275     }
276 
277     @Test
removeTextChangedListener_shouldRemoveTheListener()278     public void removeTextChangedListener_shouldRemoveTheListener() throws Exception {
279         MockTextWatcher watcher = new MockTextWatcher();
280         textView.addTextChangedListener(watcher);
281         assertTrue(shadowOf(textView).getWatchers().contains(watcher));
282 
283         textView.removeTextChangedListener(watcher);
284         assertFalse(shadowOf(textView).getWatchers().contains(watcher));
285     }
286 
287     @Test
getPaint_returnsMeasureTextEnabledObject()288     public void getPaint_returnsMeasureTextEnabledObject() throws Exception {
289         assertThat(textView.getPaint().measureText("12345"), equalTo(5f));
290     }
291 
292     @Test
append_whenSelectionIsAtTheEnd_shouldKeepSelectionAtTheEnd()293     public void append_whenSelectionIsAtTheEnd_shouldKeepSelectionAtTheEnd() throws Exception {
294         textView.setText("1");
295         shadowOf(textView).setSelection(0, 0);
296         textView.append("2");
297         assertEquals(0, textView.getSelectionEnd());
298         assertEquals(0, textView.getSelectionStart());
299 
300         shadowOf(textView).setSelection(2, 2);
301         textView.append("3");
302         assertEquals(3, textView.getSelectionEnd());
303         assertEquals(3, textView.getSelectionStart());
304     }
305 
306     @Test
append_whenSelectionReachesToEnd_shouldExtendSelectionToTheEnd()307     public void append_whenSelectionReachesToEnd_shouldExtendSelectionToTheEnd() throws Exception {
308         textView.setText("12");
309         shadowOf(textView).setSelection(0, 2);
310         textView.append("3");
311         assertEquals(3, textView.getSelectionEnd());
312         assertEquals(0, textView.getSelectionStart());
313     }
314 
315     @Test
testSetCompountDrawablesWithIntrinsicBounds_int_shouldCreateDrawablesWithResourceIds()316     public void testSetCompountDrawablesWithIntrinsicBounds_int_shouldCreateDrawablesWithResourceIds() throws Exception {
317         textView.setCompoundDrawablesWithIntrinsicBounds(6, 7, 8, 9);
318 
319         Assert.assertEquals(6, shadowOf(textView.getCompoundDrawables()[0]).getLoadedFromResourceId());
320         Assert.assertEquals(7, shadowOf(textView.getCompoundDrawables()[1]).getLoadedFromResourceId());
321         Assert.assertEquals(8, shadowOf(textView.getCompoundDrawables()[2]).getLoadedFromResourceId());
322         Assert.assertEquals(9, shadowOf(textView.getCompoundDrawables()[3]).getLoadedFromResourceId());
323     }
324 
325     @Test
testSetCompountDrawablesWithIntrinsicBounds_int_shouldNotCreateDrawablesForZero()326     public void testSetCompountDrawablesWithIntrinsicBounds_int_shouldNotCreateDrawablesForZero() throws Exception {
327         textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
328 
329         Assert.assertNull(textView.getCompoundDrawables()[0]);
330         Assert.assertNull(textView.getCompoundDrawables()[1]);
331         Assert.assertNull(textView.getCompoundDrawables()[2]);
332         Assert.assertNull(textView.getCompoundDrawables()[3]);
333     }
334 
335     @Test
canSetAndGetTypeface()336     public void canSetAndGetTypeface() throws Exception {
337         Typeface typeface = Robolectric.newInstanceOf(Typeface.class);
338         textView.setTypeface(typeface);
339         Assert.assertEquals(typeface, textView.getTypeface());
340     }
341 
342     @Test
onTouchEvent_shouldCallMovementMethodOnTouchEventWithSetMotionEvent()343     public void onTouchEvent_shouldCallMovementMethodOnTouchEventWithSetMotionEvent() throws Exception {
344         TestMovementMethod testMovementMethod = new TestMovementMethod();
345 
346         textView.setMovementMethod(testMovementMethod);
347         MotionEvent event = MotionEvent.obtain(0, 0, 0, 0, 0, 0);
348         textView.dispatchTouchEvent(event);
349 
350         assertEquals(testMovementMethod.event, event);
351     }
352 
353     @Test
canSetAndGetLayout()354     public void canSetAndGetLayout() throws Exception {
355         StaticLayout layout = new StaticLayout(null, null, 0, null, 0, 0, true);
356         shadowOf(textView).setLayout(layout);
357         assertEquals(textView.getLayout(), layout);
358     }
359 
360     @Test
testGetError()361     public void testGetError() {
362       assertNull(textView.getError());
363       CharSequence error = "myError";
364       textView.setError(error);
365       assertEquals(error, textView.getError());
366     }
367 
anyNumberOfTextWatchers()368     private List<MockTextWatcher> anyNumberOfTextWatchers() {
369         List<MockTextWatcher> mockTextWatchers = new ArrayList<MockTextWatcher>();
370         int numberBetweenOneAndTen = new Random().nextInt(10) + 1;
371         for (int i = 0; i < numberBetweenOneAndTen; i++) {
372             mockTextWatchers.add(new MockTextWatcher());
373         }
374         return mockTextWatchers;
375     }
376 
assertEachTextWatcherEventWasInvoked(MockTextWatcher mockTextWatcher)377     private void assertEachTextWatcherEventWasInvoked(MockTextWatcher mockTextWatcher) {
378         assertTrue("Expected each TextWatcher event to have been invoked once", mockTextWatcher.methodsCalled.size() == 3);
379 
380         assertThat(mockTextWatcher.methodsCalled.get(0), equalTo("beforeTextChanged"));
381         assertThat(mockTextWatcher.methodsCalled.get(1), equalTo("onTextChanged"));
382         assertThat(mockTextWatcher.methodsCalled.get(2), equalTo("afterTextChanged"));
383     }
384 
urlStringsFrom(URLSpan[] urlSpans)385     private List<String> urlStringsFrom(URLSpan[] urlSpans) {
386         List<String> urls = new ArrayList<String>();
387         for (URLSpan urlSpan : urlSpans) {
388             urls.add(urlSpan.getURL());
389         }
390         return urls;
391     }
392 
393     private static class TestOnEditorActionListener implements TextView.OnEditorActionListener {
394         private TextView textView;
395         private int sentImeId;
396 
397         @Override
onEditorAction(TextView textView, int sentImeId, KeyEvent keyEvent)398         public boolean onEditorAction(TextView textView, int sentImeId, KeyEvent keyEvent) {
399             this.textView = textView;
400             this.sentImeId = sentImeId;
401             return false;
402         }
403     }
404 
405     private static class MockTextWatcher implements TextWatcher {
406 
407         List<String> methodsCalled = new ArrayList<String>();
408         Editable afterTextChangeArgument;
409 
410         @Override
beforeTextChanged(CharSequence s, int start, int count, int after)411         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
412             methodsCalled.add("beforeTextChanged");
413         }
414 
415         @Override
onTextChanged(CharSequence s, int start, int before, int count)416         public void onTextChanged(CharSequence s, int start, int before, int count) {
417             methodsCalled.add("onTextChanged");
418         }
419 
420         @Override
afterTextChanged(Editable s)421         public void afterTextChanged(Editable s) {
422             methodsCalled.add("afterTextChanged");
423             afterTextChangeArgument = s;
424         }
425 
426     }
427 
428     private static class TestMovementMethod implements MovementMethod {
429         public MotionEvent event;
430         public boolean touchEventWasCalled;
431 
432         @Override
initialize(TextView widget, Spannable text)433         public void initialize(TextView widget, Spannable text) {
434         }
435 
436         @Override
onKeyDown(TextView widget, Spannable text, int keyCode, KeyEvent event)437         public boolean onKeyDown(TextView widget, Spannable text, int keyCode, KeyEvent event) {
438             return false;
439         }
440 
441         @Override
onKeyUp(TextView widget, Spannable text, int keyCode, KeyEvent event)442         public boolean onKeyUp(TextView widget, Spannable text, int keyCode, KeyEvent event) {
443             return false;
444         }
445 
446         @Override
onKeyOther(TextView view, Spannable text, KeyEvent event)447         public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) {
448             return false;
449         }
450 
451         @Override
onTakeFocus(TextView widget, Spannable text, int direction)452         public void onTakeFocus(TextView widget, Spannable text, int direction) {
453         }
454 
455         @Override
onTrackballEvent(TextView widget, Spannable text, MotionEvent event)456         public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event) {
457             return false;
458         }
459 
460         @Override
onTouchEvent(TextView widget, Spannable text, MotionEvent event)461         public boolean onTouchEvent(TextView widget, Spannable text, MotionEvent event) {
462             this.event = event;
463             touchEventWasCalled = true;
464             return false;
465         }
466 
467         @Override
canSelectArbitrarily()468         public boolean canSelectArbitrarily() {
469             return false;
470         }
471 
472 		@Override
onGenericMotionEvent(TextView widget, Spannable text, MotionEvent event)473 		public boolean onGenericMotionEvent(TextView widget, Spannable text,
474 				MotionEvent event) {
475 			return false;
476 		}
477     }
478 }
479