ViewTest.java revision 7cd4fd403867d4e7e6ee944a07ad6fb6c537f3ec
1package com.xtremelabs.robolectric.shadows;
2
3import android.app.Activity;
4import android.content.Context;
5import android.graphics.Point;
6import android.graphics.drawable.ColorDrawable;
7import android.view.MotionEvent;
8import android.view.View;
9import android.view.ViewGroup;
10import android.view.ViewTreeObserver;
11import android.view.animation.Animation;
12import android.widget.LinearLayout;
13import com.xtremelabs.robolectric.R;
14import com.xtremelabs.robolectric.Robolectric;
15import com.xtremelabs.robolectric.WithTestDefaultsRunner;
16import com.xtremelabs.robolectric.util.TestAnimationListener;
17import com.xtremelabs.robolectric.util.TestOnClickListener;
18import com.xtremelabs.robolectric.util.TestOnLongClickListener;
19import com.xtremelabs.robolectric.util.TestRunnable;
20import com.xtremelabs.robolectric.util.Transcript;
21import org.junit.Before;
22import org.junit.Test;
23import org.junit.runner.RunWith;
24
25import static com.xtremelabs.robolectric.Robolectric.shadowOf;
26import static junit.framework.Assert.assertEquals;
27import static org.hamcrest.CoreMatchers.*;
28import static org.junit.Assert.assertFalse;
29import static org.junit.Assert.assertNotSame;
30import static org.junit.Assert.assertThat;
31import static org.junit.Assert.assertTrue;
32
33@RunWith(WithTestDefaultsRunner.class)
34public class ViewTest {
35    private View view;
36
37    @Before
38    public void setUp() throws Exception {
39        view = new View(new Activity());
40    }
41
42    @Test
43    public void testHasEmptyLayoutParams() throws Exception {
44        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
45        assertThat(layoutParams, notNullValue());
46    }
47
48    @Test
49    public void layout_shouldAffectWidthAndHeight() throws Exception {
50        assertThat(view.getWidth(), equalTo(0));
51        assertThat(view.getHeight(), equalTo(0));
52
53        view.layout(100, 200, 303, 404);
54        assertThat(view.getWidth(), equalTo(303 - 100));
55        assertThat(view.getHeight(), equalTo(404 - 200));
56    }
57
58    @Test
59    public void shouldFocus() throws Exception {
60        final Transcript transcript = new Transcript();
61
62        view.setOnFocusChangeListener(new View.OnFocusChangeListener() {
63            @Override
64            public void onFocusChange(View v, boolean hasFocus) {
65                transcript.add(hasFocus ? "Gained focus" : "Lost focus");
66            }
67        });
68
69        assertFalse(view.isFocused());
70        assertFalse(view.hasFocus());
71        transcript.assertNoEventsSoFar();
72
73        view.requestFocus();
74        assertTrue(view.isFocused());
75        assertTrue(view.hasFocus());
76        transcript.assertEventsSoFar("Gained focus");
77
78        view.clearFocus();
79        assertFalse(view.isFocused());
80        assertFalse(view.hasFocus());
81        transcript.assertEventsSoFar("Lost focus");
82    }
83
84    @Test
85    public void shouldNotBeFocusableByDefault() throws Exception {
86        assertFalse(view.isFocusable());
87
88        view.setFocusable(true);
89        assertTrue(view.isFocusable());
90    }
91
92    @Test
93    public void shouldKnowIfThisOrAncestorsAreVisible() throws Exception {
94        assertTrue(shadowOf(view).derivedIsVisible());
95
96        ViewGroup grandParent = new LinearLayout(null);
97        ViewGroup parent = new LinearLayout(null);
98        grandParent.addView(parent);
99        parent.addView(view);
100
101        grandParent.setVisibility(View.GONE);
102
103        assertFalse(shadowOf(view).derivedIsVisible());
104    }
105
106    @Test
107    public void shouldInflateMergeRootedLayoutAndNotCreateReferentialLoops() throws Exception {
108        LinearLayout root = new LinearLayout(null);
109        root.inflate(new Activity(), R.layout.inner_merge, root);
110        for (int i = 0; i < root.getChildCount(); i++) {
111            View child = root.getChildAt(i);
112            assertNotSame(root, child);
113        }
114    }
115
116    @Test
117    public void performLongClick_shouldClickOnView() throws Exception {
118        TestOnLongClickListener clickListener = new TestOnLongClickListener();
119        view.setOnLongClickListener(clickListener);
120        shadowOf(view).performLongClick();
121
122        assertTrue(clickListener.clicked);
123    }
124
125
126    @Test
127    public void checkedClick_shouldClickOnView() throws Exception {
128        TestOnClickListener clickListener = new TestOnClickListener();
129        view.setOnClickListener(clickListener);
130        shadowOf(view).checkedPerformClick();
131
132        assertTrue(clickListener.clicked);
133    }
134
135    @Test(expected = RuntimeException.class)
136    public void checkedClick_shouldThrowIfViewIsNotVisible() throws Exception {
137        ViewGroup grandParent = new LinearLayout(null);
138        ViewGroup parent = new LinearLayout(null);
139        grandParent.addView(parent);
140        parent.addView(view);
141        grandParent.setVisibility(View.GONE);
142
143        shadowOf(view).checkedPerformClick();
144    }
145
146    @Test(expected = RuntimeException.class)
147    public void checkedClick_shouldThrowIfViewIsDisabled() throws Exception {
148        view.setEnabled(false);
149        shadowOf(view).checkedPerformClick();
150    }
151
152    @Test
153    public void getBackground_shouldReturnNullIfNoBackgroundHasBeenSet() throws Exception {
154        assertThat(view.getBackground(), nullValue());
155    }
156
157    @Test
158    public void shouldSetBackgroundColor() {
159        view.setBackgroundColor(R.color.android_red);
160        int intColor = view.getResources().getColor(R.color.android_red);
161
162        assertThat((ColorDrawable) view.getBackground(), equalTo(new ColorDrawable(intColor)));
163    }
164
165    @Test
166    public void shouldSetBackgroundResource() throws Exception {
167        view.setBackgroundResource(R.drawable.an_image);
168        assertThat(view.getBackground(), equalTo(view.getResources().getDrawable(R.drawable.an_image)));
169    }
170
171    @Test
172    public void shouldRecordBackgroundColor() {
173        int[] colors = {0, 1, 727};
174
175        for (int color : colors) {
176            view.setBackgroundColor(color);
177            assertThat(shadowOf(view).getBackgroundColor(), equalTo(color));
178        }
179    }
180
181    @Test
182    public void shouldPostActionsToTheMessageQueue() throws Exception {
183        Robolectric.pauseMainLooper();
184
185        TestRunnable runnable = new TestRunnable();
186        view.post(runnable);
187        assertFalse(runnable.wasRun);
188
189        Robolectric.unPauseMainLooper();
190        assertTrue(runnable.wasRun);
191    }
192
193    @Test
194    public void shouldPostInvalidateDelayed() throws Exception {
195        Robolectric.pauseMainLooper();
196
197        view.postInvalidateDelayed(100);
198        ShadowView shadowView = shadowOf(view);
199        assertFalse(shadowView.wasInvalidated());
200
201        Robolectric.unPauseMainLooper();
202        assertTrue(shadowView.wasInvalidated());
203    }
204
205    @Test
206    public void shouldPostActionsToTheMessageQueueWithDelay() throws Exception {
207        Robolectric.pauseMainLooper();
208
209        TestRunnable runnable = new TestRunnable();
210        view.postDelayed(runnable, 1);
211        assertFalse(runnable.wasRun);
212
213        Robolectric.getUiThreadScheduler().advanceBy(1);
214        assertTrue(runnable.wasRun);
215    }
216
217    @Test
218    public void shouldSupportAllConstructors() throws Exception {
219        new View(null);
220        new View(null, null);
221        new View(null, null, 0);
222    }
223
224    @Test
225    public void shouldSetAnimation() throws Exception {
226        Animation anim = new TestAnimation();
227        view.setAnimation(anim);
228        assertThat(view.getAnimation(), sameInstance(anim));
229    }
230
231    @Test
232    public void shouldStartAndClearAnimation() throws Exception {
233        Animation anim = new TestAnimation();
234        TestAnimationListener listener = new TestAnimationListener();
235        anim.setAnimationListener(listener);
236        assertThat(listener.wasStartCalled, equalTo(false));
237        assertThat(listener.wasRepeatCalled, equalTo(false));
238        assertThat(listener.wasEndCalled, equalTo(false));
239        view.startAnimation(anim);
240        assertThat(listener.wasStartCalled, equalTo(true));
241        assertThat(listener.wasRepeatCalled, equalTo(false));
242        assertThat(listener.wasEndCalled, equalTo(false));
243        view.clearAnimation();
244        assertThat(listener.wasStartCalled, equalTo(true));
245        assertThat(listener.wasRepeatCalled, equalTo(false));
246        assertThat(listener.wasEndCalled, equalTo(true));
247    }
248
249    @Test
250    public void shouldfindViewWithTag() {
251    	String tagged = "tagged";
252    	String tagged2 = "tagged";
253    	view.setTag(tagged);
254    	assertThat(view.findViewWithTag(tagged2),sameInstance(view));
255    }
256
257    @Test
258    public void scrollTo_shouldStoreTheScrolledCoordinates() throws Exception {
259        view.scrollTo(1, 2);
260        assertThat(shadowOf(view).scrollToCoordinates, equalTo(new Point(1, 2)));
261    }
262
263    @Test
264    public void shouldScrollTo() throws Exception {
265        view.scrollTo(7, 6);
266
267        assertEquals(7, view.getScrollX());
268        assertEquals(6, view.getScrollY());
269    }
270
271    @Test
272    public void shouldGetScrollXAndY() {
273        assertEquals(0, view.getScrollX());
274        assertEquals(0, view.getScrollY());
275    }
276
277    @Test
278    public void getViewTreeObserver_shouldReturnTheSameObserverFromMultipleCalls() throws Exception {
279        ViewTreeObserver observer = view.getViewTreeObserver();
280        assertThat(observer, instanceOf(ViewTreeObserver.class));
281        assertThat(view.getViewTreeObserver(), sameInstance(observer));
282    }
283
284    @Test
285    public void dispatchTouchEvent_sendsMotionEventToOnTouchEvent() throws Exception {
286        TouchableView touchableView = new TouchableView(null);
287        MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 12f, 34f, 0);
288        touchableView.dispatchTouchEvent(event);
289        assertThat(touchableView.event, sameInstance(event));
290        view.dispatchTouchEvent(event);
291        assertThat(shadowOf(view).getLastTouchEvent(), sameInstance(event));
292    }
293
294    @Test
295    public void dispatchTouchEvent_listensToTrueFromListener() throws Exception {
296        view.setOnTouchListener(new View.OnTouchListener() {
297            @Override
298            public boolean onTouch(View view, MotionEvent motionEvent) {
299                return true;
300            }
301        });
302        MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 12f, 34f, 0);
303        view.dispatchTouchEvent(event);
304        assertThat(shadowOf(view).getLastTouchEvent(), nullValue());
305    }
306
307    @Test
308    public void dispatchTouchEvent_listensToFalseFromListener() throws Exception {
309        view.setOnTouchListener(new View.OnTouchListener() {
310            @Override
311            public boolean onTouch(View view, MotionEvent motionEvent) {
312                return false;
313            }
314        });
315        MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 12f, 34f, 0);
316        view.dispatchTouchEvent(event);
317        assertThat(shadowOf(view).getLastTouchEvent(), sameInstance(event));
318    }
319
320    @Test
321    public void test_nextFocusDownId() throws Exception {
322        assertEquals(View.NO_ID, view.getNextFocusDownId());
323
324        view.setNextFocusDownId(R.id.icon);
325        assertEquals(R.id.icon, view.getNextFocusDownId());
326    }
327
328    private static class TestAnimation extends Animation {
329    }
330
331    private static class TouchableView extends View {
332        MotionEvent event;
333
334        public TouchableView(Context context) {
335            super(context);
336        }
337
338        @Override
339        public boolean onTouchEvent(MotionEvent event) {
340            this.event = event;
341            return false;
342        }
343    }
344}
345