1 package com.xtremelabs.robolectric.shadows;
2 
3 import android.app.Application;
4 import android.view.View;
5 import android.view.ViewGroup;
6 import android.view.animation.Animation;
7 import android.view.animation.Animation.AnimationListener;
8 import android.widget.FrameLayout;
9 import android.widget.LinearLayout;
10 import com.xtremelabs.robolectric.R;
11 import com.xtremelabs.robolectric.Robolectric;
12 import com.xtremelabs.robolectric.WithTestDefaultsRunner;
13 import com.xtremelabs.robolectric.res.ResourceLoader;
14 import org.junit.After;
15 import org.junit.Before;
16 import org.junit.Test;
17 import org.junit.runner.RunWith;
18 
19 import java.io.ByteArrayOutputStream;
20 import java.io.PrintStream;
21 
22 import static com.xtremelabs.robolectric.Robolectric.shadowOf;
23 import static org.hamcrest.CoreMatchers.equalTo;
24 import static org.hamcrest.CoreMatchers.sameInstance;
25 import static org.hamcrest.MatcherAssert.assertThat;
26 import static org.hamcrest.core.IsNull.nullValue;
27 import static org.junit.Assert.*;
28 
29 @RunWith(WithTestDefaultsRunner.class)
30 public class ViewGroupTest {
31     private String defaultLineSeparator;
32     private ViewGroup root;
33     private View child1;
34     private View child2;
35     private ViewGroup child3;
36     private View child3a;
37     private View child3b;
38     private Application context;
39 
40     @Before
setUp()41     public void setUp() throws Exception {
42         context = new Application();
43         ShadowApplication.bind(context, new ResourceLoader(10, R.class, null, null));
44 
45         root = new FrameLayout(context);
46 
47         child1 = new View(context);
48         child2 = new View(context);
49         child3 = new FrameLayout(context);
50         child3a = new View(context);
51         child3b = new View(context);
52 
53         root.addView(child1);
54         root.addView(child2);
55         root.addView(child3);
56 
57         child3.addView(child3a);
58         child3.addView(child3b);
59 
60         defaultLineSeparator = System.getProperty("line.separator");
61         System.setProperty("line.separator", "\n");
62     }
63 
64     @After
tearDown()65     public void tearDown() throws Exception {
66         System.setProperty("line.separator", defaultLineSeparator);
67     }
68 
69     @Test
testLayoutAnimationListener()70     public void testLayoutAnimationListener() {
71         assertThat(root.getLayoutAnimationListener(), nullValue());
72 
73         AnimationListener animationListener = new AnimationListener() {
74             @Override
75             public void onAnimationEnd(Animation a) { }
76 
77             @Override
78             public void onAnimationRepeat(Animation a) { }
79 
80             @Override
81             public void onAnimationStart(Animation a) { }
82         };
83         root.setLayoutAnimationListener(animationListener);
84 
85         assertThat(root.getLayoutAnimationListener(), sameInstance(animationListener));
86     }
87 
88     @Test
testRemoveChildAt()89     public void testRemoveChildAt() throws Exception {
90         root.removeViewAt(1);
91 
92         assertThat(root.getChildCount(), equalTo(2));
93         assertThat(root.getChildAt(0), sameInstance(child1));
94         assertThat(root.getChildAt(1), sameInstance((View) child3));
95 
96         assertThat(child2.getParent(), nullValue());
97     }
98 
99     @Test
testAddViewAt()100     public void testAddViewAt() throws Exception {
101         root.removeAllViews();
102         root.addView(child1);
103         root.addView(child2);
104         root.addView(child3, 1);
105         assertThat(root.getChildAt(0), sameInstance(child1));
106         assertThat(root.getChildAt(1), sameInstance((View) child3));
107         assertThat(root.getChildAt(2), sameInstance(child2));
108     }
109 
110     @Test
shouldfindViewWithTag()111     public void shouldfindViewWithTag() {
112         root.removeAllViews();
113         child1.setTag("tag1");
114         child2.setTag("tag2");
115         child3.setTag("tag3");
116         root.addView(child1);
117         root.addView(child2);
118         root.addView(child3, 1);
119         assertThat(root.findViewWithTag("tag1"), sameInstance(child1));
120         assertThat(root.findViewWithTag("tag2"), sameInstance(child2));
121         assertThat((ViewGroup) root.findViewWithTag("tag3"), sameInstance(child3));
122     }
123 
124     @Test
shouldNotfindViewWithTagReturnNull()125     public void shouldNotfindViewWithTagReturnNull() {
126         root.removeAllViews();
127         child1.setTag("tag1");
128         child2.setTag("tag2");
129         child3.setTag("tag3");
130         root.addView(child1);
131         root.addView(child2);
132         root.addView(child3, 1);
133         assertThat(root.findViewWithTag("tag21"), equalTo(null));
134         assertThat((ViewGroup) root.findViewWithTag("tag23"), equalTo(null));
135     }
136 
137     @Test
shouldfindViewWithTagFromCorrectViewGroup()138     public void shouldfindViewWithTagFromCorrectViewGroup() {
139         root.removeAllViews();
140         child1.setTag("tag1");
141         child2.setTag("tag2");
142         child3.setTag("tag3");
143         root.addView(child1);
144         root.addView(child2);
145         root.addView(child3);
146 
147         child3a.setTag("tag1");
148         child3b.setTag("tag2");
149 
150         //can find views by tag from root
151         assertThat(root.findViewWithTag("tag1"), sameInstance(child1));
152         assertThat(root.findViewWithTag("tag2"), sameInstance(child2));
153         assertThat((ViewGroup) root.findViewWithTag("tag3"), sameInstance(child3));
154 
155         //can find views by tag from child3
156         assertThat(child3.findViewWithTag("tag1"), sameInstance(child3a));
157         assertThat(child3.findViewWithTag("tag2"), sameInstance(child3b));
158     }
159 
160     @Test
shouldFindViewWithTag_whenViewGroupOverridesGetTag()161     public void shouldFindViewWithTag_whenViewGroupOverridesGetTag() throws Exception {
162         ViewGroup viewGroup = new LinearLayout(Robolectric.application) {
163             @Override
164             public Object getTag() {
165                 return "blarg";
166             }
167         };
168         assertThat((ViewGroup) viewGroup.findViewWithTag("blarg"), sameInstance(viewGroup));
169     }
170 
171     @Test
hasFocus_shouldReturnTrueIfAnyChildHasFocus()172     public void hasFocus_shouldReturnTrueIfAnyChildHasFocus() throws Exception {
173         assertFalse(root.hasFocus());
174 
175         child1.requestFocus();
176         assertTrue(root.hasFocus());
177 
178         child1.clearFocus();
179         assertFalse(root.hasFocus());
180 
181         child3b.requestFocus();
182         assertTrue(root.hasFocus());
183 
184         child3b.clearFocus();
185         assertFalse(root.hasFocus());
186 
187         root.requestFocus();
188         assertTrue(root.hasFocus());
189     }
190 
191     @Test
clearFocus_shouldRecursivelyClearTheFocusOfAllChildren()192     public void clearFocus_shouldRecursivelyClearTheFocusOfAllChildren() throws Exception {
193         child3a.requestFocus();
194 
195         root.clearFocus();
196 
197         assertFalse(child3a.hasFocus());
198         assertFalse(child3.hasFocus());
199         assertFalse(root.hasFocus());
200 
201         root.requestFocus();
202         root.clearFocus();
203         assertFalse(root.hasFocus());
204     }
205 
206     @Test
findFocus_shouldRecursivelyFindTheViewWithFocus()207     public void findFocus_shouldRecursivelyFindTheViewWithFocus() {
208         child3a.requestFocus();
209 
210         assertSame(child3a, root.findFocus());
211     }
212 
213     @Test
findFocus_shouldReturnThisBeforeChildrenWithFocus()214     public void findFocus_shouldReturnThisBeforeChildrenWithFocus() {
215         child3a.requestFocus();
216         child3.requestFocus();
217 
218         assertSame(child3, root.findFocus());
219     }
220 
221     @Test
dump_shouldDumpStructure()222     public void dump_shouldDumpStructure() throws Exception {
223         child3.setId(R.id.snippet_text);
224 
225         ByteArrayOutputStream out = new ByteArrayOutputStream();
226         shadowOf(root).dump(new PrintStream(out), 0);
227         assertEquals("<FrameLayout>\n" +
228                 "  <View/>\n" +
229                 "  <View/>\n" +
230                 "  <FrameLayout id=\"id/snippet_text\">\n" +
231                 "    <View/>\n" +
232                 "    <View/>\n" +
233                 "  </FrameLayout>\n" +
234                 "</FrameLayout>\n", out.toString());
235     }
236 
237     @Test
testRemoveView()238     public void testRemoveView() {
239         root.removeView(new View(context));
240         assertThat(root.getChildCount(), equalTo(3));
241 
242         root.removeView(child2);
243         assertThat(root.getChildCount(), equalTo(2));
244         assertThat(root.getChildAt(0), sameInstance(child1));
245         assertThat(root.getChildAt(1), sameInstance((View) child3));
246 
247         root.removeView(child2);
248         assertThat(root.getChildCount(), equalTo(2));
249         assertThat(root.getChildAt(0), sameInstance(child1));
250         assertThat(root.getChildAt(1), sameInstance((View) child3));
251 
252         root.removeView(child1);
253         root.removeView(child3);
254         assertThat(root.getChildCount(), equalTo(0));
255     }
256 
257     @Test
testRemoveViewInLayout()258     public void testRemoveViewInLayout() {
259         root.removeViewInLayout(new View(context));
260         assertThat(root.getChildCount(), equalTo(3));
261 
262         root.removeViewInLayout(child2);
263         assertThat(root.getChildCount(), equalTo(2));
264         assertThat(root.getChildAt(0), sameInstance(child1));
265         assertThat(root.getChildAt(1), sameInstance((View) child3));
266 
267         root.removeViewInLayout(child2);
268         assertThat(root.getChildCount(), equalTo(2));
269         assertThat(root.getChildAt(0), sameInstance(child1));
270         assertThat(root.getChildAt(1), sameInstance((View) child3));
271 
272         root.removeViewInLayout(child1);
273         root.removeViewInLayout(child3);
274         assertThat(root.getChildCount(), equalTo(0));
275     }
276 
277     @Test
testRemoveViews()278     public void testRemoveViews() {
279         root.removeViews(0, 0);
280         assertThat(root.getChildCount(), equalTo(3));
281 
282         root.removeViews(2, 1);
283         assertThat(root.getChildCount(), equalTo(2));
284         assertThat(root.getChildAt(0), sameInstance(child1));
285         assertThat(root.getChildAt(1), sameInstance(child2));
286 
287         root.removeViews(0, 1);
288         assertThat(root.getChildCount(), equalTo(1));
289         assertThat(root.getChildAt(0), sameInstance(child2));
290 
291         root.removeViews(0, 1);
292         assertThat(root.getChildCount(), equalTo(0));
293 
294         root.addView(child1);
295         root.addView(child2);
296         root.addView(child3);
297 
298         root.removeViews(1, 1);
299         assertThat(root.getChildCount(), equalTo(2));
300         assertThat(root.getChildAt(0), sameInstance(child1));
301         assertThat(root.getChildAt(1), sameInstance((View) child3));
302 
303         root.removeViews(0, 2);
304         assertThat(root.getChildCount(), equalTo(0));
305     }
306 
307     @Test
testRemoveViewsInLayout()308     public void testRemoveViewsInLayout() {
309         root.removeViewsInLayout(0, 0);
310         assertThat(root.getChildCount(), equalTo(3));
311 
312         root.removeViewsInLayout(2, 1);
313         assertThat(root.getChildCount(), equalTo(2));
314         assertThat(root.getChildAt(0), sameInstance(child1));
315         assertThat(root.getChildAt(1), sameInstance(child2));
316 
317         root.removeViewsInLayout(0, 1);
318         assertThat(root.getChildCount(), equalTo(1));
319         assertThat(root.getChildAt(0), sameInstance(child2));
320 
321         root.removeViewsInLayout(0, 1);
322         assertThat(root.getChildCount(), equalTo(0));
323 
324         root.addView(child1);
325         root.addView(child2);
326         root.addView(child3);
327 
328         root.removeViewsInLayout(1, 1);
329         assertThat(root.getChildCount(), equalTo(2));
330         assertThat(root.getChildAt(0), sameInstance(child1));
331         assertThat(root.getChildAt(1), sameInstance((View) child3));
332 
333         root.removeViewsInLayout(0, 2);
334         assertThat(root.getChildCount(), equalTo(0));
335     }
336 }
337