Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / app_list / views / app_list_view_unittest.cc
bloba36882e9d5152eec690e9ffeb06273ffdd666527
1 // Copyright 2014 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/views/app_list_view.h"
7 #include <string>
8 #include <vector>
10 #include "base/command_line.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/app_list/app_list_constants.h"
16 #include "ui/app_list/app_list_switches.h"
17 #include "ui/app_list/pagination_model.h"
18 #include "ui/app_list/search_box_model.h"
19 #include "ui/app_list/test/app_list_test_model.h"
20 #include "ui/app_list/test/app_list_test_view_delegate.h"
21 #include "ui/app_list/test/test_search_result.h"
22 #include "ui/app_list/views/app_list_folder_view.h"
23 #include "ui/app_list/views/app_list_main_view.h"
24 #include "ui/app_list/views/apps_container_view.h"
25 #include "ui/app_list/views/apps_grid_view.h"
26 #include "ui/app_list/views/contents_view.h"
27 #include "ui/app_list/views/search_box_view.h"
28 #include "ui/app_list/views/search_result_page_view.h"
29 #include "ui/app_list/views/search_result_tile_item_view.h"
30 #include "ui/app_list/views/start_page_view.h"
31 #include "ui/app_list/views/test/apps_grid_view_test_api.h"
32 #include "ui/app_list/views/tile_item_view.h"
33 #include "ui/events/event_utils.h"
34 #include "ui/views/controls/textfield/textfield.h"
35 #include "ui/views/test/test_views_delegate.h"
36 #include "ui/views/test/views_test_base.h"
37 #include "ui/views/views_delegate.h"
38 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
40 namespace app_list {
41 namespace test {
43 namespace {
45 enum TestType {
46 TEST_TYPE_START = 0,
47 NORMAL = TEST_TYPE_START,
48 LANDSCAPE,
49 EXPERIMENTAL,
50 TEST_TYPE_END,
53 template <class T>
54 size_t GetVisibleViews(const std::vector<T*>& tiles) {
55 size_t count = 0;
56 for (const auto& tile : tiles) {
57 if (tile->visible())
58 count++;
60 return count;
63 void SimulateClick(views::View* view) {
64 gfx::Point center = view->GetLocalBounds().CenterPoint();
65 view->OnMousePressed(ui::MouseEvent(
66 ui::ET_MOUSE_PRESSED, center, center, ui::EventTimeForNow(),
67 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
68 view->OnMouseReleased(ui::MouseEvent(
69 ui::ET_MOUSE_RELEASED, center, center, ui::EventTimeForNow(),
70 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
73 // Choose a set that is 3 regular app list pages and 2 landscape app list pages.
74 const int kInitialItems = 34;
76 class TestStartPageSearchResult : public TestSearchResult {
77 public:
78 TestStartPageSearchResult() { set_display_type(DISPLAY_RECOMMENDATION); }
79 ~TestStartPageSearchResult() override {}
81 private:
82 DISALLOW_COPY_AND_ASSIGN(TestStartPageSearchResult);
85 // Allows the same tests to run with different contexts: either an Ash-style
86 // root window or a desktop window tree host.
87 class AppListViewTestContext {
88 public:
89 AppListViewTestContext(int test_type, gfx::NativeView parent);
90 ~AppListViewTestContext();
92 // Test displaying the app list and performs a standard set of checks on its
93 // top level views. Then closes the window.
94 void RunDisplayTest();
96 // Hides and reshows the app list with a folder open, expecting the main grid
97 // view to be shown.
98 void RunReshowWithOpenFolderTest();
100 // Tests that pressing the search box's back button navigates correctly.
101 void RunBackTest();
103 // Tests displaying of the experimental app list and shows the start page.
104 void RunStartPageTest();
106 // Tests switching rapidly between multiple pages of the launcher.
107 void RunPageSwitchingAnimationTest();
109 // Tests changing the App List profile.
110 void RunProfileChangeTest();
112 // Tests displaying of the search results.
113 void RunSearchResultsTest();
115 // Tests displaying the app list overlay.
116 void RunAppListOverlayTest();
118 // A standard set of checks on a view, e.g., ensuring it is drawn and visible.
119 static void CheckView(views::View* subview);
121 // Invoked when the Widget is closing, and the view it contains is about to
122 // be torn down. This only occurs in a run loop and will be used as a signal
123 // to quit.
124 void NativeWidgetClosing() {
125 view_ = NULL;
126 run_loop_->Quit();
129 // Whether the experimental "landscape" app launcher UI is being tested.
130 bool is_landscape() const {
131 return test_type_ == LANDSCAPE || test_type_ == EXPERIMENTAL;
134 private:
135 // Switches the launcher to |state| and lays out to ensure all launcher pages
136 // are in the correct position. Checks that the state is where it should be
137 // and returns false on failure.
138 bool SetAppListState(AppListModel::State state);
140 // Returns true if all of the pages are in their correct position for |state|.
141 bool IsStateShown(AppListModel::State state);
143 // Shows the app list and waits until a paint occurs.
144 void Show();
146 // Closes the app list. This sets |view_| to NULL.
147 void Close();
149 // Checks the search box widget is at |expected| in the contents view's
150 // coordinate space.
151 bool CheckSearchBoxWidget(const gfx::Rect& expected);
153 // Gets the PaginationModel owned by |view_|.
154 PaginationModel* GetPaginationModel();
156 const TestType test_type_;
157 scoped_ptr<base::RunLoop> run_loop_;
158 app_list::AppListView* view_; // Owned by native widget.
159 scoped_ptr<app_list::test::AppListTestViewDelegate> delegate_;
161 DISALLOW_COPY_AND_ASSIGN(AppListViewTestContext);
164 // Extend the regular AppListTestViewDelegate to communicate back to the test
165 // context. Note the test context doesn't simply inherit this, because the
166 // delegate is owned by the view.
167 class UnitTestViewDelegate : public app_list::test::AppListTestViewDelegate {
168 public:
169 explicit UnitTestViewDelegate(AppListViewTestContext* parent)
170 : parent_(parent) {}
172 // Overridden from app_list::AppListViewDelegate:
173 bool ShouldCenterWindow() const override {
174 return app_list::switches::IsCenteredAppListEnabled();
177 // Overridden from app_list::test::AppListTestViewDelegate:
178 void ViewClosing() override { parent_->NativeWidgetClosing(); }
180 private:
181 AppListViewTestContext* parent_;
183 DISALLOW_COPY_AND_ASSIGN(UnitTestViewDelegate);
186 AppListViewTestContext::AppListViewTestContext(int test_type,
187 gfx::NativeView parent)
188 : test_type_(static_cast<TestType>(test_type)) {
189 switch (test_type_) {
190 case NORMAL:
191 base::CommandLine::ForCurrentProcess()->AppendSwitch(
192 switches::kDisableExperimentalAppList);
193 break;
194 case LANDSCAPE:
195 base::CommandLine::ForCurrentProcess()->AppendSwitch(
196 switches::kDisableExperimentalAppList);
197 base::CommandLine::ForCurrentProcess()->AppendSwitch(
198 switches::kEnableCenteredAppList);
199 break;
200 case EXPERIMENTAL:
201 base::CommandLine::ForCurrentProcess()->AppendSwitch(
202 switches::kEnableExperimentalAppList);
203 break;
204 default:
205 NOTREACHED();
206 break;
209 delegate_.reset(new UnitTestViewDelegate(this));
210 view_ = new app_list::AppListView(delegate_.get());
212 // Initialize centered around a point that ensures the window is wholly shown.
213 view_->InitAsBubbleAtFixedLocation(parent,
215 gfx::Point(300, 300),
216 views::BubbleBorder::FLOAT,
217 false /* border_accepts_events */);
220 AppListViewTestContext::~AppListViewTestContext() {
221 // The view observes the PaginationModel which is about to get destroyed, so
222 // if the view is not already deleted by the time this destructor is called,
223 // there will be problems.
224 EXPECT_FALSE(view_);
227 // static
228 void AppListViewTestContext::CheckView(views::View* subview) {
229 ASSERT_TRUE(subview);
230 EXPECT_TRUE(subview->parent());
231 EXPECT_TRUE(subview->visible());
232 EXPECT_TRUE(subview->IsDrawn());
233 EXPECT_FALSE(subview->bounds().IsEmpty());
236 bool AppListViewTestContext::SetAppListState(AppListModel::State state) {
237 ContentsView* contents_view = view_->app_list_main_view()->contents_view();
238 contents_view->SetActiveState(state);
239 contents_view->Layout();
240 return IsStateShown(state);
243 bool AppListViewTestContext::IsStateShown(AppListModel::State state) {
244 ContentsView* contents_view = view_->app_list_main_view()->contents_view();
245 bool success = true;
246 for (int i = 0; i < contents_view->NumLauncherPages(); ++i) {
247 success = success &&
248 (contents_view->GetPageView(i)->GetPageBoundsForState(state) ==
249 contents_view->GetPageView(i)->bounds());
251 return success && state == delegate_->GetTestModel()->state();
254 void AppListViewTestContext::Show() {
255 view_->GetWidget()->Show();
256 run_loop_.reset(new base::RunLoop);
257 view_->SetNextPaintCallback(run_loop_->QuitClosure());
258 run_loop_->Run();
260 EXPECT_TRUE(view_->GetWidget()->IsVisible());
263 void AppListViewTestContext::Close() {
264 view_->GetWidget()->Close();
265 run_loop_.reset(new base::RunLoop);
266 run_loop_->Run();
268 // |view_| should have been deleted and set to NULL via ViewClosing().
269 EXPECT_FALSE(view_);
272 bool AppListViewTestContext::CheckSearchBoxWidget(const gfx::Rect& expected) {
273 ContentsView* contents_view = view_->app_list_main_view()->contents_view();
274 // Adjust for the search box view's shadow.
275 gfx::Rect expected_with_shadow =
276 view_->app_list_main_view()
277 ->search_box_view()
278 ->GetViewBoundsForSearchBoxContentsBounds(expected);
279 gfx::Point point = expected_with_shadow.origin();
280 views::View::ConvertPointToScreen(contents_view, &point);
282 return gfx::Rect(point, expected_with_shadow.size()) ==
283 view_->search_box_widget()->GetWindowBoundsInScreen();
286 PaginationModel* AppListViewTestContext::GetPaginationModel() {
287 return view_->GetAppsPaginationModel();
290 void AppListViewTestContext::RunDisplayTest() {
291 EXPECT_FALSE(view_->GetWidget()->IsVisible());
292 EXPECT_EQ(-1, GetPaginationModel()->total_pages());
293 delegate_->GetTestModel()->PopulateApps(kInitialItems);
295 Show();
297 // Explicitly enforce the exact dimensions of the app list. Feel free to
298 // change these if you need to (they are just here to prevent against
299 // accidental changes to the window size).
300 switch (test_type_) {
301 case NORMAL:
302 EXPECT_EQ("400x500", view_->bounds().size().ToString());
303 break;
304 case LANDSCAPE:
305 // NOTE: Height should not exceed 402, because otherwise there might not
306 // be enough space to accomodate the virtual keyboard. (LANDSCAPE mode is
307 // enabled by default when the virtual keyboard is enabled.)
308 EXPECT_EQ("576x402", view_->bounds().size().ToString());
309 break;
310 case EXPERIMENTAL:
311 EXPECT_EQ("768x570", view_->bounds().size().ToString());
312 break;
313 default:
314 NOTREACHED();
315 break;
318 if (is_landscape())
319 EXPECT_EQ(2, GetPaginationModel()->total_pages());
320 else
321 EXPECT_EQ(3, GetPaginationModel()->total_pages());
322 EXPECT_EQ(0, GetPaginationModel()->selected_page());
324 // Checks on the main view.
325 AppListMainView* main_view = view_->app_list_main_view();
326 EXPECT_NO_FATAL_FAILURE(CheckView(main_view));
327 EXPECT_NO_FATAL_FAILURE(CheckView(main_view->contents_view()));
329 AppListModel::State expected = test_type_ == EXPERIMENTAL
330 ? AppListModel::STATE_START
331 : AppListModel::STATE_APPS;
332 EXPECT_TRUE(main_view->contents_view()->IsStateActive(expected));
333 EXPECT_EQ(expected, delegate_->GetTestModel()->state());
335 Close();
338 void AppListViewTestContext::RunReshowWithOpenFolderTest() {
339 EXPECT_FALSE(view_->GetWidget()->IsVisible());
340 EXPECT_EQ(-1, GetPaginationModel()->total_pages());
342 AppListTestModel* model = delegate_->GetTestModel();
343 model->PopulateApps(kInitialItems);
344 const std::string folder_id =
345 model->MergeItems(model->top_level_item_list()->item_at(0)->id(),
346 model->top_level_item_list()->item_at(1)->id());
348 AppListFolderItem* folder_item = model->FindFolderItem(folder_id);
349 EXPECT_TRUE(folder_item);
351 Show();
353 // The main grid view should be showing initially.
354 AppListMainView* main_view = view_->app_list_main_view();
355 AppsContainerView* container_view =
356 main_view->contents_view()->apps_container_view();
357 EXPECT_NO_FATAL_FAILURE(CheckView(main_view));
358 EXPECT_NO_FATAL_FAILURE(CheckView(container_view->apps_grid_view()));
359 EXPECT_FALSE(container_view->app_list_folder_view()->visible());
361 AppsGridViewTestApi test_api(container_view->apps_grid_view());
362 test_api.PressItemAt(0);
364 // After pressing the folder item, the folder view should be showing.
365 EXPECT_NO_FATAL_FAILURE(CheckView(main_view));
366 EXPECT_NO_FATAL_FAILURE(CheckView(container_view->app_list_folder_view()));
367 EXPECT_FALSE(container_view->apps_grid_view()->visible());
369 view_->GetWidget()->Hide();
370 EXPECT_FALSE(view_->GetWidget()->IsVisible());
372 Show();
374 // The main grid view should be showing after a reshow.
375 EXPECT_NO_FATAL_FAILURE(CheckView(main_view));
376 EXPECT_NO_FATAL_FAILURE(CheckView(container_view->apps_grid_view()));
377 EXPECT_FALSE(container_view->app_list_folder_view()->visible());
379 Close();
382 void AppListViewTestContext::RunBackTest() {
383 if (test_type_ != EXPERIMENTAL) {
384 Close();
385 return;
388 EXPECT_FALSE(view_->GetWidget()->IsVisible());
389 EXPECT_EQ(-1, GetPaginationModel()->total_pages());
391 Show();
393 AppListMainView* main_view = view_->app_list_main_view();
394 ContentsView* contents_view = main_view->contents_view();
395 SearchBoxView* search_box_view = main_view->search_box_view();
397 // Show the apps grid.
398 SetAppListState(AppListModel::STATE_APPS);
399 EXPECT_NO_FATAL_FAILURE(CheckView(search_box_view->back_button()));
401 // The back button should return to the start page.
402 EXPECT_TRUE(contents_view->Back());
403 contents_view->Layout();
404 EXPECT_TRUE(IsStateShown(AppListModel::STATE_START));
405 EXPECT_FALSE(search_box_view->back_button()->visible());
407 // Show the apps grid again.
408 SetAppListState(AppListModel::STATE_APPS);
409 EXPECT_NO_FATAL_FAILURE(CheckView(search_box_view->back_button()));
411 // Pressing ESC should return to the start page.
412 view_->AcceleratorPressed(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
413 contents_view->Layout();
414 EXPECT_TRUE(IsStateShown(AppListModel::STATE_START));
415 EXPECT_FALSE(search_box_view->back_button()->visible());
417 // Pressing ESC from the start page should close the app list.
418 EXPECT_EQ(0, delegate_->dismiss_count());
419 view_->AcceleratorPressed(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
420 EXPECT_EQ(1, delegate_->dismiss_count());
422 // Show the search results.
423 base::string16 new_search_text = base::UTF8ToUTF16("apple");
424 search_box_view->search_box()->SetText(base::string16());
425 search_box_view->search_box()->InsertText(new_search_text);
426 contents_view->Layout();
427 EXPECT_TRUE(IsStateShown(AppListModel::STATE_SEARCH_RESULTS));
428 EXPECT_NO_FATAL_FAILURE(CheckView(search_box_view->back_button()));
430 // The back button should return to the start page.
431 EXPECT_TRUE(contents_view->Back());
432 contents_view->Layout();
433 EXPECT_TRUE(IsStateShown(AppListModel::STATE_START));
434 EXPECT_FALSE(search_box_view->back_button()->visible());
436 Close();
439 void AppListViewTestContext::RunStartPageTest() {
440 EXPECT_FALSE(view_->GetWidget()->IsVisible());
441 EXPECT_EQ(-1, GetPaginationModel()->total_pages());
442 AppListTestModel* model = delegate_->GetTestModel();
443 model->PopulateApps(3);
445 Show();
447 AppListMainView* main_view = view_->app_list_main_view();
448 StartPageView* start_page_view =
449 main_view->contents_view()->start_page_view();
450 // Checks on the main view.
451 EXPECT_NO_FATAL_FAILURE(CheckView(main_view));
452 EXPECT_NO_FATAL_FAILURE(CheckView(main_view->contents_view()));
453 if (test_type_ == EXPERIMENTAL) {
454 EXPECT_NO_FATAL_FAILURE(CheckView(start_page_view));
456 // Show the start page view.
457 EXPECT_TRUE(SetAppListState(AppListModel::STATE_START));
458 gfx::Size view_size(view_->GetPreferredSize());
460 // The "All apps" button should have its "parent background color" set
461 // to the tiles container's background color.
462 TileItemView* all_apps_button = start_page_view->all_apps_button();
463 EXPECT_TRUE(all_apps_button->visible());
464 EXPECT_EQ(kLabelBackgroundColor,
465 all_apps_button->parent_background_color());
467 // Simulate clicking the "All apps" button. Check that we navigate to the
468 // apps grid view.
469 SimulateClick(all_apps_button);
470 main_view->contents_view()->Layout();
471 EXPECT_TRUE(IsStateShown(AppListModel::STATE_APPS));
473 // Hiding and showing the search box should not affect the app list's
474 // preferred size. This is a regression test for http://crbug.com/386912.
475 EXPECT_EQ(view_size.ToString(), view_->GetPreferredSize().ToString());
477 // Check tiles hide and show on deletion and addition.
478 EXPECT_TRUE(SetAppListState(AppListModel::STATE_START));
479 model->results()->Add(new TestStartPageSearchResult());
480 start_page_view->UpdateForTesting();
481 EXPECT_EQ(1u, GetVisibleViews(start_page_view->tile_views()));
482 model->results()->DeleteAll();
483 start_page_view->UpdateForTesting();
484 EXPECT_EQ(0u, GetVisibleViews(start_page_view->tile_views()));
486 // Tiles should not update when the start page is not active but should be
487 // correct once the start page is shown.
488 EXPECT_TRUE(SetAppListState(AppListModel::STATE_APPS));
489 model->results()->Add(new TestStartPageSearchResult());
490 start_page_view->UpdateForTesting();
491 EXPECT_EQ(0u, GetVisibleViews(start_page_view->tile_views()));
492 EXPECT_TRUE(SetAppListState(AppListModel::STATE_START));
493 EXPECT_EQ(1u, GetVisibleViews(start_page_view->tile_views()));
494 } else {
495 EXPECT_EQ(NULL, start_page_view);
498 Close();
501 void AppListViewTestContext::RunPageSwitchingAnimationTest() {
502 if (test_type_ == EXPERIMENTAL) {
503 Show();
505 AppListMainView* main_view = view_->app_list_main_view();
506 // Checks on the main view.
507 EXPECT_NO_FATAL_FAILURE(CheckView(main_view));
508 EXPECT_NO_FATAL_FAILURE(CheckView(main_view->contents_view()));
510 ContentsView* contents_view = main_view->contents_view();
512 contents_view->SetActiveState(AppListModel::STATE_START);
513 contents_view->Layout();
515 IsStateShown(AppListModel::STATE_START);
517 // Change pages. View should not have moved without Layout().
518 contents_view->SetActiveState(AppListModel::STATE_SEARCH_RESULTS);
519 IsStateShown(AppListModel::STATE_START);
521 // Change to a third page. This queues up the second animation behind the
522 // first.
523 contents_view->SetActiveState(AppListModel::STATE_APPS);
524 IsStateShown(AppListModel::STATE_START);
526 // Call Layout(). Should jump to the third page.
527 contents_view->Layout();
528 IsStateShown(AppListModel::STATE_APPS);
531 Close();
534 void AppListViewTestContext::RunProfileChangeTest() {
535 EXPECT_FALSE(view_->GetWidget()->IsVisible());
536 EXPECT_EQ(-1, GetPaginationModel()->total_pages());
537 delegate_->GetTestModel()->PopulateApps(kInitialItems);
539 Show();
541 if (is_landscape())
542 EXPECT_EQ(2, GetPaginationModel()->total_pages());
543 else
544 EXPECT_EQ(3, GetPaginationModel()->total_pages());
546 // Change the profile. The original model needs to be kept alive for
547 // observers to unregister themselves.
548 scoped_ptr<AppListTestModel> original_test_model(
549 delegate_->ReleaseTestModel());
550 delegate_->set_next_profile_app_count(1);
552 // The original ContentsView is destroyed here.
553 view_->SetProfileByPath(base::FilePath());
554 EXPECT_EQ(1, GetPaginationModel()->total_pages());
556 StartPageView* start_page_view =
557 view_->app_list_main_view()->contents_view()->start_page_view();
558 if (test_type_ == EXPERIMENTAL)
559 EXPECT_NO_FATAL_FAILURE(CheckView(start_page_view));
560 else
561 EXPECT_EQ(NULL, start_page_view);
563 // New model updates should be processed by the start page view.
564 delegate_->GetTestModel()->results()->Add(new TestStartPageSearchResult());
565 if (test_type_ == EXPERIMENTAL) {
566 start_page_view->UpdateForTesting();
567 EXPECT_EQ(1u, GetVisibleViews(start_page_view->tile_views()));
570 // Old model updates should be ignored.
571 original_test_model->results()->Add(new TestStartPageSearchResult());
572 original_test_model->results()->Add(new TestStartPageSearchResult());
573 if (test_type_ == EXPERIMENTAL) {
574 start_page_view->UpdateForTesting();
575 EXPECT_EQ(1u, GetVisibleViews(start_page_view->tile_views()));
578 Close();
581 void AppListViewTestContext::RunSearchResultsTest() {
582 EXPECT_FALSE(view_->GetWidget()->IsVisible());
583 EXPECT_EQ(-1, GetPaginationModel()->total_pages());
584 AppListTestModel* model = delegate_->GetTestModel();
585 model->PopulateApps(3);
587 Show();
589 AppListMainView* main_view = view_->app_list_main_view();
590 ContentsView* contents_view = main_view->contents_view();
591 EXPECT_TRUE(SetAppListState(AppListModel::STATE_APPS));
593 // Show the search results.
594 contents_view->ShowSearchResults(true);
595 contents_view->Layout();
596 EXPECT_TRUE(contents_view->IsStateActive(AppListModel::STATE_SEARCH_RESULTS));
598 EXPECT_TRUE(IsStateShown(AppListModel::STATE_SEARCH_RESULTS));
600 // Hide the search results.
601 contents_view->ShowSearchResults(false);
602 contents_view->Layout();
604 // Check that we return to the page that we were on before the search.
605 EXPECT_TRUE(IsStateShown(AppListModel::STATE_APPS));
607 if (test_type_ == EXPERIMENTAL) {
608 // Check that typing into the search box triggers the search page.
609 EXPECT_TRUE(SetAppListState(AppListModel::STATE_START));
610 view_->Layout();
611 EXPECT_TRUE(IsStateShown(AppListModel::STATE_START));
613 base::string16 search_text = base::UTF8ToUTF16("test");
614 main_view->search_box_view()->search_box()->SetText(base::string16());
615 main_view->search_box_view()->search_box()->InsertText(search_text);
616 // Check that the current search is using |search_text|.
617 EXPECT_EQ(search_text, delegate_->GetTestModel()->search_box()->text());
618 EXPECT_EQ(search_text, main_view->search_box_view()->search_box()->text());
619 contents_view->Layout();
620 EXPECT_TRUE(
621 contents_view->IsStateActive(AppListModel::STATE_SEARCH_RESULTS));
622 EXPECT_TRUE(
623 CheckSearchBoxWidget(contents_view->GetDefaultSearchBoxBounds()));
625 // Check that typing into the search box triggers the search page.
626 EXPECT_TRUE(SetAppListState(AppListModel::STATE_APPS));
627 contents_view->Layout();
628 EXPECT_TRUE(IsStateShown(AppListModel::STATE_APPS));
629 EXPECT_TRUE(
630 CheckSearchBoxWidget(contents_view->GetDefaultSearchBoxBounds()));
632 base::string16 new_search_text = base::UTF8ToUTF16("apple");
633 main_view->search_box_view()->search_box()->SetText(base::string16());
634 main_view->search_box_view()->search_box()->InsertText(new_search_text);
635 // Check that the current search is using |new_search_text|.
636 EXPECT_EQ(new_search_text, delegate_->GetTestModel()->search_box()->text());
637 EXPECT_EQ(new_search_text,
638 main_view->search_box_view()->search_box()->text());
639 contents_view->Layout();
640 EXPECT_TRUE(IsStateShown(AppListModel::STATE_SEARCH_RESULTS));
641 EXPECT_TRUE(
642 CheckSearchBoxWidget(contents_view->GetDefaultSearchBoxBounds()));
645 Close();
648 void AppListViewTestContext::RunAppListOverlayTest() {
649 Show();
651 AppListMainView* main_view = view_->app_list_main_view();
652 SearchBoxView* search_box_view = main_view->search_box_view();
654 // The search box should not be enabled when the app list overlay is shown.
655 view_->SetAppListOverlayVisible(true);
656 EXPECT_FALSE(search_box_view->enabled());
658 // The search box should be refocused when the app list overlay is hidden.
659 view_->SetAppListOverlayVisible(false);
660 EXPECT_TRUE(search_box_view->enabled());
661 EXPECT_EQ(search_box_view->search_box(),
662 view_->GetWidget()->GetFocusManager()->GetFocusedView());
664 Close();
667 class AppListViewTestAura : public views::ViewsTestBase,
668 public ::testing::WithParamInterface<int> {
669 public:
670 AppListViewTestAura() {}
671 virtual ~AppListViewTestAura() {}
673 // testing::Test overrides:
674 void SetUp() override {
675 views::ViewsTestBase::SetUp();
677 // On Ash (only) the app list is placed into an aura::Window "container",
678 // which is also used to determine the context. In tests, use the ash root
679 // window as the parent. This only works on aura where the root window is a
680 // NativeView as well as a NativeWindow.
681 gfx::NativeView container = NULL;
682 #if defined(USE_AURA)
683 container = GetContext();
684 #endif
686 test_context_.reset(new AppListViewTestContext(GetParam(), container));
689 void TearDown() override {
690 test_context_.reset();
691 views::ViewsTestBase::TearDown();
694 protected:
695 scoped_ptr<AppListViewTestContext> test_context_;
697 private:
698 DISALLOW_COPY_AND_ASSIGN(AppListViewTestAura);
701 class AppListViewTestDesktop : public views::ViewsTestBase,
702 public ::testing::WithParamInterface<int> {
703 public:
704 AppListViewTestDesktop() {}
705 virtual ~AppListViewTestDesktop() {}
707 // testing::Test overrides:
708 void SetUp() override {
709 set_views_delegate(make_scoped_ptr(new AppListViewTestViewsDelegate(this)));
710 views::ViewsTestBase::SetUp();
711 test_context_.reset(new AppListViewTestContext(GetParam(), NULL));
714 void TearDown() override {
715 test_context_.reset();
716 views::ViewsTestBase::TearDown();
719 protected:
720 scoped_ptr<AppListViewTestContext> test_context_;
722 private:
723 class AppListViewTestViewsDelegate : public views::TestViewsDelegate {
724 public:
725 explicit AppListViewTestViewsDelegate(AppListViewTestDesktop* parent)
726 : parent_(parent) {}
728 // Overridden from views::ViewsDelegate:
729 void OnBeforeWidgetInit(
730 views::Widget::InitParams* params,
731 views::internal::NativeWidgetDelegate* delegate) override;
733 private:
734 AppListViewTestDesktop* parent_;
736 DISALLOW_COPY_AND_ASSIGN(AppListViewTestViewsDelegate);
739 DISALLOW_COPY_AND_ASSIGN(AppListViewTestDesktop);
742 void AppListViewTestDesktop::AppListViewTestViewsDelegate::OnBeforeWidgetInit(
743 views::Widget::InitParams* params,
744 views::internal::NativeWidgetDelegate* delegate) {
745 // Mimic the logic in ChromeViewsDelegate::OnBeforeWidgetInit(). Except, for
746 // ChromeOS, use the root window from the AuraTestHelper rather than depending
747 // on ash::Shell:GetPrimaryRootWindow(). Also assume non-ChromeOS is never the
748 // Ash desktop, as that is covered by AppListViewTestAura.
749 #if defined(OS_CHROMEOS)
750 if (!params->parent && !params->context)
751 params->context = parent_->GetContext();
752 #elif defined(USE_AURA)
753 if (params->parent == NULL && params->context == NULL && !params->child)
754 params->native_widget = new views::DesktopNativeWidgetAura(delegate);
755 #endif
758 } // namespace
760 // Tests showing the app list with basic test model in an ash-style root window.
761 TEST_P(AppListViewTestAura, Display) {
762 EXPECT_NO_FATAL_FAILURE(test_context_->RunDisplayTest());
765 // Tests showing the app list on the desktop. Note on ChromeOS, this will still
766 // use the regular root window.
767 TEST_P(AppListViewTestDesktop, Display) {
768 EXPECT_NO_FATAL_FAILURE(test_context_->RunDisplayTest());
771 // Tests that the main grid view is shown after hiding and reshowing the app
772 // list with a folder view open. This is a regression test for crbug.com/357058.
773 TEST_P(AppListViewTestAura, ReshowWithOpenFolder) {
774 EXPECT_NO_FATAL_FAILURE(test_context_->RunReshowWithOpenFolderTest());
777 TEST_P(AppListViewTestDesktop, ReshowWithOpenFolder) {
778 EXPECT_NO_FATAL_FAILURE(test_context_->RunReshowWithOpenFolderTest());
781 // Tests that the start page view operates correctly.
782 TEST_P(AppListViewTestAura, StartPageTest) {
783 EXPECT_NO_FATAL_FAILURE(test_context_->RunStartPageTest());
786 TEST_P(AppListViewTestDesktop, StartPageTest) {
787 EXPECT_NO_FATAL_FAILURE(test_context_->RunStartPageTest());
790 // Tests that the start page view operates correctly.
791 TEST_P(AppListViewTestAura, PageSwitchingAnimationTest) {
792 EXPECT_NO_FATAL_FAILURE(test_context_->RunPageSwitchingAnimationTest());
795 TEST_P(AppListViewTestDesktop, PageSwitchingAnimationTest) {
796 EXPECT_NO_FATAL_FAILURE(test_context_->RunPageSwitchingAnimationTest());
799 // Tests that the profile changes operate correctly.
800 TEST_P(AppListViewTestAura, ProfileChangeTest) {
801 EXPECT_NO_FATAL_FAILURE(test_context_->RunProfileChangeTest());
804 TEST_P(AppListViewTestDesktop, ProfileChangeTest) {
805 EXPECT_NO_FATAL_FAILURE(test_context_->RunProfileChangeTest());
808 // Tests that the correct views are displayed for showing search results.
809 TEST_P(AppListViewTestAura, SearchResultsTest) {
810 EXPECT_NO_FATAL_FAILURE(test_context_->RunSearchResultsTest());
813 TEST_P(AppListViewTestDesktop, SearchResultsTest) {
814 EXPECT_NO_FATAL_FAILURE(test_context_->RunSearchResultsTest());
817 // Tests that the back button navigates through the app list correctly.
818 TEST_P(AppListViewTestAura, BackTest) {
819 EXPECT_NO_FATAL_FAILURE(test_context_->RunBackTest());
822 TEST_P(AppListViewTestDesktop, BackTest) {
823 EXPECT_NO_FATAL_FAILURE(test_context_->RunBackTest());
826 // Tests that the correct views are displayed for showing search results.
827 TEST_P(AppListViewTestAura, AppListOverlayTest) {
828 EXPECT_NO_FATAL_FAILURE(test_context_->RunAppListOverlayTest());
831 TEST_P(AppListViewTestDesktop, AppListOverlayTest) {
832 EXPECT_NO_FATAL_FAILURE(test_context_->RunAppListOverlayTest());
835 #if defined(USE_AURA)
836 INSTANTIATE_TEST_CASE_P(AppListViewTestAuraInstance,
837 AppListViewTestAura,
838 ::testing::Range<int>(TEST_TYPE_START, TEST_TYPE_END));
839 #endif
841 INSTANTIATE_TEST_CASE_P(AppListViewTestDesktopInstance,
842 AppListViewTestDesktop,
843 ::testing::Range<int>(TEST_TYPE_START, TEST_TYPE_END));
845 } // namespace test
846 } // namespace app_list