app_list_nudge_controller_unittest.cc 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // Copyright 2022 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.
  4. #include "ash/app_list/views/app_list_nudge_controller.h"
  5. #include <memory>
  6. #include "ash/app_list/app_list_controller_impl.h"
  7. #include "ash/app_list/test/app_list_test_helper.h"
  8. #include "ash/app_list/views/app_list_bubble_apps_page.h"
  9. #include "ash/app_list/views/app_list_toast_container_view.h"
  10. #include "ash/app_list/views/apps_container_view.h"
  11. #include "ash/app_list/views/search_box_view.h"
  12. #include "ash/constants/ash_features.h"
  13. #include "ash/public/cpp/app_list/app_list_types.h"
  14. #include "ash/session/session_controller_impl.h"
  15. #include "ash/shell.h"
  16. #include "ash/test/ash_test_base.h"
  17. #include "ash/wm/tablet_mode/tablet_mode_controller.h"
  18. #include "base/callback.h"
  19. #include "base/test/scoped_feature_list.h"
  20. #include "base/test/task_environment.h"
  21. #include "ui/views/controls/button/label_button.h"
  22. #include "ui/wm/core/window_util.h"
  23. namespace ash {
  24. namespace {
  25. bool IsTabletMode() {
  26. return Shell::Get()->tablet_mode_controller()->InTabletMode();
  27. }
  28. // Returns the number of times the nudge has been shown. Note that the count
  29. // will be updated only when the nudge becomes invisible.
  30. int GetReorderNudgeShownCount() {
  31. PrefService* pref_service =
  32. Shell::Get()->session_controller()->GetLastActiveUserPrefService();
  33. return AppListNudgeController::GetShownCount(
  34. pref_service, AppListNudgeController::NudgeType::kReorderNudge);
  35. }
  36. } // namespace
  37. class AppListNudgeControllerTest : public AshTestBase {
  38. public:
  39. AppListNudgeControllerTest()
  40. : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
  41. scoped_feature_list_.InitWithFeatures(
  42. {features::kLauncherAppSort, features::kProductivityLauncher,
  43. features::kLauncherDismissButtonsOnSortNudgeAndToast},
  44. {});
  45. }
  46. AppListNudgeControllerTest(const AppListNudgeControllerTest&) = delete;
  47. AppListNudgeControllerTest& operator=(const AppListNudgeControllerTest&) =
  48. delete;
  49. ~AppListNudgeControllerTest() override = default;
  50. void SetUp() override {
  51. AshTestBase::SetUp();
  52. GetAppListTestHelper()->DisableAppListNudge(false);
  53. }
  54. AppListNudgeController* GetNudgeController() {
  55. if (!IsTabletMode()) {
  56. return GetAppListTestHelper()
  57. ->GetBubbleAppsPage()
  58. ->app_list_nudge_controller();
  59. }
  60. return GetAppListTestHelper()
  61. ->GetAppsContainerView()
  62. ->app_list_nudge_controller();
  63. }
  64. AppListToastContainerView* GetToastContainerView() {
  65. if (!IsTabletMode()) {
  66. return GetAppListTestHelper()
  67. ->GetBubbleAppsPage()
  68. ->toast_container_for_test();
  69. }
  70. return GetAppListTestHelper()->GetAppsContainerView()->toast_container();
  71. }
  72. // Show app list and wait long enough for the nudge to be considered shown.
  73. void ShowAppListAndWait() {
  74. Shell::Get()->app_list_controller()->ShowAppList();
  75. task_environment()->AdvanceClock(base::Seconds(1));
  76. }
  77. void DismissAppList() { GetAppListTestHelper()->Dismiss(); }
  78. private:
  79. base::test::ScopedFeatureList scoped_feature_list_;
  80. };
  81. TEST_F(AppListNudgeControllerTest, Basic) {
  82. // Simulate a user login.
  83. SimulateUserLogin("user@gmail.com");
  84. // The reorder nudge should show 3 times to the users.
  85. ShowAppListAndWait();
  86. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  87. EXPECT_EQ(AppListToastType::kReorderNudge,
  88. GetToastContainerView()->current_toast());
  89. DismissAppList();
  90. ShowAppListAndWait();
  91. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  92. EXPECT_EQ(AppListToastType::kReorderNudge,
  93. GetToastContainerView()->current_toast());
  94. DismissAppList();
  95. ShowAppListAndWait();
  96. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  97. EXPECT_EQ(AppListToastType::kReorderNudge,
  98. GetToastContainerView()->current_toast());
  99. DismissAppList();
  100. // After the fourth time opening the app list, the nudge should be removed.
  101. ShowAppListAndWait();
  102. EXPECT_FALSE(GetToastContainerView()->IsToastVisible());
  103. EXPECT_EQ(AppListToastType::kNone, GetToastContainerView()->current_toast());
  104. DismissAppList();
  105. }
  106. TEST_F(AppListNudgeControllerTest, StopShowingNudgeAfterReordering) {
  107. // Simulate a user login.
  108. SimulateUserLogin("user@gmail.com");
  109. // The reorder nudge should show for the first time.
  110. ShowAppListAndWait();
  111. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  112. EXPECT_EQ(AppListToastType::kReorderNudge,
  113. GetToastContainerView()->current_toast());
  114. // Simulate that the app list is reordered by name.
  115. Shell::Get()->app_list_controller()->UpdateAppListWithNewTemporarySortOrder(
  116. AppListSortOrder::kNameAlphabetical, /*animate=*/false,
  117. base::OnceClosure());
  118. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  119. EXPECT_EQ(AppListToastType::kReorderUndo,
  120. GetToastContainerView()->current_toast());
  121. DismissAppList();
  122. // If the app list was reordered, remove the nudge from the app list when the
  123. // app list is opened next time.
  124. ShowAppListAndWait();
  125. EXPECT_EQ(GetNudgeController()->current_nudge(),
  126. AppListNudgeController::NudgeType::kNone);
  127. DismissAppList();
  128. }
  129. TEST_F(AppListNudgeControllerTest, TabletModeVisibilityTest) {
  130. // Simulate a user login.
  131. SimulateUserLogin("user@gmail.com");
  132. ShowAppListAndWait();
  133. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  134. EXPECT_EQ(AppListToastType::kReorderNudge,
  135. GetToastContainerView()->current_toast());
  136. // Change to tablet mode. The bubble app list is hidden and fullscreen app
  137. // list is showing.
  138. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  139. EXPECT_EQ(1, GetReorderNudgeShownCount());
  140. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  141. EXPECT_EQ(AppListToastType::kReorderNudge,
  142. GetToastContainerView()->current_toast());
  143. // Wait for long enough for the nudge to be considered shown.
  144. task_environment()->AdvanceClock(base::Seconds(1));
  145. // Open a window to make the app list invisible. This will update the prefs in
  146. // nudge controller.
  147. std::unique_ptr<aura::Window> window = AshTestBase::CreateTestWindow();
  148. wm::ActivateWindow(window.get());
  149. EXPECT_EQ(2, GetReorderNudgeShownCount());
  150. // Close the window and return back to app list.
  151. window->Hide();
  152. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  153. EXPECT_EQ(AppListToastType::kReorderNudge,
  154. GetToastContainerView()->current_toast());
  155. // Wait for long enough for the nudge to be considered shown.
  156. task_environment()->AdvanceClock(base::Seconds(1));
  157. // Activate the search box. The nudge will become inactive but the nudge view
  158. // still exists.
  159. auto* search_box = GetAppListTestHelper()->GetSearchBoxView();
  160. search_box->SetSearchBoxActive(true, ui::ET_MOUSE_PRESSED);
  161. // For the case where the nudge is visible but inactive, the count doesn't
  162. // increment as the nudge is still visible.
  163. EXPECT_EQ(2, GetReorderNudgeShownCount());
  164. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  165. // Exit the search view. The nudge should be visible and active now.
  166. search_box->SetSearchBoxActive(false, ui::ET_MOUSE_PRESSED);
  167. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  168. EXPECT_EQ(AppListToastType::kReorderNudge,
  169. GetToastContainerView()->current_toast());
  170. // Change to tablet mode. The nudge should be removed when the next time the
  171. // app list is shown.
  172. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
  173. EXPECT_EQ(3, GetReorderNudgeShownCount());
  174. ShowAppListAndWait();
  175. EXPECT_FALSE(GetToastContainerView()->IsToastVisible());
  176. EXPECT_EQ(AppListToastType::kNone, GetToastContainerView()->current_toast());
  177. }
  178. TEST_F(AppListNudgeControllerTest, ReorderNudgeDismissButton) {
  179. // Simulate a user login.
  180. SimulateUserLogin("user@gmail.com");
  181. ShowAppListAndWait();
  182. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  183. EXPECT_EQ(AppListToastType::kReorderNudge,
  184. GetToastContainerView()->current_toast());
  185. // Dismiss the reorder nudge and check that it is no longer visible.
  186. auto* event_generator = GetEventGenerator();
  187. event_generator->MoveMouseTo(GetToastContainerView()
  188. ->GetToastButton()
  189. ->GetBoundsInScreen()
  190. .CenterPoint());
  191. event_generator->ClickLeftButton();
  192. EXPECT_FALSE(GetToastContainerView()->IsToastVisible());
  193. // Close and reopen app list to make sure that the reorder nudge is no longer
  194. // shown after being dismissed.
  195. DismissAppList();
  196. ShowAppListAndWait();
  197. EXPECT_FALSE(GetToastContainerView()->IsToastVisible());
  198. EXPECT_EQ(AppListToastType::kNone, GetToastContainerView()->current_toast());
  199. }
  200. TEST_F(AppListNudgeControllerTest, ReorderUndoCloseButton) {
  201. // Simulate a user login.
  202. SimulateUserLogin("user@gmail.com");
  203. ShowAppListAndWait();
  204. // Simulate that the app list is reordered by name and check that the reorder
  205. // undo nudge is shown.
  206. Shell::Get()->app_list_controller()->UpdateAppListWithNewTemporarySortOrder(
  207. AppListSortOrder::kNameAlphabetical, /*animate=*/false,
  208. base::OnceClosure());
  209. EXPECT_TRUE(GetToastContainerView()->IsToastVisible());
  210. EXPECT_EQ(AppListToastType::kReorderUndo,
  211. GetToastContainerView()->current_toast());
  212. GetToastContainerView()->GetWidget()->LayoutRootViewIfNecessary();
  213. // Click the close button and check that the nudge is no longer visible.
  214. auto* event_generator = GetEventGenerator();
  215. event_generator->MoveMouseTo(GetToastContainerView()
  216. ->GetCloseButton()
  217. ->GetBoundsInScreen()
  218. .CenterPoint());
  219. event_generator->ClickLeftButton();
  220. EXPECT_FALSE(GetToastContainerView()->IsToastVisible());
  221. }
  222. } // namespace ash