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/stringprintf.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 virtual ~TestPaginationModelObserver() {}
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::StringPrintf("%d", page
));
63 // PaginationModelObserver overrides:
64 virtual void TotalPagesChanged() OVERRIDE
{}
65 virtual void SelectedPageChanged(int old_selected
,
66 int new_selected
) OVERRIDE
{
67 AppendSelectedPage(new_selected
);
69 if (expected_page_selection_
&&
70 selection_count_
== expected_page_selection_
) {
71 base::MessageLoop::current()->Quit();
75 virtual void TransitionStarted() OVERRIDE
{
78 virtual void TransitionChanged() OVERRIDE
{
79 if (transition_page_
== -1 ||
80 model_
->transition().target_page
== transition_page_
) {
81 if (model_
->transition().progress
== 0)
82 ++transition_start_count_
;
83 if (model_
->transition().progress
== 1)
84 ++transition_end_count_
;
87 if ((expected_transition_start_
&&
88 transition_start_count_
== expected_transition_start_
) ||
89 (expected_transition_end_
&&
90 transition_end_count_
== expected_transition_end_
)) {
91 base::MessageLoop::current()->Quit();
95 PaginationModel
* model_
;
97 int expected_page_selection_
;
98 int expected_transition_start_
;
99 int expected_transition_end_
;
101 int selection_count_
;
102 int transition_start_count_
;
103 int transition_end_count_
;
105 // Indicate which page index should be counted for |transition_start_count_|
106 // and |transition_end_count_|. -1 means all the pages should be counted.
107 int transition_page_
;
109 std::string selected_pages_
;
111 DISALLOW_COPY_AND_ASSIGN(TestPaginationModelObserver
);
114 class PaginationModelTest
: public testing::Test
{
116 PaginationModelTest() {}
117 virtual ~PaginationModelTest() {}
119 // testing::Test overrides:
120 virtual void SetUp() OVERRIDE
{
121 pagination_
.SetTotalPages(5);
122 pagination_
.SetTransitionDurations(1, 1);
123 observer_
.set_model(&pagination_
);
124 pagination_
.AddObserver(&observer_
);
126 virtual void TearDown() OVERRIDE
{
127 pagination_
.RemoveObserver(&observer_
);
128 observer_
.set_model(NULL
);
132 void SetStartPageAndExpects(int start_page
,
133 int expected_selection
,
134 int expected_transition_start
,
135 int expected_transition_end
) {
136 observer_
.set_expected_page_selection(0);
137 pagination_
.SelectPage(start_page
, false /* animate */);
139 observer_
.set_expected_page_selection(expected_selection
);
140 observer_
.set_expected_transition_start(expected_transition_start
);
141 observer_
.set_expected_transition_end(expected_transition_end
);
144 PaginationModel pagination_
;
145 TestPaginationModelObserver observer_
;
148 base::MessageLoopForUI message_loop_
;
150 DISALLOW_COPY_AND_ASSIGN(PaginationModelTest
);
153 TEST_F(PaginationModelTest
, SelectPage
) {
154 pagination_
.SelectPage(2, false /* animate */);
155 pagination_
.SelectPage(4, false /* animate */);
156 pagination_
.SelectPage(3, false /* animate */);
157 pagination_
.SelectPage(1, false /* animate */);
159 EXPECT_EQ(0, observer_
.transition_start_count());
160 EXPECT_EQ(0, observer_
.transition_end_count());
161 EXPECT_EQ(4, observer_
.selection_count());
162 EXPECT_EQ(std::string("2 4 3 1"), observer_
.selected_pages());
164 // Nothing happens if select the same page.
165 pagination_
.SelectPage(1, false /* animate */);
166 EXPECT_EQ(4, observer_
.selection_count());
167 EXPECT_EQ(std::string("2 4 3 1"), observer_
.selected_pages());
170 TEST_F(PaginationModelTest
, SelectPageAnimated
) {
171 const int kStartPage
= 0;
174 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
175 pagination_
.SelectPage(1, true /* animate */);
176 base::MessageLoop::current()->Run();
177 EXPECT_EQ(1, observer_
.transition_start_count());
178 EXPECT_EQ(1, observer_
.transition_end_count());
179 EXPECT_EQ(1, observer_
.selection_count());
180 EXPECT_EQ(std::string("1"), observer_
.selected_pages());
182 // Two transitions in a row.
183 SetStartPageAndExpects(kStartPage
, 2, 0, 0);
184 pagination_
.SelectPage(1, true /* animate */);
185 pagination_
.SelectPage(3, true /* animate */);
186 base::MessageLoop::current()->Run();
187 EXPECT_EQ(2, observer_
.transition_start_count());
188 EXPECT_EQ(2, observer_
.transition_end_count());
189 EXPECT_EQ(2, observer_
.selection_count());
190 EXPECT_EQ(std::string("1 3"), observer_
.selected_pages());
192 // Transition to same page twice and only one should happen.
193 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
194 pagination_
.SelectPage(1, true /* animate */);
195 pagination_
.SelectPage(1, true /* animate */); // Ignored.
196 base::MessageLoop::current()->Run();
197 EXPECT_EQ(1, observer_
.transition_start_count());
198 EXPECT_EQ(1, observer_
.transition_end_count());
199 EXPECT_EQ(1, observer_
.selection_count());
200 EXPECT_EQ(std::string("1"), observer_
.selected_pages());
202 // More than two transitions and only the first and last would happen.
203 SetStartPageAndExpects(kStartPage
, 2, 0, 0);
204 pagination_
.SelectPage(1, true /* animate */);
205 pagination_
.SelectPage(3, true /* animate */); // Ignored
206 pagination_
.SelectPage(4, true /* animate */); // Ignored
207 pagination_
.SelectPage(2, true /* animate */);
208 base::MessageLoop::current()->Run();
209 EXPECT_EQ(2, observer_
.transition_start_count());
210 EXPECT_EQ(2, observer_
.transition_end_count());
211 EXPECT_EQ(2, observer_
.selection_count());
212 EXPECT_EQ(std::string("1 2"), observer_
.selected_pages());
214 // Multiple transitions with one transition that goes back to the original
215 // and followed by a new transition. Two transitions would happen. The first
216 // one will be reversed by the kStart transition and the second one will be
218 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
219 pagination_
.SelectPage(1, true /* animate */);
220 pagination_
.SelectPage(2, true /* animate */); // Ignored
221 pagination_
.SelectPage(kStartPage
, true /* animate */);
222 pagination_
.SelectPage(3, true /* animate */);
223 base::MessageLoop::current()->Run();
224 EXPECT_EQ(std::string("3"), observer_
.selected_pages());
227 TEST_F(PaginationModelTest
, SimpleScroll
) {
228 const int kStartPage
= 2;
230 // Scroll to the next page (negative delta) and finish it.
231 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
232 pagination_
.StartScroll();
233 pagination_
.UpdateScroll(-0.1);
234 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
235 pagination_
.EndScroll(false); // Finish transition
236 base::MessageLoop::current()->Run();
237 EXPECT_EQ(1, observer_
.selection_count());
239 // Scroll to the previous page (positive delta) and finish it.
240 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
241 pagination_
.StartScroll();
242 pagination_
.UpdateScroll(0.1);
243 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
244 pagination_
.EndScroll(false); // Finish transition
245 base::MessageLoop::current()->Run();
246 EXPECT_EQ(1, observer_
.selection_count());
248 // Scroll to the next page (negative delta) and cancel it.
249 SetStartPageAndExpects(kStartPage
, 0, 1, 0);
250 pagination_
.StartScroll();
251 pagination_
.UpdateScroll(-0.1);
252 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
253 pagination_
.EndScroll(true); // Cancel transition
254 base::MessageLoop::current()->Run();
255 EXPECT_EQ(0, observer_
.selection_count());
257 // Scroll to the previous page (position delta) and cancel it.
258 SetStartPageAndExpects(kStartPage
, 0, 1, 0);
259 pagination_
.StartScroll();
260 pagination_
.UpdateScroll(0.1);
261 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
262 pagination_
.EndScroll(true); // Cancel transition
263 base::MessageLoop::current()->Run();
264 EXPECT_EQ(0, observer_
.selection_count());
267 TEST_F(PaginationModelTest
, ScrollWithTransition
) {
268 const int kStartPage
= 2;
270 // Scroll to the next page (negative delta) with a transition in the same
272 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
273 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
+ 1, 0.5));
274 pagination_
.StartScroll();
275 pagination_
.UpdateScroll(-0.1);
276 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
277 EXPECT_EQ(0.6, pagination_
.transition().progress
);
278 pagination_
.EndScroll(false);
279 base::MessageLoop::current()->Run();
280 EXPECT_EQ(1, observer_
.selection_count());
282 // Scroll to the next page (negative delta) with a transition in a different
284 SetStartPageAndExpects(kStartPage
, 0, 1, 0);
285 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
- 1, 0.5));
286 pagination_
.StartScroll();
287 pagination_
.UpdateScroll(-0.1);
288 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
289 EXPECT_EQ(0.4, pagination_
.transition().progress
);
290 pagination_
.EndScroll(true);
292 // Scroll to the previous page (positive delta) with a transition in the same
294 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
295 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
- 1, 0.5));
296 pagination_
.StartScroll();
297 pagination_
.UpdateScroll(0.1);
298 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
299 EXPECT_EQ(0.6, pagination_
.transition().progress
);
300 pagination_
.EndScroll(false);
301 base::MessageLoop::current()->Run();
302 EXPECT_EQ(1, observer_
.selection_count());
304 // Scroll to the previous page (positive delta) with a transition in a
305 // different direction.
306 SetStartPageAndExpects(kStartPage
, 0, 1, 0);
307 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
+ 1, 0.5));
308 pagination_
.StartScroll();
309 pagination_
.UpdateScroll(0.1);
310 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
311 EXPECT_EQ(0.4, pagination_
.transition().progress
);
312 pagination_
.EndScroll(true);
315 TEST_F(PaginationModelTest
, LongScroll
) {
316 const int kStartPage
= 2;
318 // Scroll to the next page (negative delta) with a transition in the same
319 // direction. And scroll enough to change page twice.
320 SetStartPageAndExpects(kStartPage
, 2, 0, 0);
321 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
+ 1, 0.5));
322 pagination_
.StartScroll();
323 pagination_
.UpdateScroll(-0.1);
324 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
325 EXPECT_EQ(0.6, pagination_
.transition().progress
);
326 pagination_
.UpdateScroll(-0.5);
327 EXPECT_EQ(1, observer_
.selection_count());
328 pagination_
.UpdateScroll(-0.5);
329 EXPECT_EQ(kStartPage
+ 2, pagination_
.transition().target_page
);
330 pagination_
.EndScroll(false);
331 base::MessageLoop::current()->Run();
332 EXPECT_EQ(2, observer_
.selection_count());
334 // Scroll to the next page (negative delta) with a transition in a different
335 // direction. And scroll enough to revert it and switch page once.
336 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
337 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
- 1, 0.5));
338 pagination_
.StartScroll();
339 pagination_
.UpdateScroll(-0.1);
340 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
341 EXPECT_EQ(0.4, pagination_
.transition().progress
);
342 pagination_
.UpdateScroll(-0.5); // This clears the transition.
343 pagination_
.UpdateScroll(-0.5); // This starts a new transition.
344 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
345 pagination_
.EndScroll(false);
346 base::MessageLoop::current()->Run();
347 EXPECT_EQ(1, observer_
.selection_count());
349 // Similar cases as above but in the opposite direction.
350 // Scroll to the previous page (positive delta) with a transition in the same
351 // direction. And scroll enough to change page twice.
352 SetStartPageAndExpects(kStartPage
, 2, 0, 0);
353 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
- 1, 0.5));
354 pagination_
.StartScroll();
355 pagination_
.UpdateScroll(0.1);
356 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
357 EXPECT_EQ(0.6, pagination_
.transition().progress
);
358 pagination_
.UpdateScroll(0.5);
359 EXPECT_EQ(1, observer_
.selection_count());
360 pagination_
.UpdateScroll(0.5);
361 EXPECT_EQ(kStartPage
- 2, pagination_
.transition().target_page
);
362 pagination_
.EndScroll(false);
363 base::MessageLoop::current()->Run();
364 EXPECT_EQ(2, observer_
.selection_count());
366 // Scroll to the previous page (positive delta) with a transition in a
367 // different direction. And scroll enough to revert it and switch page once.
368 SetStartPageAndExpects(kStartPage
, 1, 0, 0);
369 pagination_
.SetTransition(PaginationModel::Transition(kStartPage
+ 1, 0.5));
370 pagination_
.StartScroll();
371 pagination_
.UpdateScroll(0.1);
372 EXPECT_EQ(kStartPage
+ 1, pagination_
.transition().target_page
);
373 EXPECT_EQ(0.4, pagination_
.transition().progress
);
374 pagination_
.UpdateScroll(0.5); // This clears the transition.
375 pagination_
.UpdateScroll(0.5); // This starts a new transition.
376 EXPECT_EQ(kStartPage
- 1, pagination_
.transition().target_page
);
377 pagination_
.EndScroll(false);
378 base::MessageLoop::current()->Run();
379 EXPECT_EQ(1, observer_
.selection_count());
382 TEST_F(PaginationModelTest
, FireTransitionZero
) {
383 const int kStartPage
= 2;
385 // Scroll to next page then revert the scroll and make sure transition
386 // progress 0 is fired when previous scroll is cleared.
387 SetStartPageAndExpects(kStartPage
, 0, 0, 0);
388 pagination_
.StartScroll();
389 pagination_
.UpdateScroll(-0.1);
391 int target_page
= kStartPage
+ 1;
392 EXPECT_EQ(target_page
, pagination_
.transition().target_page
);
393 observer_
.set_transition_page(target_page
);
395 pagination_
.UpdateScroll(0.2); // This clears the transition.
396 EXPECT_EQ(1, observer_
.transition_start_count());
397 pagination_
.EndScroll(true); // Cancel transition.
399 // Similar to above but in the other direction.
400 SetStartPageAndExpects(kStartPage
, 0, 0, 0);
401 pagination_
.StartScroll();
402 pagination_
.UpdateScroll(0.1);
404 target_page
= kStartPage
- 1;
405 EXPECT_EQ(target_page
, pagination_
.transition().target_page
);
406 observer_
.set_transition_page(target_page
);
408 pagination_
.UpdateScroll(-0.2); // This clears the transition.
409 EXPECT_EQ(1, observer_
.transition_start_count());
410 pagination_
.EndScroll(true); // Cancel transition.
413 TEST_F(PaginationModelTest
, SelectedPageIsLost
) {
414 pagination_
.SetTotalPages(2);
415 // The selected page is set to 0 once the total number of pages are set.
416 EXPECT_EQ(0, pagination_
.selected_page());
418 pagination_
.SelectPage(1, false /* animate */);
419 EXPECT_EQ(1, pagination_
.selected_page());
421 // The selected page is unchanged if it's still valid.
422 pagination_
.SetTotalPages(3);
423 EXPECT_EQ(1, pagination_
.selected_page());
424 pagination_
.SetTotalPages(2);
425 EXPECT_EQ(1, pagination_
.selected_page());
427 // But if the currently selected_page exceeds the total number of pages,
428 // it automatically switches to the last page.
429 pagination_
.SetTotalPages(1);
430 EXPECT_EQ(0, pagination_
.selected_page());
434 } // namespace app_list