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 androidx.leanback.app;
17
18import static org.junit.Assert.assertEquals;
19import static org.mockito.Matchers.anyInt;
20import static org.mockito.Mockito.times;
21import static org.mockito.Mockito.verify;
22
23import android.support.test.filters.MediumTest;
24import android.support.test.filters.SmallTest;
25import android.support.test.runner.AndroidJUnit4;
26
27import androidx.leanback.widget.ArrayObjectAdapter;
28import androidx.leanback.widget.DividerRow;
29import androidx.leanback.widget.HeaderItem;
30import androidx.leanback.widget.ListRow;
31import androidx.leanback.widget.ObjectAdapter;
32import androidx.leanback.widget.PresenterSelector;
33import androidx.leanback.widget.SectionRow;
34
35import org.junit.Before;
36import org.junit.Test;
37import org.junit.runner.RunWith;
38import org.mockito.Mock;
39import org.mockito.Mockito;
40import org.mockito.MockitoAnnotations;
41
42import java.util.ArrayList;
43import java.util.List;
44
45/**
46 * Unit test for {@link ListRowDataAdapter} class.
47 */
48@RunWith(AndroidJUnit4.class)
49public class ListRowDataAdapterTest {
50    @Mock
51    private PresenterSelector presenterSelector;
52    @Mock
53    private ObjectAdapter.DataObserver dataObserver;
54
55    @Before
56    public void setUp() throws Exception {
57        MockitoAnnotations.initMocks(this);
58    }
59
60    @SmallTest
61    @Test
62    public void itemRangeChangedTest() {
63        int itemCount = 4;
64        ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenterSelector);
65        adapter.add(new SectionRow("section 1"));
66        for (int i = 0; i < itemCount; i++) {
67            HeaderItem headerItem = new HeaderItem(i, "header "+i);
68            adapter.add(new ListRow(headerItem, createListRowAdapter()));
69        }
70
71        ListRowDataAdapter listRowDataAdapter = new ListRowDataAdapter(adapter);
72        listRowDataAdapter.registerObserver(dataObserver);
73        SectionRow sectionRow = new SectionRow("section 11");
74        adapter.replace(0, sectionRow);
75
76        verify(dataObserver, times(1)).onItemRangeChanged(0, 1);
77        assertEquals(5, listRowDataAdapter.size());
78    }
79
80    @SmallTest
81    @Test
82    public void adapterSize_nonVisibleRowPresent() {
83        int itemCount = 4;
84        ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenterSelector);
85        adapter.add(new SectionRow("section 1"));
86        for (int i = 0; i < itemCount; i++) {
87            HeaderItem headerItem = new HeaderItem(i, "header "+i);
88            adapter.add(new ListRow(headerItem, createListRowAdapter()));
89        }
90
91        ListRowDataAdapter listRowDataAdapter = new ListRowDataAdapter(adapter);
92        assertEquals(5, listRowDataAdapter.size());
93
94        List<DividerRow> invisibleRows = new ArrayList<>();
95        invisibleRows.add(new DividerRow());
96        invisibleRows.add(new DividerRow());
97        adapter.addAll(5, invisibleRows);
98        verify(dataObserver, times(0)).onItemRangeInserted(anyInt(), anyInt());
99        assertEquals(5, listRowDataAdapter.size());
100    }
101
102    @SmallTest
103    @Test
104    public void adapterSize_visibleRowInserted() {
105        int itemCount = 4;
106        ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenterSelector);
107        adapter.add(new SectionRow("section 1"));
108        for (int i = 0; i < itemCount; i++) {
109            HeaderItem headerItem = new HeaderItem(i, "header "+i);
110            adapter.add(new ListRow(headerItem, createListRowAdapter()));
111        }
112
113        ListRowDataAdapter listRowDataAdapter = new ListRowDataAdapter(adapter);
114        assertEquals(5, listRowDataAdapter.size());
115
116        listRowDataAdapter.registerObserver(dataObserver);
117        List<ListRow> visibleRows = new ArrayList<>();
118        visibleRows.add(new ListRow(new HeaderItem(0, "Header 51"), createListRowAdapter()));
119        visibleRows.add(new ListRow(new HeaderItem(0, "Header 52"), createListRowAdapter()));
120        visibleRows.add(new ListRow(new HeaderItem(0, "Header 53"), createListRowAdapter()));
121        adapter.addAll(2, visibleRows);
122        verify(dataObserver, times(1)).onItemRangeInserted(2, 3);
123        assertEquals(8, listRowDataAdapter.size());
124    }
125
126    @SmallTest
127    @Test
128    public void adapterSize_nonVisibleRowInserted() {
129        int itemCount = 4;
130        ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenterSelector);
131        adapter.add(new SectionRow("section 1"));
132        for (int i = 0; i < itemCount; i++) {
133            HeaderItem headerItem = new HeaderItem(i, "header "+i);
134            adapter.add(new ListRow(headerItem, createListRowAdapter()));
135        }
136
137        ListRowDataAdapter listRowDataAdapter = new ListRowDataAdapter(adapter);
138        assertEquals(5, listRowDataAdapter.size());
139
140        List<DividerRow> invisibleRows = new ArrayList<>();
141        invisibleRows.add(new DividerRow());
142        invisibleRows.add(new DividerRow());
143
144        listRowDataAdapter.registerObserver(dataObserver);
145        adapter.addAll(adapter.size(), invisibleRows);
146        verify(dataObserver, times(0)).onItemRangeInserted(anyInt(), anyInt());
147        assertEquals(5, listRowDataAdapter.size());
148
149        adapter.add(new DividerRow());
150        verify(dataObserver, times(0)).onItemRangeInserted(anyInt(), anyInt());
151        assertEquals(5, listRowDataAdapter.size());
152
153        adapter.add(new ListRow(new HeaderItem(0, "Header 5"), createListRowAdapter()));
154        verify(dataObserver, times(1)).onItemRangeInserted(5, 4);
155        assertEquals(9, listRowDataAdapter.size());
156    }
157
158    @SmallTest
159    @Test
160    public void adapterSize_visibleRowRemoved() {
161        int itemCount = 4;
162        ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenterSelector);
163        adapter.add(new SectionRow("section 1"));
164        for (int i = 0; i < itemCount; i++) {
165            HeaderItem headerItem = new HeaderItem(i, "header "+i);
166            adapter.add(new ListRow(headerItem, createListRowAdapter()));
167        }
168
169        ListRowDataAdapter listRowDataAdapter = new ListRowDataAdapter(adapter);
170        assertEquals(5, listRowDataAdapter.size());
171        adapter.add(new DividerRow());
172        assertEquals(5, listRowDataAdapter.size());
173
174        listRowDataAdapter.registerObserver(dataObserver);
175        adapter.removeItems(2, 2);
176        verify(dataObserver, times(1)).onItemRangeRemoved(2, 2);
177        assertEquals(3, listRowDataAdapter.size());
178    }
179
180    @MediumTest
181    @Test
182    public void adapterSize_nonVisibleRowRemoved() {
183        int itemCount = 4;
184        ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenterSelector);
185        adapter.add(new SectionRow("section 1"));
186        for (int i = 0; i < itemCount; i++) {
187            HeaderItem headerItem = new HeaderItem(i, "header "+i);
188            adapter.add(new ListRow(headerItem, createListRowAdapter()));
189        }
190
191        ListRowDataAdapter listRowDataAdapter = new ListRowDataAdapter(adapter);
192        assertEquals(5, listRowDataAdapter.size());
193        adapter.add(new DividerRow());
194        assertEquals(5, listRowDataAdapter.size());
195
196        listRowDataAdapter.registerObserver(dataObserver);
197        adapter.removeItems(4, 1);
198        verify(dataObserver, times(1)).onItemRangeRemoved(4, 1);
199        assertEquals(4, listRowDataAdapter.size());
200
201        adapter.removeItems(4, 1);
202        verify(dataObserver, times(0)).onItemRangeInserted(anyInt(), anyInt());
203        assertEquals(4, listRowDataAdapter.size());
204    }
205
206    @SmallTest
207    @Test
208    public void adapterSize_rowsRemoveAll() {
209        ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenterSelector);
210        adapter.add(new SectionRow("section 1"));
211        for (int i = 0; i < 4; i++) {
212            HeaderItem headerItem = new HeaderItem(i, "header "+i);
213            adapter.add(new ListRow(headerItem, createListRowAdapter()));
214        }
215
216        ListRowDataAdapter listRowDataAdapter = new ListRowDataAdapter(adapter);
217        assertEquals(5, listRowDataAdapter.size());
218
219        adapter.clear();
220        assertEquals(0, listRowDataAdapter.size());
221
222        HeaderItem headerItem = new HeaderItem(10, "header "+10);
223        adapter.add(new ListRow(headerItem, createListRowAdapter()));
224        assertEquals(1, listRowDataAdapter.size());
225    }
226
227    @SmallTest
228    @Test
229    public void changeRemove_revealInvisibleItems() {
230        ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenterSelector);
231        for (int i = 0; i < 4; i++) {
232            HeaderItem headerItem = new HeaderItem(i, "header "+i);
233            adapter.add(new ListRow(headerItem, createListRowAdapter()));
234        }
235        adapter.add(new SectionRow("section"));
236        for (int i = 4; i < 8; i++) {
237            HeaderItem headerItem = new HeaderItem(i, "header "+i);
238            adapter.add(new ListRow(headerItem, createListRowAdapter()));
239        }
240
241        ListRowDataAdapter listRowDataAdapter = new ListRowDataAdapter(adapter);
242        assertEquals(9, listRowDataAdapter.size());
243
244        listRowDataAdapter.registerObserver(dataObserver);
245        adapter.removeItems(5, 4);
246        verify(dataObserver, times(1)).onItemRangeRemoved(4, 5);
247        assertEquals(4, listRowDataAdapter.size());
248    }
249
250    @SmallTest
251    @Test
252    public void adapterSize_rowsRemoved() {
253        int itemCount = 4;
254        ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenterSelector);
255        adapter.add(new SectionRow("section 1"));
256        for (int i = 0; i < itemCount; i++) {
257            HeaderItem headerItem = new HeaderItem(i, "header "+i);
258            adapter.add(new ListRow(headerItem, createListRowAdapter()));
259        }
260
261        ListRowDataAdapter listRowDataAdapter = new ListRowDataAdapter(adapter);
262        assertEquals(5, listRowDataAdapter.size());
263
264        adapter.add(new DividerRow());
265        assertEquals(5, listRowDataAdapter.size());
266
267        listRowDataAdapter.registerObserver(dataObserver);
268        adapter.removeItems(3, 3);
269        verify(dataObserver, times(1)).onItemRangeRemoved(3, 2);
270        assertEquals(3, listRowDataAdapter.size());
271    }
272
273    @SmallTest
274    @Test
275    public void customObjectAdapterTest() {
276        int itemCount = 4;
277        ArrayObjectAdapter adapter = new CustomAdapter(presenterSelector);
278        adapter.add(new SectionRow("section 1"));
279        for (int i = 0; i < itemCount; i++) {
280            HeaderItem headerItem = new HeaderItem(i, "header "+i);
281            adapter.add(new ListRow(headerItem, createListRowAdapter()));
282        }
283
284        ListRowDataAdapter listRowDataAdapter = new ListRowDataAdapter(adapter);
285        assertEquals(5, listRowDataAdapter.size());
286
287        adapter.add(new DividerRow());
288        assertEquals(5, listRowDataAdapter.size());
289
290        listRowDataAdapter.registerObserver(dataObserver);
291        adapter.removeItems(3, 3);
292        verify(dataObserver, times(1)).onChanged();
293        assertEquals(3, listRowDataAdapter.size());
294
295        Mockito.reset(dataObserver);
296        adapter.add(new DividerRow());
297        verify(dataObserver, times(1)).onChanged();
298        assertEquals(3, listRowDataAdapter.size());
299    }
300
301    private ArrayObjectAdapter createListRowAdapter() {
302        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(presenterSelector);
303        listRowAdapter.add(new Integer(1));
304        listRowAdapter.add(new Integer(2));
305        return listRowAdapter;
306    }
307
308    private class CustomAdapter extends ArrayObjectAdapter {
309
310        public CustomAdapter(PresenterSelector selector) {
311            super(selector);
312        }
313
314        @Override
315        public boolean isImmediateNotifySupported() {
316            return false;
317        }
318    }
319}
320