123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/public/cpp/test/app_list_test_api.h"
- #include <string>
- #include <utility>
- #include <vector>
- #include "ash/app_list/app_list_bubble_presenter.h"
- #include "ash/app_list/app_list_controller_impl.h"
- #include "ash/app_list/app_list_model_provider.h"
- #include "ash/app_list/app_list_presenter_impl.h"
- #include "ash/app_list/model/app_list_folder_item.h"
- #include "ash/app_list/model/app_list_item.h"
- #include "ash/app_list/model/app_list_model.h"
- #include "ash/app_list/views/app_list_bubble_apps_page.h"
- #include "ash/app_list/views/app_list_bubble_view.h"
- #include "ash/app_list/views/app_list_folder_view.h"
- #include "ash/app_list/views/app_list_item_view.h"
- #include "ash/app_list/views/app_list_main_view.h"
- #include "ash/app_list/views/app_list_menu_model_adapter.h"
- #include "ash/app_list/views/app_list_toast_container_view.h"
- #include "ash/app_list/views/app_list_toast_view.h"
- #include "ash/app_list/views/app_list_view.h"
- #include "ash/app_list/views/apps_container_view.h"
- #include "ash/app_list/views/apps_grid_context_menu.h"
- #include "ash/app_list/views/apps_grid_view.h"
- #include "ash/app_list/views/apps_grid_view_test_api.h"
- #include "ash/app_list/views/contents_view.h"
- #include "ash/app_list/views/paged_apps_grid_view.h"
- #include "ash/app_list/views/recent_apps_view.h"
- #include "ash/app_list/views/scrollable_apps_grid_view.h"
- #include "ash/app_list/views/search_box_view.h"
- #include "ash/constants/ash_features.h"
- #include "ash/public/cpp/accelerators.h"
- #include "ash/shell.h"
- #include "ash/test/layer_animation_stopped_waiter.h"
- #include "base/callback.h"
- #include "base/run_loop.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "ui/aura/window_observer.h"
- #include "ui/compositor/layer.h"
- #include "ui/events/test/event_generator.h"
- #include "ui/views/controls/button/label_button.h"
- #include "ui/views/controls/label.h"
- #include "ui/views/controls/menu/menu_item_view.h"
- #include "ui/views/controls/menu/submenu_view.h"
- #include "ui/views/controls/scroll_view.h"
- #include "ui/views/controls/textfield/textfield.h"
- #include "ui/views/view_model.h"
- namespace ash {
- namespace {
- // A global pointer to the disabler's instance. Used to ensure at most one
- // disabler exists at a time.
- class ScopedItemMoveAnimationDisabler;
- ScopedItemMoveAnimationDisabler* g_disabler_ptr = nullptr;
- AppListView* GetAppListView() {
- return Shell::Get()->app_list_controller()->fullscreen_presenter()->GetView();
- }
- // An app list should be either a bubble app list or a fullscreen app list.
- // Returns true if a bubble app list should be used under the current mode.
- bool ShouldUseBubbleAppList() {
- // A bubble app list should be used only when:
- // (1) It is in clamshell mode; and
- // (2) The productivity launcher flag is enabled.
- return !Shell::Get()->IsInTabletMode() &&
- features::IsProductivityLauncherEnabled();
- }
- // Creates a RunLoop that waits until the context menu of app list item is
- // shown.
- void WaitUntilItemMenuShown(ash::AppListItemView* item_view) {
- base::RunLoop run_loop;
- // Set the callback that will quit the RunLoop when context menu is shown.
- item_view->SetContextMenuShownCallbackForTest(run_loop.QuitClosure());
- run_loop.Run();
- // Reset the callback.
- item_view->SetContextMenuShownCallbackForTest(base::RepeatingClosure());
- }
- // Returns the menu item indicated by `order` from a non-folder item menu.
- views::MenuItemView* GetReorderOptionForNonFolderItemMenu(
- const views::MenuItemView* root_menu,
- ash::AppListSortOrder order) {
- // Get the last menu item index where the reorder submenu is.
- views::MenuItemView* reorder_item_view =
- root_menu->GetSubmenu()->GetLastItem();
- DCHECK_EQ(reorder_item_view->title(), u"Sort by");
- return reorder_item_view;
- }
- ash::AppListItemView* FindFolderItemView(ash::AppsGridView* apps_grid_view) {
- auto* model = apps_grid_view->view_model();
- for (size_t index = 0; index < model->view_size(); ++index) {
- ash::AppListItemView* current_view = model->view_at(index);
- if (current_view->is_folder())
- return current_view;
- }
- return nullptr;
- }
- ash::AppListItemView* FindNonFolderItemView(ash::AppsGridView* apps_grid_view) {
- auto* model = apps_grid_view->view_model();
- for (size_t index = 0; index < model->view_size(); ++index) {
- ash::AppListItemView* current_view = model->view_at(index);
- if (!current_view->is_folder())
- return current_view;
- }
- return nullptr;
- }
- // Returns the index of the specified sorting option.
- size_t GetMenuIndexOfSortingOrder(ash::AppListSortOrder order) {
- switch (order) {
- case ash::AppListSortOrder::kNameAlphabetical:
- return 0;
- case ash::AppListSortOrder::kColor:
- return 1;
- case ash::AppListSortOrder::kNameReverseAlphabetical:
- case ash::AppListSortOrder::kCustom:
- NOTREACHED();
- return 0;
- }
- }
- views::MenuItemView* GetReorderOptionForAppListOrFolderItemMenu(
- const views::MenuItemView* root_menu,
- const ash::AppListSortOrder order) {
- views::MenuItemView* reorder_option = nullptr;
- switch (order) {
- case ash::AppListSortOrder::kNameAlphabetical:
- reorder_option = root_menu->GetSubmenu()->GetMenuItemAt(1);
- EXPECT_TRUE(reorder_option->title() == u"Name");
- break;
- case ash::AppListSortOrder::kColor:
- reorder_option = root_menu->GetSubmenu()->GetMenuItemAt(2);
- EXPECT_TRUE(reorder_option->title() == u"Color");
- break;
- case ash::AppListSortOrder::kNameReverseAlphabetical:
- case ash::AppListSortOrder::kCustom:
- NOTREACHED();
- return nullptr;
- }
- return reorder_option;
- }
- views::MenuItemView* ShowRootMenuAndReturn(
- ash::AppsGridView* apps_grid_view,
- AppListTestApi::MenuType menu_type,
- ui::test::EventGenerator* event_generator) {
- views::MenuItemView* root_menu = nullptr;
- EXPECT_GT(apps_grid_view->view_model()->view_size(), 0u);
- switch (menu_type) {
- case AppListTestApi::MenuType::kAppListPageMenu:
- event_generator->MoveMouseTo(
- apps_grid_view->GetBoundsInScreen().CenterPoint());
- event_generator->ClickRightButton();
- root_menu =
- apps_grid_view->context_menu_for_test()->root_menu_item_view();
- break;
- case AppListTestApi::MenuType::kAppListNonFolderItemMenu:
- case AppListTestApi::MenuType::kAppListFolderItemMenu:
- const bool is_folder_item =
- (menu_type == AppListTestApi::MenuType::kAppListFolderItemMenu);
- ash::AppListItemView* item_view =
- is_folder_item ? FindFolderItemView(apps_grid_view)
- : FindNonFolderItemView(apps_grid_view);
- EXPECT_TRUE(item_view);
- event_generator->MoveMouseTo(
- item_view->GetBoundsInScreen().CenterPoint());
- event_generator->ClickRightButton();
- if (is_folder_item) {
- root_menu = item_view->context_menu_for_folder()->root_menu_item_view();
- } else {
- WaitUntilItemMenuShown(item_view);
- ash::AppListMenuModelAdapter* menu_model_adapter =
- item_view->item_menu_model_adapter();
- root_menu = menu_model_adapter->root_for_testing();
- }
- break;
- }
- EXPECT_TRUE(root_menu->SubmenuIsShowing());
- return root_menu;
- }
- PagedAppsGridView* GetPagedAppsGridView() {
- // This view only exists for tablet launcher and legacy peeking launcher.
- DCHECK(!ShouldUseBubbleAppList());
- return AppListView::TestApi(GetAppListView()).GetRootAppsGridView();
- }
- AppListBubbleView* GetAppListBubbleView() {
- AppListBubbleView* bubble_view = Shell::Get()
- ->app_list_controller()
- ->bubble_presenter_for_test()
- ->bubble_view_for_test();
- DCHECK(bubble_view) << "Bubble launcher view not yet created. Tests must "
- "show the launcher and may need to call "
- "WaitForBubbleWindow() if animations are enabled.";
- return bubble_view;
- }
- AppsContainerView* GetAppsContainerView() {
- return GetAppListView()
- ->app_list_main_view()
- ->contents_view()
- ->apps_container_view();
- }
- AppListFolderView* GetAppListFolderView() {
- // Handle the case that the app list bubble view is effective.
- if (ShouldUseBubbleAppList())
- return GetAppListBubbleView()->folder_view_for_test();
- return GetAppsContainerView()->app_list_folder_view();
- }
- AppListToastContainerView* GetToastContainerViewFromBubble() {
- DCHECK(features::IsLauncherAppSortEnabled());
- return GetAppListBubbleView()
- ->apps_page_for_test()
- ->toast_container_for_test();
- }
- AppListToastContainerView* GetToastContainerViewFromFullscreenAppList() {
- DCHECK(features::IsLauncherAppSortEnabled());
- return GetAppsContainerView()->toast_container();
- }
- RecentAppsView* GetRecentAppsView() {
- if (ShouldUseBubbleAppList())
- return GetAppListBubbleView()->apps_page_for_test()->recent_apps_for_test();
- return GetAppsContainerView()->GetRecentAppsView();
- }
- SearchBoxView* GetSearchBoxView() {
- if (ShouldUseBubbleAppList())
- return GetAppListBubbleView()->search_box_view_for_test();
- return GetAppListView()->app_list_main_view()->search_box_view();
- }
- // AppListVisibilityChangedWaiter ----------------------------------------------
- // Waits until the app list visibility changes.
- class AppListVisibilityChangedWaiter : public AppListControllerObserver {
- public:
- AppListVisibilityChangedWaiter() = default;
- AppListVisibilityChangedWaiter(const AppListVisibilityChangedWaiter&) =
- delete;
- AppListVisibilityChangedWaiter& operator=(
- const AppListVisibilityChangedWaiter&) = delete;
- ~AppListVisibilityChangedWaiter() override {
- AppListController::Get()->RemoveObserver(this);
- }
- void Wait() {
- AppListController::Get()->AddObserver(this);
- run_loop_.Run();
- }
- // AppListControllerObserver:
- void OnAppListVisibilityChanged(bool shown, int64_t display_id) override {
- run_loop_.Quit();
- }
- private:
- base::RunLoop run_loop_;
- };
- // WindowAddedWaiter -----------------------------------------------------------
- // Waits until a child window is added to a container window.
- class WindowAddedWaiter : public aura::WindowObserver {
- public:
- explicit WindowAddedWaiter(aura::Window* container) : container_(container) {
- container_->AddObserver(this);
- }
- WindowAddedWaiter(const WindowAddedWaiter&) = delete;
- WindowAddedWaiter& operator=(const WindowAddedWaiter&) = delete;
- ~WindowAddedWaiter() override { container_->RemoveObserver(this); }
- void Wait() { run_loop_.Run(); }
- aura::Window* added_window() { return added_window_; }
- private:
- // aura::WindowObserver:
- void OnWindowAdded(aura::Window* new_window) override {
- added_window_ = new_window;
- DCHECK(run_loop_.IsRunningOnCurrentThread());
- run_loop_.Quit();
- }
- aura::Window* const container_;
- aura::Window* added_window_ = nullptr;
- base::RunLoop run_loop_;
- };
- // ScopedItemMoveAnimationDisabler ---------------------------------------------
- // Disable the apps grid item move animation in scope.
- class ScopedItemMoveAnimationDisabler {
- public:
- explicit ScopedItemMoveAnimationDisabler(AppsGridView* apps_grid)
- : apps_grid_(apps_grid) {
- DCHECK(!g_disabler_ptr);
- apps_grid_->set_enable_item_move_animation_for_test(false);
- g_disabler_ptr = this;
- }
- ScopedItemMoveAnimationDisabler(const ScopedItemMoveAnimationDisabler&) =
- delete;
- ScopedItemMoveAnimationDisabler& operator=(
- const ScopedItemMoveAnimationDisabler&) = delete;
- ~ScopedItemMoveAnimationDisabler() {
- apps_grid_->set_enable_item_move_animation_for_test(true);
- DCHECK(g_disabler_ptr);
- g_disabler_ptr = nullptr;
- }
- private:
- AppsGridView* const apps_grid_;
- };
- } // namespace
- AppListTestApi::AppListTestApi() = default;
- AppListTestApi::~AppListTestApi() = default;
- AppListModel* AppListTestApi::GetAppListModel() {
- return AppListModelProvider::Get()->model();
- }
- void AppListTestApi::ShowBubbleAppListAndWait() {
- ash::AcceleratorController::Get()->PerformActionIfEnabled(
- ash::TOGGLE_APP_LIST_FULLSCREEN, {});
- WaitForBubbleWindow(
- /*wait_for_opening_animation=*/true);
- }
- void AppListTestApi::WaitForBubbleWindow(bool wait_for_opening_animation) {
- DCHECK(features::IsProductivityLauncherEnabled());
- DCHECK(!Shell::Get()->IsInTabletMode());
- // Wait for the window only when the app list window does not exist.
- auto* app_list_controller = Shell::Get()->app_list_controller();
- if (!app_list_controller->GetWindow()) {
- // Wait for a child window to be added to the app list container.
- aura::Window* container = Shell::GetContainer(
- Shell::GetPrimaryRootWindow(), kShellWindowId_AppListContainer);
- WindowAddedWaiter waiter(container);
- waiter.Wait();
- // App list window exists.
- aura::Window* app_list_window = app_list_controller->GetWindow();
- DCHECK(app_list_window);
- DCHECK_EQ(app_list_window, waiter.added_window());
- }
- if (wait_for_opening_animation)
- WaitForAppListShowAnimation(/*is_bubble_window=*/true);
- }
- void AppListTestApi::WaitForAppListShowAnimation(bool is_bubble_window) {
- // Ensure that the app list is visible before waiting for animations.
- AppListController* controller = AppListControllerImpl::Get();
- if (!controller->IsVisible()) {
- AppListVisibilityChangedWaiter waiter;
- waiter.Wait();
- if (!controller->IsVisible())
- ADD_FAILURE() << "Launcher is not visible.";
- }
- // Wait for the app list window animation.
- aura::Window* app_list_window = controller->GetWindow();
- DCHECK(app_list_window);
- LayerAnimationStoppedWaiter().Wait(app_list_window->layer());
- if (!is_bubble_window)
- return;
- DCHECK(features::IsProductivityLauncherEnabled());
- DCHECK(!Shell::Get()->IsInTabletMode());
- ScrollableAppsGridView* scrollable_apps_grid_view =
- static_cast<ScrollableAppsGridView*>(GetTopLevelAppsGridView());
- if (!scrollable_apps_grid_view->layer())
- return;
- // Wait for the animation to show the bubble view.
- LayerAnimationStoppedWaiter().Wait(GetAppListBubbleView()->layer());
- // Wait for the animation to show the apps page.
- LayerAnimationStoppedWaiter().Wait(GetAppListBubbleView()
- ->apps_page_for_test()
- ->scroll_view()
- ->contents()
- ->layer());
- // Wait for the apps grid slide animation.
- LayerAnimationStoppedWaiter().Wait(scrollable_apps_grid_view->layer());
- }
- bool AppListTestApi::HasApp(const std::string& app_id) {
- return GetAppListModel()->FindItem(app_id);
- }
- std::u16string AppListTestApi::GetAppListItemViewName(
- const std::string& item_id) {
- AppListItemView* item_view = GetTopLevelItemViewFromId(item_id);
- if (!item_view)
- return u"";
- return item_view->title()->GetText();
- }
- AppListItemView* AppListTestApi::GetTopLevelItemViewFromId(
- const std::string& item_id) {
- views::ViewModelT<AppListItemView>* view_model =
- GetTopLevelAppsGridView()->view_model();
- for (size_t i = 0; i < view_model->view_size(); ++i) {
- AppListItemView* app_list_item_view = view_model->view_at(i);
- if (app_list_item_view->item()->id() == item_id)
- return app_list_item_view;
- }
- return nullptr;
- }
- std::vector<std::string> AppListTestApi::GetTopLevelViewIdList() {
- std::vector<std::string> id_list;
- auto* view_model = GetTopLevelAppsGridView()->view_model();
- for (size_t i = 0; i < view_model->view_size(); ++i) {
- AppListItem* app_list_item = view_model->view_at(i)->item();
- if (app_list_item) {
- id_list.push_back(app_list_item->id());
- }
- }
- return id_list;
- }
- std::string AppListTestApi::CreateFolderWithApps(
- const std::vector<std::string>& apps) {
- // Only create a folder if there are two or more apps.
- DCHECK_GE(apps.size(), 2u);
- AppListModel* model = GetAppListModel();
- // Create a folder using the first two apps, and add the others to the
- // folder iteratively.
- std::string folder_id = model->MergeItems(apps[0], apps[1]);
- // Return early if MergeItems failed.
- if (folder_id.empty())
- return "";
- // Skip item move animations.
- ScopedItemMoveAnimationDisabler disabler(GetTopLevelAppsGridView());
- for (size_t i = 2; i < apps.size(); ++i)
- model->MergeItems(folder_id, apps[i]);
- return folder_id;
- }
- std::string AppListTestApi::GetFolderId(const std::string& app_id) {
- return GetAppListModel()->FindItem(app_id)->folder_id();
- }
- std::vector<std::string> AppListTestApi::GetAppIdsInFolder(
- const std::string& folder_id) {
- AppListItem* folder_item = GetAppListModel()->FindItem(folder_id);
- DCHECK(folder_item->is_folder());
- AppListItemList* folder_list =
- static_cast<AppListFolderItem*>(folder_item)->item_list();
- std::vector<std::string> id_list;
- for (size_t i = 0; i < folder_list->item_count(); ++i)
- id_list.push_back(folder_list->item_at(i)->id());
- return id_list;
- }
- void AppListTestApi::MoveItemToPosition(const std::string& item_id,
- const size_t to_index) {
- AppListItem* app_item = GetAppListModel()->FindItem(item_id);
- const std::string folder_id = app_item->folder_id();
- AppListItemList* item_list;
- std::vector<std::string> top_level_id_list = GetTopLevelViewIdList();
- // The app should be either at the top level or in a folder.
- if (folder_id.empty()) {
- // The app is at the top level.
- item_list = GetAppListModel()->top_level_item_list();
- } else {
- // The app is in the folder with |folder_id|.
- item_list = GetAppListModel()->FindFolderItem(folder_id)->item_list();
- }
- size_t from_index = 0;
- item_list->FindItemIndex(item_id, &from_index);
- item_list->MoveItem(from_index, to_index);
- }
- void AppListTestApi::AddPageBreakItemAfterId(const std::string& item_id) {
- auto* model = GetAppListModel();
- model->AddPageBreakItemAfter(model->FindItem(item_id));
- }
- int AppListTestApi::GetTopListItemCount() {
- return GetAppListModel()->top_level_item_list()->item_count();
- }
- views::View* AppListTestApi::GetLastItemInAppsGridView() {
- AppsGridView* grid = GetTopLevelAppsGridView();
- return grid->view_model()->view_at(grid->view_model()->view_size() - 1);
- }
- PaginationModel* AppListTestApi::GetPaginationModel() {
- return GetPagedAppsGridView()->pagination_model();
- }
- void AppListTestApi::UpdatePagedViewStructure() {
- GetPagedAppsGridView()->UpdatePagedViewStructure();
- }
- AppsGridView* AppListTestApi::GetTopLevelAppsGridView() {
- if (ShouldUseBubbleAppList()) {
- return GetAppListBubbleView()
- ->apps_page_for_test()
- ->scrollable_apps_grid_view();
- }
- return GetPagedAppsGridView();
- }
- const AppsGridView* AppListTestApi::GetTopLevelAppsGridView() const {
- if (ShouldUseBubbleAppList()) {
- return GetAppListBubbleView()
- ->apps_page_for_test()
- ->scrollable_apps_grid_view();
- }
- return GetPagedAppsGridView();
- }
- AppsGridView* AppListTestApi::GetFolderAppsGridView() {
- return GetAppListFolderView()->items_grid_view();
- }
- bool AppListTestApi::IsFolderViewAnimating() const {
- return GetAppListFolderView()->IsAnimationRunning();
- }
- views::View* AppListTestApi::GetBubbleReorderUndoButton() {
- return GetToastContainerViewFromBubble()->GetToastButton();
- }
- views::View* AppListTestApi::GetFullscreenReorderUndoButton() {
- return GetToastContainerViewFromFullscreenAppList()->GetToastButton();
- }
- AppListToastType AppListTestApi::GetToastType() const {
- AppListToastContainerView* toast_container =
- ShouldUseBubbleAppList() ? GetToastContainerViewFromBubble()
- : GetToastContainerViewFromFullscreenAppList();
- return toast_container->current_toast();
- }
- void AppListTestApi::SetFolderViewAnimationCallback(
- base::OnceClosure folder_animation_done_callback) {
- AppListFolderView* folder_view = GetAppListFolderView();
- folder_view->SetAnimationDoneTestCallback(base::BindOnce(
- [](AppListFolderView* folder_view,
- base::OnceClosure folder_animation_done_callback) {
- std::move(folder_animation_done_callback).Run();
- },
- folder_view, std::move(folder_animation_done_callback)));
- }
- views::View* AppListTestApi::GetToastContainerView() {
- if (ShouldUseBubbleAppList())
- return GetToastContainerViewFromBubble();
- return GetToastContainerViewFromFullscreenAppList();
- }
- void AppListTestApi::AddReorderAnimationCallback(
- AppsGridView::TestReorderDoneCallbackType callback) {
- DCHECK(features::IsLauncherAppSortEnabled());
- GetTopLevelAppsGridView()->AddReorderCallbackForTest(std::move(callback));
- }
- void AppListTestApi::AddFadeOutAnimationStartClosure(
- base::OnceClosure closure) {
- DCHECK(features::IsLauncherAppSortEnabled());
- GetTopLevelAppsGridView()->AddFadeOutAnimationStartClosureForTest(
- std::move(closure));
- }
- bool AppListTestApi::HasAnyWaitingReorderDoneCallback() const {
- DCHECK(features::IsLauncherAppSortEnabled());
- return GetTopLevelAppsGridView()->HasAnyWaitingReorderDoneCallbackForTest();
- }
- void AppListTestApi::DisableAppListNudge(bool disable) {
- AppListNudgeController::SetReorderNudgeDisabledForTest(disable);
- }
- void AppListTestApi::SetContinueSectionPrivacyNoticeAccepted() {
- AppListNudgeController::SetPrivacyNoticeAcceptedForTest(true);
- }
- void AppListTestApi::ReorderItemInRootByDragAndDrop(int source_index,
- int target_index) {
- test::AppsGridViewTestApi(GetTopLevelAppsGridView())
- .ReorderItemByDragAndDrop(source_index, target_index);
- }
- views::View* AppListTestApi::GetVisibleSearchResultView(int index) {
- views::View* app_list =
- ShouldUseBubbleAppList()
- ? static_cast<views::View*>(GetAppListBubbleView())
- : static_cast<views::View*>(GetAppListView());
- views::View::Views search_results;
- app_list->GetViewsInGroup(kSearchResultViewGroup, &search_results);
- int current_visible_index = -1;
- for (auto* view : search_results) {
- if (view->GetVisible())
- ++current_visible_index;
- if (current_visible_index == index)
- return view;
- }
- return nullptr;
- }
- ash::AppListItemView* AppListTestApi::FindTopLevelFolderItemView() {
- return FindFolderItemView(GetTopLevelAppsGridView());
- }
- void AppListTestApi::VerifyTopLevelItemVisibility() {
- auto* view_model = GetTopLevelAppsGridView()->view_model();
- std::vector<std::string> invisible_item_names;
- for (size_t view_index = 0; view_index < view_model->view_size();
- ++view_index) {
- auto* item_view = view_model->view_at(view_index);
- if (!item_view->GetVisible())
- invisible_item_names.push_back(item_view->item()->name());
- }
- // Invisible items should be none.
- EXPECT_EQ(std::vector<std::string>(), invisible_item_names);
- }
- views::View* AppListTestApi::GetRecentAppAt(int index) {
- return GetRecentAppsView()->GetItemViewAt(index);
- }
- void AppListTestApi::SimulateSearch(const std::u16string& query) {
- views::Textfield* textfield = GetSearchBoxView()->search_box();
- textfield->SetText(u"");
- textfield->InsertText(
- query,
- ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
- }
- void AppListTestApi::ReorderByMouseClickAtContextMenuInAppsGrid(
- ash::AppsGridView* apps_grid_view,
- ash::AppListSortOrder order,
- MenuType menu_type,
- ui::test::EventGenerator* event_generator,
- ReorderAnimationEndState target_state,
- ReorderAnimationEndState* actual_state) {
- // Ensure that the apps grid layout is refreshed before showing the
- // context menu.
- apps_grid_view->GetWidget()->LayoutRootViewIfNecessary();
- // Custom order is not a menu option.
- EXPECT_NE(order, ash::AppListSortOrder::kCustom);
- views::MenuItemView* root_menu =
- ShowRootMenuAndReturn(apps_grid_view, menu_type, event_generator);
- // Get the "Name" or "Color" option.
- views::MenuItemView* reorder_option = nullptr;
- switch (menu_type) {
- case MenuType::kAppListPageMenu:
- case MenuType::kAppListFolderItemMenu:
- reorder_option =
- GetReorderOptionForAppListOrFolderItemMenu(root_menu, order);
- break;
- case MenuType::kAppListNonFolderItemMenu: {
- // The `reorder_option` cached here is the submenu of the options.
- views::MenuItemView* reorder_submenu =
- GetReorderOptionForNonFolderItemMenu(root_menu, order);
- event_generator->MoveMouseTo(
- reorder_submenu->GetBoundsInScreen().CenterPoint());
- event_generator->ClickLeftButton();
- reorder_option = reorder_submenu->GetSubmenu()->GetMenuItemAt(
- GetMenuIndexOfSortingOrder(order));
- break;
- }
- }
- gfx::Point point_on_option =
- reorder_option->GetBoundsInScreen().CenterPoint();
- RegisterReorderAnimationDoneCallback(actual_state);
- // Click at the sorting option.
- event_generator->MoveMouseTo(point_on_option);
- event_generator->ClickLeftButton();
- switch (target_state) {
- case ReorderAnimationEndState::kCompleted:
- // Wait until the reorder animation is done.
- WaitForReorderAnimationAndVerifyItemVisibility();
- break;
- case ReorderAnimationEndState::kFadeOutAborted:
- // The fade out animation starts synchronously so do not wait before
- // animation interruption.
- break;
- case ReorderAnimationEndState::kFadeInAborted:
- // Wait until the fade out animation is done. It ensures that the app
- // list is under fade in animation when animation interruption occurs.
- WaitForFadeOutAnimation();
- break;
- }
- }
- void AppListTestApi::ReorderByMouseClickAtToplevelAppsGridMenu(
- ash::AppListSortOrder order,
- MenuType menu_type,
- ui::test::EventGenerator* event_generator,
- ReorderAnimationEndState target_state,
- ReorderAnimationEndState* actual_state) {
- ReorderByMouseClickAtContextMenuInAppsGrid(GetTopLevelAppsGridView(), order,
- menu_type, event_generator,
- target_state, actual_state);
- }
- void AppListTestApi::ClickOnRedoButtonAndWaitForAnimation(
- ui::test::EventGenerator* event_generator) {
- ReorderAnimationEndState actual_state;
- RegisterReorderAnimationDoneCallback(&actual_state);
- // Mouse click at the undo button.
- views::View* reorder_undo_toast_button = nullptr;
- if (ShouldUseBubbleAppList())
- reorder_undo_toast_button = GetBubbleReorderUndoButton();
- else
- reorder_undo_toast_button = GetFullscreenReorderUndoButton();
- event_generator->MoveMouseTo(
- reorder_undo_toast_button->GetBoundsInScreen().CenterPoint());
- event_generator->ClickLeftButton();
- // Verify that the toast is under animation.
- EXPECT_TRUE(GetToastContainerView()->layer()->GetAnimator()->is_animating());
- WaitForReorderAnimationAndVerifyItemVisibility();
- EXPECT_EQ(ReorderAnimationEndState::kCompleted, actual_state);
- }
- void AppListTestApi::ClickOnCloseButtonAndWaitForToastAnimation(
- ui::test::EventGenerator* event_generator) {
- AppListToastContainerView* toast_container =
- ShouldUseBubbleAppList() ? GetToastContainerViewFromBubble()
- : GetToastContainerViewFromFullscreenAppList();
- views::View* close_button = toast_container->GetCloseButton();
- event_generator->MoveMouseTo(close_button->GetBoundsInScreen().CenterPoint());
- event_generator->ClickLeftButton();
- // Wait until the toast fade out animation ends.
- LayerAnimationStoppedWaiter animation_waiter;
- animation_waiter.Wait(toast_container->toast_view()->layer());
- }
- void AppListTestApi::RegisterReorderAnimationDoneCallback(
- ReorderAnimationEndState* actual_state) {
- AddReorderAnimationCallback(
- base::BindRepeating(&AppListTestApi::OnReorderAnimationDone,
- weak_factory_.GetWeakPtr(), actual_state));
- }
- void AppListTestApi::OnReorderAnimationDone(ReorderAnimationEndState* result,
- bool abort,
- AppListGridAnimationStatus status) {
- DCHECK(status == AppListGridAnimationStatus::kReorderFadeOut ||
- status == AppListGridAnimationStatus::kReorderFadeIn);
- // Record the animation running result.
- if (abort) {
- if (status == AppListGridAnimationStatus::kReorderFadeOut)
- *result = ReorderAnimationEndState::kFadeOutAborted;
- else
- *result = ReorderAnimationEndState::kFadeInAborted;
- } else {
- EXPECT_EQ(AppListGridAnimationStatus::kReorderFadeIn, status);
- *result = ReorderAnimationEndState::kCompleted;
- // Verify that the toast container under the clamshell mode does not have
- // a layer after reorder animation completes.
- views::View* toast_container = GetToastContainerView();
- if (toast_container && !ash::Shell::Get()->IsInTabletMode())
- EXPECT_FALSE(toast_container->layer());
- }
- // Callback can be registered without a running loop.
- if (run_loop_for_reorder_)
- run_loop_for_reorder_->Quit();
- }
- void AppListTestApi::WaitForReorderAnimationAndVerifyItemVisibility() {
- run_loop_for_reorder_ = std::make_unique<base::RunLoop>();
- run_loop_for_reorder_->Run();
- VerifyTopLevelItemVisibility();
- }
- void AppListTestApi::WaitForFadeOutAnimation() {
- ash::AppsGridView* apps_grid_view = GetTopLevelAppsGridView();
- if (apps_grid_view->grid_animation_status_for_test() !=
- AppListGridAnimationStatus::kReorderFadeOut) {
- // The apps grid is not under fade out animation so no op.
- return;
- }
- ASSERT_TRUE(!run_loop_for_reorder_ || !run_loop_for_reorder_->running());
- run_loop_for_reorder_ = std::make_unique<base::RunLoop>();
- apps_grid_view->AddFadeOutAnimationDoneClosureForTest(
- run_loop_for_reorder_->QuitClosure());
- run_loop_for_reorder_->Run();
- }
- } // namespace ash
|