GuidedStepFragmentTest.java revision 42e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.support.v17.leanback.app;
17
18import static org.junit.Assert.assertEquals;
19import static org.junit.Assert.assertFalse;
20import static org.junit.Assert.assertTrue;
21import static org.mockito.Mockito.any;
22import static org.mockito.Mockito.doAnswer;
23import static org.mockito.Mockito.times;
24import static org.mockito.Mockito.verify;
25
26import android.os.Bundle;
27import android.support.test.filters.MediumTest;
28import android.support.test.runner.AndroidJUnit4;
29import android.support.v17.leanback.testutils.PollingCheck;
30import android.support.v17.leanback.widget.GuidedAction;
31import android.view.KeyEvent;
32import android.view.LayoutInflater;
33import android.view.View;
34import android.view.ViewGroup;
35
36import org.junit.Test;
37import org.junit.runner.RunWith;
38import org.mockito.ArgumentCaptor;
39import org.mockito.invocation.InvocationOnMock;
40import org.mockito.stubbing.Answer;
41
42import java.util.ArrayList;
43import java.util.List;
44
45/**
46 * @hide from javadoc
47 */
48@MediumTest
49@RunWith(AndroidJUnit4.class)
50public class GuidedStepFragmentTest extends GuidedStepFragmentTestBase {
51
52    @Test
53    public void nextAndBack() throws Throwable {
54        GuidedStepTestFragment.Provider first = mockProvider("first");
55        doAnswer(new Answer<Void>() {
56            public Void answer(InvocationOnMock invocation) {
57                List actions = (List) invocation.getArguments()[0];
58                actions.add(new GuidedAction.Builder().id(1000).title("OK").build());
59                return null;
60            }
61        }).when(first).onCreateActions(any(List.class), any(Bundle.class));
62        doAnswer(new Answer<Void>() {
63            public Void answer(InvocationOnMock invocation) {
64                GuidedAction action = (GuidedAction) invocation.getArguments()[0];
65                GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
66                        invocation.getMock();
67                if (action.getId() == 1000) {
68                    GuidedStepFragment.add(obj.getFragmentManager(),
69                            new GuidedStepTestFragment("second"));
70                }
71                return null;
72            }
73        }).when(first).onGuidedActionClicked(any(GuidedAction.class));
74
75        GuidedStepTestFragment.Provider second = mockProvider("second");
76
77        GuidedStepFragmentTestActivity activity = launchTestActivity("first");
78        verify(first, times(1)).onCreate(any(Bundle.class));
79        verify(first, times(1)).onCreateGuidance(any(Bundle.class));
80        verify(first, times(1)).onCreateActions(any(List.class), any(Bundle.class));
81        verify(first, times(1)).onCreateButtonActions(any(List.class), any(Bundle.class));
82        verify(first, times(1)).onCreateView(any(LayoutInflater.class), any(ViewGroup.class),
83                any(Bundle.class), any(View.class));
84        verify(first, times(1)).onViewStateRestored(any(Bundle.class));
85        verify(first, times(1)).onStart();
86        verify(first, times(1)).onResume();
87
88        sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
89        verify(first, times(1)).onGuidedActionClicked(any(GuidedAction.class));
90
91        PollingCheck.waitFor(new EnterTransitionFinish(second));
92        verify(first, times(1)).onPause();
93        verify(first, times(1)).onStop();
94        verify(first, times(1)).onDestroyView();
95        verify(second, times(1)).onCreate(any(Bundle.class));
96        verify(second, times(1)).onCreateGuidance(any(Bundle.class));
97        verify(second, times(1)).onCreateActions(any(List.class), any(Bundle.class));
98        verify(second, times(1)).onCreateButtonActions(any(List.class), any(Bundle.class));
99        verify(second, times(1)).onCreateView(any(LayoutInflater.class), any(ViewGroup.class),
100                any(Bundle.class), any(View.class));
101        verify(second, times(1)).onViewStateRestored(any(Bundle.class));
102        verify(second, times(1)).onStart();
103        verify(second, times(1)).onResume();
104
105        sendKey(KeyEvent.KEYCODE_BACK);
106
107        PollingCheck.waitFor(new EnterTransitionFinish(first));
108        verify(second, times(1)).onPause();
109        verify(second, times(1)).onStop();
110        verify(second, times(1)).onDestroyView();
111        verify(second, times(1)).onDestroy();
112        verify(first, times(1)).onCreateActions(any(List.class), any(Bundle.class));
113        verify(first, times(2)).onCreateView(any(LayoutInflater.class), any(ViewGroup.class),
114                any(Bundle.class), any(View.class));
115        verify(first, times(2)).onViewStateRestored(any(Bundle.class));
116        verify(first, times(2)).onStart();
117        verify(first, times(2)).onResume();
118
119        sendKey(KeyEvent.KEYCODE_BACK);
120        PollingCheck.waitFor(new PollingCheck.ActivityDestroy(activity));
121        verify(first, times(1)).onDestroy();
122        assertTrue(activity.isDestroyed());
123    }
124
125    @Test
126    public void restoreFragments() throws Throwable {
127        GuidedStepTestFragment.Provider first = mockProvider("first");
128        doAnswer(new Answer<Void>() {
129            public Void answer(InvocationOnMock invocation) {
130                List actions = (List) invocation.getArguments()[0];
131                actions.add(new GuidedAction.Builder().id(1000).title("OK").build());
132                actions.add(new GuidedAction.Builder().id(1001).editable(true).title("text")
133                        .build());
134                actions.add(new GuidedAction.Builder().id(1002).editable(true).title("text")
135                        .autoSaveRestoreEnabled(false).build());
136                return null;
137            }
138        }).when(first).onCreateActions(any(List.class), any(Bundle.class));
139        doAnswer(new Answer<Void>() {
140            public Void answer(InvocationOnMock invocation) {
141                GuidedAction action = (GuidedAction) invocation.getArguments()[0];
142                GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
143                        invocation.getMock();
144                if (action.getId() == 1000) {
145                    GuidedStepFragment.add(obj.getFragmentManager(),
146                            new GuidedStepTestFragment("second"));
147                }
148                return null;
149            }
150        }).when(first).onGuidedActionClicked(any(GuidedAction.class));
151
152        GuidedStepTestFragment.Provider second = mockProvider("second");
153
154        final GuidedStepFragmentTestActivity activity = launchTestActivity("first");
155        first.getFragment().findActionById(1001).setTitle("modified text");
156        first.getFragment().findActionById(1002).setTitle("modified text");
157        sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
158        PollingCheck.waitFor(new EnterTransitionFinish(second));
159
160        activityTestRule.runOnUiThread(new Runnable() {
161            @Override
162            public void run() {
163                activity.recreate();
164            }
165        });
166        PollingCheck.waitFor(new EnterTransitionFinish(second));
167        verify(first, times(2)).onCreate(any(Bundle.class));
168        verify(first, times(1)).onCreateView(any(LayoutInflater.class), any(ViewGroup.class),
169                any(Bundle.class), any(View.class));
170        verify(first, times(2)).onCreateActions(any(List.class), any(Bundle.class));
171        verify(first, times(1)).onDestroy();
172        verify(second, times(2)).onCreate(any(Bundle.class));
173        verify(second, times(2)).onCreateView(any(LayoutInflater.class), any(ViewGroup.class),
174                any(Bundle.class), any(View.class));
175        verify(second, times(1)).onDestroy();
176        assertEquals("modified text", first.getFragment().findActionById(1001).getTitle());
177        assertEquals("text", first.getFragment().findActionById(1002).getTitle());
178
179        sendKey(KeyEvent.KEYCODE_BACK);
180        PollingCheck.waitFor(new EnterTransitionFinish(first));
181        verify(second, times(2)).onPause();
182        verify(second, times(2)).onStop();
183        verify(second, times(2)).onDestroyView();
184        verify(second, times(2)).onDestroy();
185        verify(first, times(2)).onCreateView(any(LayoutInflater.class), any(ViewGroup.class),
186                any(Bundle.class), any(View.class));
187    }
188
189
190    @Test
191    public void finishGuidedStepFragment_finishes_activity() throws Throwable {
192        GuidedStepTestFragment.Provider first = mockProvider("first");
193        doAnswer(new Answer<Void>() {
194            public Void answer(InvocationOnMock invocation) {
195                List actions = (List) invocation.getArguments()[0];
196                actions.add(new GuidedAction.Builder().id(1001).title("Finish activity").build());
197                return null;
198            }
199        }).when(first).onCreateActions(any(List.class), any(Bundle.class));
200        doAnswer(new Answer<Void>() {
201            public Void answer(InvocationOnMock invocation) {
202                GuidedAction action = (GuidedAction) invocation.getArguments()[0];
203                GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
204                        invocation.getMock();
205                if (action.getId() == 1001) {
206                    obj.getFragment().finishGuidedStepFragments();
207                }
208                return null;
209            }
210        }).when(first).onGuidedActionClicked(any(GuidedAction.class));
211
212        final GuidedStepFragmentTestActivity activity = launchTestActivity("first");
213
214        View viewFinish = first.getFragment().getActionItemView(0);
215        assertTrue(viewFinish.hasFocus());
216        sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
217        PollingCheck.waitFor(new PollingCheck.ActivityDestroy(activity));
218        verify(first, times(1)).onDestroy();
219    }
220
221    @Test
222    public void finishGuidedStepFragment_finishes_fragments() throws Throwable {
223        GuidedStepTestFragment.Provider first = mockProvider("first");
224        doAnswer(new Answer<Void>() {
225            public Void answer(InvocationOnMock invocation) {
226                List actions = (List) invocation.getArguments()[0];
227                actions.add(new GuidedAction.Builder().id(1001).title("Finish fragments").build());
228                return null;
229            }
230        }).when(first).onCreateActions(any(List.class), any(Bundle.class));
231        doAnswer(new Answer<Void>() {
232            public Void answer(InvocationOnMock invocation) {
233                GuidedAction action = (GuidedAction) invocation.getArguments()[0];
234                GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
235                        invocation.getMock();
236                if (action.getId() == 1001) {
237                    obj.getFragment().finishGuidedStepFragments();
238                }
239                return null;
240            }
241        }).when(first).onGuidedActionClicked(any(GuidedAction.class));
242
243        final GuidedStepFragmentTestActivity activity = launchTestActivity("first",
244                false /*asRoot*/);
245
246        View viewFinish = first.getFragment().getActionItemView(0);
247        assertTrue(viewFinish.hasFocus());
248        sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
249
250        // fragment should be destroyed, activity should not destroyed
251        waitOnDestroy(first, 1);
252        assertFalse(activity.isDestroyed());
253    }
254
255    @Test
256    public void subActions() throws Throwable {
257        final boolean[] expandSubActionInOnCreateView = new boolean[] {false};
258        GuidedStepTestFragment.Provider first = mockProvider("first");
259        doAnswer(new Answer<Void>() {
260            public Void answer(InvocationOnMock invocation) {
261                GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
262                        invocation.getMock();
263                if (expandSubActionInOnCreateView[0]) {
264                    obj.getFragment().expandAction(obj.getFragment().findActionById(1000), false);
265                }
266                return null;
267            }
268        }).when(first).onCreateView(any(LayoutInflater.class), any(ViewGroup.class),
269                any(Bundle.class), any(View.class));
270        doAnswer(new Answer<Void>() {
271            public Void answer(InvocationOnMock invocation) {
272                List actions = (List) invocation.getArguments()[0];
273                List<GuidedAction> subActions = new ArrayList<GuidedAction>();
274                subActions.add(new GuidedAction.Builder().id(2000).title("item1").build());
275                subActions.add(new GuidedAction.Builder().id(2001).title("item2").build());
276                actions.add(new GuidedAction.Builder().id(1000).subActions(subActions)
277                        .title("list").build());
278                return null;
279            }
280        }).when(first).onCreateActions(any(List.class), any(Bundle.class));
281        doAnswer(new Answer<Boolean>() {
282            public Boolean answer(InvocationOnMock invocation) {
283                GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
284                        invocation.getMock();
285                GuidedAction action = (GuidedAction) invocation.getArguments()[0];
286                if (action.getId() == 2000) {
287                    return true;
288                } else if (action.getId() == 2001) {
289                    GuidedStepFragment.add(obj.getFragmentManager(),
290                            new GuidedStepTestFragment("second"));
291                    return false;
292                }
293                return false;
294            }
295        }).when(first).onSubGuidedActionClicked(any(GuidedAction.class));
296
297        GuidedStepTestFragment.Provider second = mockProvider("second");
298
299        final GuidedStepFragmentTestActivity activity = launchTestActivity("first");
300
301        // after clicked, it sub actions list should expand
302        View viewForList = first.getFragment().getActionItemView(0);
303        assertTrue(viewForList.hasFocus());
304        sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
305        PollingCheck.waitFor(new ExpandTransitionFinish(first));
306        assertFalse(viewForList.hasFocus());
307
308        sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
309        ArgumentCaptor<GuidedAction> actionCapture = ArgumentCaptor.forClass(GuidedAction.class);
310        verify(first, times(1)).onSubGuidedActionClicked(actionCapture.capture());
311        assertEquals(2000, actionCapture.getValue().getId());
312        // after clicked a sub action, it sub actions list should close
313        PollingCheck.waitFor(new ExpandTransitionFinish(first));
314        assertTrue(viewForList.hasFocus());
315
316        sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
317        PollingCheck.waitFor(new ExpandTransitionFinish(first));
318
319        assertFalse(viewForList.hasFocus());
320        sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
321        sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
322        ArgumentCaptor<GuidedAction> actionCapture2 = ArgumentCaptor.forClass(GuidedAction.class);
323        verify(first, times(2)).onSubGuidedActionClicked(actionCapture2.capture());
324        assertEquals(2001, actionCapture2.getValue().getId());
325
326        PollingCheck.waitFor(new EnterTransitionFinish(second));
327        verify(second, times(1)).onCreateView(any(LayoutInflater.class), any(ViewGroup.class),
328                any(Bundle.class), any(View.class));
329
330        // test expand sub action when return to first fragment
331        expandSubActionInOnCreateView[0] = true;
332        sendKey(KeyEvent.KEYCODE_BACK);
333        PollingCheck.waitFor(new EnterTransitionFinish(first));
334        verify(first, times(2)).onCreateView(any(LayoutInflater.class), any(ViewGroup.class),
335                any(Bundle.class), any(View.class));
336        assertTrue(first.getFragment().isExpanded());
337
338        sendKey(KeyEvent.KEYCODE_BACK);
339        PollingCheck.waitFor(new ExpandTransitionFinish(first));
340        assertFalse(first.getFragment().isExpanded());
341
342        sendKey(KeyEvent.KEYCODE_BACK);
343        PollingCheck.waitFor(new PollingCheck.ActivityDestroy(activity));
344        verify(first, times(1)).onDestroy();
345    }
346}
347