folder_header_view_unittest.cc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // Copyright (c) 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.
  4. #include "ash/app_list/views/folder_header_view.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include "ash/app_list/model/app_list_folder_item.h"
  10. #include "ash/app_list/model/app_list_item.h"
  11. #include "ash/app_list/model/app_list_test_model.h"
  12. #include "ash/app_list/test/app_list_test_helper.h"
  13. #include "ash/app_list/views/app_list_folder_view.h"
  14. #include "ash/app_list/views/apps_grid_view_test_api.h"
  15. #include "ash/app_list/views/scrollable_apps_grid_view.h"
  16. #include "ash/test/ash_test_base.h"
  17. #include "base/strings/utf_string_conversions.h"
  18. #include "testing/gtest/include/gtest/gtest.h"
  19. #include "ui/events/event.h"
  20. #include "ui/events/keycodes/keyboard_codes_posix.h"
  21. #include "ui/views/controls/textfield/textfield.h"
  22. namespace ash {
  23. class FolderHeaderViewTest : public AshTestBase {
  24. public:
  25. FolderHeaderViewTest() = default;
  26. FolderHeaderViewTest(const FolderHeaderViewTest&) = delete;
  27. FolderHeaderViewTest& operator=(const FolderHeaderViewTest&) = delete;
  28. ~FolderHeaderViewTest() override = default;
  29. // testing::Test overrides:
  30. void SetUp() override {
  31. AshTestBase::SetUp();
  32. model_ = GetAppListTestHelper()->model();
  33. // `folder_header_view_` is set when the folder is opened. This allows test
  34. // cases to configure the model before opening the folder.
  35. }
  36. // Assumes the folder is the first item in the grid.
  37. void ShowAppListAndOpenFolder() {
  38. auto* helper = GetAppListTestHelper();
  39. helper->ShowAppList();
  40. AppsGridView* apps_grid_view = helper->GetScrollableAppsGridView();
  41. ASSERT_TRUE(apps_grid_view);
  42. test::AppsGridViewTestApi(apps_grid_view).PressItemAt(0);
  43. ASSERT_TRUE(helper->IsInFolderView());
  44. folder_header_view_ = helper->GetBubbleFolderView()->folder_header_view();
  45. }
  46. protected:
  47. void UpdateFolderName(const std::string& name) {
  48. std::u16string folder_name = base::UTF8ToUTF16(name);
  49. folder_header_view_->SetFolderNameForTest(folder_name);
  50. folder_header_view_->ContentsChanged(
  51. folder_header_view_->GetFolderNameViewForTest(), folder_name);
  52. }
  53. const std::string GetFolderNameFromUI() {
  54. return base::UTF16ToUTF8(folder_header_view_->GetFolderNameForTest());
  55. }
  56. bool CanEditFolderName() {
  57. return folder_header_view_->IsFolderNameEnabledForTest();
  58. }
  59. void FocusText() { folder_header_view_->SetTextFocus(); }
  60. bool HasTextFocus() { return folder_header_view_->HasTextFocus(); }
  61. void SendKey(ui::KeyboardCode key_code, int flags = ui::EF_NONE) {
  62. PressAndReleaseKey(key_code, flags);
  63. }
  64. test::AppListTestModel* model_ = nullptr;
  65. FolderHeaderView* folder_header_view_ = nullptr;
  66. };
  67. TEST_F(FolderHeaderViewTest, WhitespaceCollapsedWhenFolderNameViewLosesFocus) {
  68. AppListFolderItem* folder_item = model_->CreateAndPopulateFolderWithApps(2);
  69. ShowAppListAndOpenFolder();
  70. views::View* name_view = folder_header_view_->GetFolderNameViewForTest();
  71. name_view->RequestFocus();
  72. UpdateFolderName(" N A ");
  73. name_view->GetFocusManager()->ClearFocus();
  74. // Expect that the folder name contains the same string with collapsed
  75. // whitespace.
  76. EXPECT_EQ("N A", folder_item->name());
  77. }
  78. TEST_F(FolderHeaderViewTest, MaxFolderNameLength) {
  79. // Creating a folder with empty folder name.
  80. AppListFolderItem* folder_item = model_->CreateAndPopulateFolderWithApps(2);
  81. ShowAppListAndOpenFolder();
  82. EXPECT_EQ("", GetFolderNameFromUI());
  83. EXPECT_TRUE(CanEditFolderName());
  84. // Update UI to set folder name to really long one beyond its maximum limit
  85. // If folder name is set beyond the maximum char limit, it should revert to
  86. // the previous valid folder name.
  87. std::string max_len_name;
  88. for (int i = 0; i < folder_header_view_->GetMaxFolderNameCharLengthForTest();
  89. ++i) {
  90. max_len_name += "a";
  91. }
  92. std::string too_long_name = max_len_name + "a";
  93. // Expect that the folder name does not change, and does not truncate
  94. UpdateFolderName(too_long_name);
  95. EXPECT_EQ(std::string(), folder_item->name());
  96. // Expect the folder does change to the new valid name given
  97. UpdateFolderName(max_len_name);
  98. EXPECT_EQ(max_len_name, folder_item->name());
  99. // Expect that the name is reverted to the previous valid name and is not
  100. // truncated
  101. too_long_name.insert(5, "testing");
  102. UpdateFolderName(too_long_name);
  103. EXPECT_EQ(max_len_name, folder_item->name());
  104. }
  105. TEST_F(FolderHeaderViewTest, OemFolderNameNotEditable) {
  106. model_->CreateAndAddOemFolder();
  107. ShowAppListAndOpenFolder();
  108. EXPECT_EQ("", GetFolderNameFromUI());
  109. EXPECT_FALSE(CanEditFolderName());
  110. }
  111. namespace {
  112. // Sends a tap gesture with events corresponding to touch-down and touch-up.
  113. // This is a template to support a |handler| with an OnGestureEvent() method
  114. // such as views::Widget or views::View.
  115. template <typename GestureHandler>
  116. void SendTap(GestureHandler* handler, const gfx::Point& location) {
  117. ui::GestureEvent tap_down(
  118. location.x(), location.y(), 0, base::TimeTicks::Now(),
  119. ui::GestureEventDetails(ui::EventType::ET_GESTURE_TAP_DOWN));
  120. handler->OnGestureEvent(&tap_down);
  121. ui::GestureEvent tap_up(
  122. location.x(), location.y(), 0, base::TimeTicks::Now(),
  123. ui::GestureEventDetails(ui::EventType::ET_GESTURE_TAP));
  124. handler->OnGestureEvent(&tap_up);
  125. }
  126. template <typename EventHandler>
  127. void SendPress(EventHandler* handler, const gfx::Point& location) {
  128. ui::MouseEvent press_down(ui::ET_MOUSE_PRESSED,
  129. gfx::PointF(location.x(), location.y()),
  130. gfx::PointF(0, 0), base::TimeTicks::Now(), 0, 0);
  131. handler->OnMouseEvent(&press_down);
  132. ui::MouseEvent press_up(ui::ET_MOUSE_RELEASED,
  133. gfx::PointF(location.x(), location.y()),
  134. gfx::PointF(0, 0), base::TimeTicks::Now(), 0, 0);
  135. handler->OnMouseEvent(&press_up);
  136. }
  137. } // namespace
  138. // Tests that when folder name is small, the folder name textfield is triggered
  139. // by only tap when on the textfieldd or near it to the left/right.
  140. TEST_F(FolderHeaderViewTest, TriggerFolderRenameAfterTappingNearFolderName) {
  141. // Create a folder with a small name.
  142. model_->CreateAndPopulateFolderWithApps(2);
  143. ShowAppListAndOpenFolder();
  144. UpdateFolderName("ab");
  145. // Get in screen bounds of folder name
  146. views::View* name_view = folder_header_view_->GetFolderNameViewForTest();
  147. const gfx::Rect name_view_bounds = name_view->GetBoundsInScreen();
  148. // Tap folder name and check that folder renaming is triggered.
  149. SendTap(name_view, name_view_bounds.CenterPoint());
  150. base::RunLoop().RunUntilIdle();
  151. EXPECT_TRUE(name_view->HasFocus());
  152. // Clear focus from the folder name.
  153. name_view->GetFocusManager()->ClearFocus();
  154. ASSERT_FALSE(name_view->HasFocus());
  155. // Test that tapping near (but not directly on) the folder name still
  156. // triggers folder rename.
  157. gfx::Point right_of_name_view = name_view_bounds.right_center();
  158. right_of_name_view.Offset(2, 0);
  159. SendTap(name_view, right_of_name_view);
  160. base::RunLoop().RunUntilIdle();
  161. EXPECT_TRUE(name_view->HasFocus());
  162. // Clear focus from the folder name.
  163. name_view->GetFocusManager()->ClearFocus();
  164. ASSERT_FALSE(name_view->HasFocus());
  165. // Test that clicking in the same spot won't trigger folder rename.
  166. SendPress(name_view, right_of_name_view);
  167. EXPECT_FALSE(name_view->HasFocus());
  168. }
  169. // Test that hitting the return key sets the folder name.
  170. TEST_F(FolderHeaderViewTest, SetFolderNameOnReturn) {
  171. // Create a folder with empty folder name.
  172. AppListFolderItem* folder_item = model_->CreateAndPopulateFolderWithApps(2);
  173. ShowAppListAndOpenFolder();
  174. ASSERT_EQ("", GetFolderNameFromUI());
  175. ASSERT_TRUE(CanEditFolderName());
  176. // Focus the text.
  177. FocusText();
  178. ASSERT_TRUE(HasTextFocus());
  179. // Set the folder name.
  180. UpdateFolderName("ret");
  181. EXPECT_EQ("ret", GetFolderNameFromUI());
  182. // Press return.
  183. SendKey(ui::VKEY_RETURN);
  184. // Make sure the return press unfocused the text and registered the name
  185. // change.
  186. EXPECT_FALSE(HasTextFocus());
  187. EXPECT_EQ("ret", folder_item->name());
  188. }
  189. // Test that hitting the escape key reverts the folder name.
  190. TEST_F(FolderHeaderViewTest, RevertFolderNameOnEscape) {
  191. // Create a folder with empty folder name.
  192. AppListFolderItem* folder_item = model_->CreateAndPopulateFolderWithApps(2);
  193. ShowAppListAndOpenFolder();
  194. ASSERT_EQ("", GetFolderNameFromUI());
  195. ASSERT_TRUE(CanEditFolderName());
  196. // Focus the text.
  197. FocusText();
  198. ASSERT_TRUE(HasTextFocus());
  199. // Set the folder name.
  200. UpdateFolderName("esc");
  201. EXPECT_EQ("esc", GetFolderNameFromUI());
  202. // Press escape.
  203. SendKey(ui::VKEY_ESCAPE);
  204. // Make sure the escape press unfocused the text and reverted the name change.
  205. EXPECT_FALSE(HasTextFocus());
  206. EXPECT_EQ("", folder_item->name());
  207. }
  208. } // namespace ash