1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/app_list/pagination_model.h"
9 #include "base/basictypes.h"
10 #include "base/compiler_specific.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/app_list/pagination_model_observer.h"
19 class TestPaginationModelObserver
: public PaginationModelObserver
{
21 TestPaginationModelObserver()
23 expected_page_selection_(0),
24 expected_transition_start_(0),
25 expected_transition_end_(0),
26 transition_page_(-1) {
29 ~TestPaginationModelObserver() override
{}
33 transition_start_count_
= 0;
34 transition_end_count_
= 0;
35 selected_pages_
.clear();
38 void set_model(PaginationModel
* model
) { model_
= model
; }
40 void set_expected_page_selection(int expected_page_selection
) {
41 expected_page_selection_
= expected_page_selection
;
43 void set_expected_transition_start(int expected_transition_start
) {
44 expected_transition_start_
= expected_transition_start
;
46 void set_expected_transition_end(int expected_transition_end
) {
47 expected_transition_end_
= expected_transition_end
;
49 void set_transition_page(int page
) { transition_page_
= page
; }
51 const std::string
& selected_pages() const { return selected_pages_
; }
52 int selection_count() const { return selection_count_
; }
53 int transition_start_count() const { return transition_start_count_
; }
54 int transition_end_count() const { return transition_end_count_
; }
57 void AppendSelectedPage(int page
) {
58 if (selected_pages_
.length())
59 selected_pages_
.append(std::string(" "));
60 selected_pages_
.append(base::IntToString(page
));
63 // PaginationModelObserver overrides:
64 void TotalPagesChanged() override
{}
65 void SelectedPageChanged(int old_selected
, int new_selected
) override
{
66 AppendSelectedPage(new_selected
);
68 if (expected_page_selection_
&&
69 selection_count_
== expected_page_selection_
) {
70 base::MessageLoop::current()->Quit();
74 void TransitionStarted() override
{}
76 void TransitionChanged() override
{
77 if (transition_page_
== -1 ||
78 model_
->transition().target_page
== transition_page_
) {
79 if (model_
->transition().progress
== 0)
80 ++transition_start_count_
;
81 if (model_
->transition().progress
== 1)
82 ++transition_end_count_
;
85 if ((expected_transition_start_
&&
86 transition_start_count_
== expected_transition_start_
) ||
87 (expected_transition_end_
&&
88 transition_end_count_
== expected_transition_end_
)) {
89 base::MessageLoop::current()->Quit();
93 PaginationModel
* model_
;
95 int expected_page_selection_
;
96 int expected_transition_start_
;
97 int expected_transition_end_
;
100 int transition_start_count_
;
101 int transition_end_count_
;
103 // Indicate which page index should be counted for |transition_start_count_|
104 // and |transition_end_count_|. -1 means all the pages should be counted.
105 int transition_page_
;
107 std::string selected_pages_
;
109 DISALLOW_COPY_AND_ASSIGN(TestPaginationModelObserver
);
112 class PaginationModelTest
: public testing::Test
{
114 PaginationModelTest() {}
115 ~PaginationModelTest() override
{}
117 // testing::Test overrides:
118 void SetUp() override
{
119 pagination_
.SetTotalPages(5);
120 pagination_
.SetTransitionDurations(1, 1);
121 observer_
.set_model(&pagination_
);
122 pagination_
.AddObserver(&observer_
);
124 void TearDown() override
{
125 pagination_
.RemoveObserver(&observer_
);
126 observer_
.set_model(NULL
);
130 void SetStartPageAndExpects(int start_page
,
131 int expected_selection
,
132 int expected_transition_start
,
133 int expected_transition_end
) {
134 observer_
.set_expected_page_selection(0);
135 pagination_
.SelectPage(start_page
, false /* animate */);
137 observer_
.set_expected_page_selection(expected_selection
);
138 observer_
.set_expected_transition_start(expected_transition_start
);
139 observer_
.set_expected_transition_end(expected_transition_end
);
142 PaginationModel pagination_
;
143 TestPaginationModelObserver observer_
;
146 base::MessageLoopForUI message_loop_
;
148 DISALLOW_COPY_AND_ASSIGN(PaginationModelTest
);
151 TEST_F(PaginationModelTest
, SelectPage
) {
152 pagination_
.SelectPage(2, false /* animate */);
153 pagination_
.SelectPage(4, false /* animate */);
154 pagination_
.SelectPage(3, false /* animate */);
155 pagination_
.SelectPage(1, false /* animate */);
157 EXPECT_EQ(0, observer_
.transition_start_count());
158 EXPECT_EQ(0, observer_
.transition_end_count());
159 EXPECT_EQ(4, observer_
.selection_count());
160 EXPECT_EQ(std::string("2 4 3 1"), observer_
.selected_pages());
162 // Nothing happens if select the same page.
163 pagination_
.SelectPage(1, false /* animate */);
164 EXPECT_EQ(4, observer_
.selection_count());
165 EXPECT_EQ(std::string("2 4 3 1"), observer_
.selected_pages());
168 TEST_F(PaginationModelTest
, SelectPageAnimated
) {
169 const int kStartPage
= 0;
172 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
173 pagination_
.SelectPage(1, true /* animate */);
174 base::MessageLoop::current()->Run();
175 EXPECT_EQ(1, observer_
.transition_start_count());
176 EXPECT_EQ(1, observer_
.transition_end_count());
177 EXPECT_EQ(1, observer_
.selection_count());
178 EXPECT_EQ(std::string("1"), observer_
.selected_pages());
180 // Two transitions in a row.
181 SetStartPageAndExpects(kStartPage
, 2, 0, 0);
182 pagination_
.SelectPage(1, true /* animate */);
183 pagination_
.SelectPage(3, true /* animate */);
184 base::MessageLoop::current()->Run();
185 EXPECT_EQ(2, observer_
.transition_start_count());
186 EXPECT_EQ(2, observer_
.transition_end_count());
187 EXPECT_EQ(2, observer_
.selection_count());
188 EXPECT_EQ(std::string("1 3"), observer_
.selected_pages());
190 // Transition to same page twice and only one should happen.
191 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
192 pagination_
.SelectPage(1, true /* animate */);
193 pagination_
.SelectPage(1, true /* animate */); // Ignored.
194 base::MessageLoop::current()->Run();
195 EXPECT_EQ(1, observer_
.transition_start_count());
196 EXPECT_EQ(1, observer_
.transition_end_count());
197 EXPECT_EQ(1, observer_
.selection_count());
198 EXPECT_EQ(std::string("1"), observer_
.selected_pages());
200 // More than two transitions and only the first and last would happen.
201 SetStartPageAndExpects(kStartPage
, 2, 0, 0);
202 pagination_
.SelectPage(1, true /* animate */);
203 pagination_
.SelectPage(3, true /* animate */); // Ignored
204 pagination_
.SelectPage(4, true /* animate */); // Ignored
205 pagination_
.SelectPage(2, true /* animate */);
206 base::MessageLoop::current()->Run();
207 EXPECT_EQ(2, observer_
.transition_start_count());
208 EXPECT_EQ(2, observer_
.transition_end_count());
209 EXPECT_EQ(2, observer_
.selection_count());
210 EXPECT_EQ(std::string("1 2"), observer_
.selected_pages());
212 // Multiple transitions with one transition that goes back to the original
213 // and followed by a new transition. Two transitions would happen. The first
214 // one will be reversed by the kStart transition and the second one will be
216 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
217 pagination_
.SelectPage(1, true /* animate */);
218 pagination_
.SelectPage(2, true /* animate */); // Ignored
219 pagination_
.SelectPage(kStartPage
, true /* animate */);
220 pagination_
.SelectPage(3, true /* animate */);
221 base::MessageLoop::current()->Run();
222 EXPECT_EQ(std::string("3"), observer_
.selected_pages());
225 TEST_F(PaginationModelTest
, SimpleScroll
) {
226 const int kStartPage
= 2;
228 // Scroll to the next page (negative delta) and finish it.
229 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
230 pagination_
.StartScroll();
231 pagination_
.UpdateScroll(-0.1);
232 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
233 pagination_
.EndScroll(false); // Finish transition
234 base::MessageLoop::current()->Run();
235 EXPECT_EQ(1, observer_
.selection_count());
237 // Scroll to the previous page (positive delta) and finish it.
238 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
239 pagination_
.StartScroll();
240 pagination_
.UpdateScroll(0.1);
241 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
242 pagination_
.EndScroll(false); // Finish transition
243 base::MessageLoop::current()->Run();
244 EXPECT_EQ(1, observer_
.selection_count());
246 // Scroll to the next page (negative delta) and cancel it.
247 SetStartPageAndExpects(kStartPage
, 0, 1, 0);
248 pagination_
.StartScroll();
249 pagination_
.UpdateScroll(-0.1);
250 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
251 pagination_
.EndScroll(true); // Cancel transition
252 base::MessageLoop::current()->Run();
253 EXPECT_EQ(0, observer_
.selection_count());
255 // Scroll to the previous page (position delta) and cancel it.
256 SetStartPageAndExpects(kStartPage
, 0, 1, 0);
257 pagination_
.StartScroll();
258 pagination_
.UpdateScroll(0.1);
259 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
260 pagination_
.EndScroll(true); // Cancel transition
261 base::MessageLoop::current()->Run();
262 EXPECT_EQ(0, observer_
.selection_count());
265 TEST_F(PaginationModelTest
, ScrollWithTransition
) {
266 const int kStartPage
= 2;
268 // Scroll to the next page (negative delta) with a transition in the same
270 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
271 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
+ 1, 0.5));
272 pagination_
.StartScroll();
273 pagination_
.UpdateScroll(-0.1);
274 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
275 EXPECT_EQ(0.6, pagination_
.transition().progress
);
276 pagination_
.EndScroll(false);
277 base::MessageLoop::current()->Run();
278 EXPECT_EQ(1, observer_
.selection_count());
280 // Scroll to the next page (negative delta) with a transition in a different
282 SetStartPageAndExpects(kStartPage
, 0, 1, 0);
283 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
- 1, 0.5));
284 pagination_
.StartScroll();
285 pagination_
.UpdateScroll(-0.1);
286 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
287 EXPECT_EQ(0.4, pagination_
.transition().progress
);
288 pagination_
.EndScroll(true);
290 // Scroll to the previous page (positive delta) with a transition in the same
292 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
293 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
- 1, 0.5));
294 pagination_
.StartScroll();
295 pagination_
.UpdateScroll(0.1);
296 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
297 EXPECT_EQ(0.6, pagination_
.transition().progress
);
298 pagination_
.EndScroll(false);
299 base::MessageLoop::current()->Run();
300 EXPECT_EQ(1, observer_
.selection_count());
302 // Scroll to the previous page (positive delta) with a transition in a
303 // different direction.
304 SetStartPageAndExpects(kStartPage
, 0, 1, 0);
305 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
+ 1, 0.5));
306 pagination_
.StartScroll();
307 pagination_
.UpdateScroll(0.1);
308 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
309 EXPECT_EQ(0.4, pagination_
.transition().progress
);
310 pagination_
.EndScroll(true);
313 TEST_F(PaginationModelTest
, LongScroll
) {
314 const int kStartPage
= 2;
316 // Scroll to the next page (negative delta) with a transition in the same
317 // direction. And scroll enough to change page twice.
318 SetStartPageAndExpects(kStartPage
, 2, 0, 0);
319 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
+ 1, 0.5));
320 pagination_
.StartScroll();
321 pagination_
.UpdateScroll(-0.1);
322 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
323 EXPECT_EQ(0.6, pagination_
.transition().progress
);
324 pagination_
.UpdateScroll(-0.5);
325 EXPECT_EQ(1, observer_
.selection_count());
326 pagination_
.UpdateScroll(-0.5);
327 EXPECT_EQ(kStartPage
+ 2, pagination_
.transition().target_page
);
328 pagination_
.EndScroll(false);
329 base::MessageLoop::current()->Run();
330 EXPECT_EQ(2, observer_
.selection_count());
332 // Scroll to the next page (negative delta) with a transition in a different
333 // direction. And scroll enough to revert it and switch page once.
334 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
335 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
- 1, 0.5));
336 pagination_
.StartScroll();
337 pagination_
.UpdateScroll(-0.1);
338 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
339 EXPECT_EQ(0.4, pagination_
.transition().progress
);
340 pagination_
.UpdateScroll(-0.5); // This clears the transition.
341 pagination_
.UpdateScroll(-0.5); // This starts a new transition.
342 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
343 pagination_
.EndScroll(false);
344 base::MessageLoop::current()->Run();
345 EXPECT_EQ(1, observer_
.selection_count());
347 // Similar cases as above but in the opposite direction.
348 // Scroll to the previous page (positive delta) with a transition in the same
349 // direction. And scroll enough to change page twice.
350 SetStartPageAndExpects(kStartPage
, 2, 0, 0);
351 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
- 1, 0.5));
352 pagination_
.StartScroll();
353 pagination_
.UpdateScroll(0.1);
354 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
355 EXPECT_EQ(0.6, pagination_
.transition().progress
);
356 pagination_
.UpdateScroll(0.5);
357 EXPECT_EQ(1, observer_
.selection_count());
358 pagination_
.UpdateScroll(0.5);
359 EXPECT_EQ(kStartPage
- 2, pagination_
.transition().target_page
);
360 pagination_
.EndScroll(false);
361 base::MessageLoop::current()->Run();
362 EXPECT_EQ(2, observer_
.selection_count());
364 // Scroll to the previous page (positive delta) with a transition in a
365 // different direction. And scroll enough to revert it and switch page once.
366 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
367 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
+ 1, 0.5));
368 pagination_
.StartScroll();
369 pagination_
.UpdateScroll(0.1);
370 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
371 EXPECT_EQ(0.4, pagination_
.transition().progress
);
372 pagination_
.UpdateScroll(0.5); // This clears the transition.
373 pagination_
.UpdateScroll(0.5); // This starts a new transition.
374 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
375 pagination_
.EndScroll(false);
376 base::MessageLoop::current()->Run();
377 EXPECT_EQ(1, observer_
.selection_count());
380 TEST_F(PaginationModelTest
, FireTransitionZero
) {
381 const int kStartPage
= 2;
383 // Scroll to next page then revert the scroll and make sure transition
384 // progress 0 is fired when previous scroll is cleared.
385 SetStartPageAndExpects(kStartPage
, 0, 0, 0);
386 pagination_
.StartScroll();
387 pagination_
.UpdateScroll(-0.1);
389 int target_page
= kStartPage
+ 1;
390 EXPECT_EQ(target_page
, pagination_
.transition().target_page
);
391 observer_
.set_transition_page(target_page
);
393 pagination_
.UpdateScroll(0.2); // This clears the transition.
394 EXPECT_EQ(1, observer_
.transition_start_count());
395 pagination_
.EndScroll(true); // Cancel transition.
397 // Similar to above but in the other direction.
398 SetStartPageAndExpects(kStartPage
, 0, 0, 0);
399 pagination_
.StartScroll();
400 pagination_
.UpdateScroll(0.1);
402 target_page
= kStartPage
- 1;
403 EXPECT_EQ(target_page
, pagination_
.transition().target_page
);
404 observer_
.set_transition_page(target_page
);
406 pagination_
.UpdateScroll(-0.2); // This clears the transition.
407 EXPECT_EQ(1, observer_
.transition_start_count());
408 pagination_
.EndScroll(true); // Cancel transition.
411 TEST_F(PaginationModelTest
, SelectedPageIsLost
) {
412 pagination_
.SetTotalPages(2);
413 // The selected page is set to 0 once the total number of pages are set.
414 EXPECT_EQ(0, pagination_
.selected_page());
416 pagination_
.SelectPage(1, false /* animate */);
417 EXPECT_EQ(1, pagination_
.selected_page());
419 // The selected page is unchanged if it's still valid.
420 pagination_
.SetTotalPages(3);
421 EXPECT_EQ(1, pagination_
.selected_page());
422 pagination_
.SetTotalPages(2);
423 EXPECT_EQ(1, pagination_
.selected_page());
425 // But if the currently selected_page exceeds the total number of pages,
426 // it automatically switches to the last page.
427 pagination_
.SetTotalPages(1);
428 EXPECT_EQ(0, pagination_
.selected_page());
432 } // namespace app_list