123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- // Copyright (c) 2014 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/app_list/views/folder_header_view.h"
- #include <stddef.h>
- #include <memory>
- #include <string>
- #include <utility>
- #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_test_model.h"
- #include "ash/app_list/test/app_list_test_helper.h"
- #include "ash/app_list/views/app_list_folder_view.h"
- #include "ash/app_list/views/apps_grid_view_test_api.h"
- #include "ash/app_list/views/scrollable_apps_grid_view.h"
- #include "ash/test/ash_test_base.h"
- #include "base/strings/utf_string_conversions.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "ui/events/event.h"
- #include "ui/events/keycodes/keyboard_codes_posix.h"
- #include "ui/views/controls/textfield/textfield.h"
- namespace ash {
- class FolderHeaderViewTest : public AshTestBase {
- public:
- FolderHeaderViewTest() = default;
- FolderHeaderViewTest(const FolderHeaderViewTest&) = delete;
- FolderHeaderViewTest& operator=(const FolderHeaderViewTest&) = delete;
- ~FolderHeaderViewTest() override = default;
- // testing::Test overrides:
- void SetUp() override {
- AshTestBase::SetUp();
- model_ = GetAppListTestHelper()->model();
- // `folder_header_view_` is set when the folder is opened. This allows test
- // cases to configure the model before opening the folder.
- }
- // Assumes the folder is the first item in the grid.
- void ShowAppListAndOpenFolder() {
- auto* helper = GetAppListTestHelper();
- helper->ShowAppList();
- AppsGridView* apps_grid_view = helper->GetScrollableAppsGridView();
- ASSERT_TRUE(apps_grid_view);
- test::AppsGridViewTestApi(apps_grid_view).PressItemAt(0);
- ASSERT_TRUE(helper->IsInFolderView());
- folder_header_view_ = helper->GetBubbleFolderView()->folder_header_view();
- }
- protected:
- void UpdateFolderName(const std::string& name) {
- std::u16string folder_name = base::UTF8ToUTF16(name);
- folder_header_view_->SetFolderNameForTest(folder_name);
- folder_header_view_->ContentsChanged(
- folder_header_view_->GetFolderNameViewForTest(), folder_name);
- }
- const std::string GetFolderNameFromUI() {
- return base::UTF16ToUTF8(folder_header_view_->GetFolderNameForTest());
- }
- bool CanEditFolderName() {
- return folder_header_view_->IsFolderNameEnabledForTest();
- }
- void FocusText() { folder_header_view_->SetTextFocus(); }
- bool HasTextFocus() { return folder_header_view_->HasTextFocus(); }
- void SendKey(ui::KeyboardCode key_code, int flags = ui::EF_NONE) {
- PressAndReleaseKey(key_code, flags);
- }
- test::AppListTestModel* model_ = nullptr;
- FolderHeaderView* folder_header_view_ = nullptr;
- };
- TEST_F(FolderHeaderViewTest, WhitespaceCollapsedWhenFolderNameViewLosesFocus) {
- AppListFolderItem* folder_item = model_->CreateAndPopulateFolderWithApps(2);
- ShowAppListAndOpenFolder();
- views::View* name_view = folder_header_view_->GetFolderNameViewForTest();
- name_view->RequestFocus();
- UpdateFolderName(" N A ");
- name_view->GetFocusManager()->ClearFocus();
- // Expect that the folder name contains the same string with collapsed
- // whitespace.
- EXPECT_EQ("N A", folder_item->name());
- }
- TEST_F(FolderHeaderViewTest, MaxFolderNameLength) {
- // Creating a folder with empty folder name.
- AppListFolderItem* folder_item = model_->CreateAndPopulateFolderWithApps(2);
- ShowAppListAndOpenFolder();
- EXPECT_EQ("", GetFolderNameFromUI());
- EXPECT_TRUE(CanEditFolderName());
- // Update UI to set folder name to really long one beyond its maximum limit
- // If folder name is set beyond the maximum char limit, it should revert to
- // the previous valid folder name.
- std::string max_len_name;
- for (int i = 0; i < folder_header_view_->GetMaxFolderNameCharLengthForTest();
- ++i) {
- max_len_name += "a";
- }
- std::string too_long_name = max_len_name + "a";
- // Expect that the folder name does not change, and does not truncate
- UpdateFolderName(too_long_name);
- EXPECT_EQ(std::string(), folder_item->name());
- // Expect the folder does change to the new valid name given
- UpdateFolderName(max_len_name);
- EXPECT_EQ(max_len_name, folder_item->name());
- // Expect that the name is reverted to the previous valid name and is not
- // truncated
- too_long_name.insert(5, "testing");
- UpdateFolderName(too_long_name);
- EXPECT_EQ(max_len_name, folder_item->name());
- }
- TEST_F(FolderHeaderViewTest, OemFolderNameNotEditable) {
- model_->CreateAndAddOemFolder();
- ShowAppListAndOpenFolder();
- EXPECT_EQ("", GetFolderNameFromUI());
- EXPECT_FALSE(CanEditFolderName());
- }
- namespace {
- // Sends a tap gesture with events corresponding to touch-down and touch-up.
- // This is a template to support a |handler| with an OnGestureEvent() method
- // such as views::Widget or views::View.
- template <typename GestureHandler>
- void SendTap(GestureHandler* handler, const gfx::Point& location) {
- ui::GestureEvent tap_down(
- location.x(), location.y(), 0, base::TimeTicks::Now(),
- ui::GestureEventDetails(ui::EventType::ET_GESTURE_TAP_DOWN));
- handler->OnGestureEvent(&tap_down);
- ui::GestureEvent tap_up(
- location.x(), location.y(), 0, base::TimeTicks::Now(),
- ui::GestureEventDetails(ui::EventType::ET_GESTURE_TAP));
- handler->OnGestureEvent(&tap_up);
- }
- template <typename EventHandler>
- void SendPress(EventHandler* handler, const gfx::Point& location) {
- ui::MouseEvent press_down(ui::ET_MOUSE_PRESSED,
- gfx::PointF(location.x(), location.y()),
- gfx::PointF(0, 0), base::TimeTicks::Now(), 0, 0);
- handler->OnMouseEvent(&press_down);
- ui::MouseEvent press_up(ui::ET_MOUSE_RELEASED,
- gfx::PointF(location.x(), location.y()),
- gfx::PointF(0, 0), base::TimeTicks::Now(), 0, 0);
- handler->OnMouseEvent(&press_up);
- }
- } // namespace
- // Tests that when folder name is small, the folder name textfield is triggered
- // by only tap when on the textfieldd or near it to the left/right.
- TEST_F(FolderHeaderViewTest, TriggerFolderRenameAfterTappingNearFolderName) {
- // Create a folder with a small name.
- model_->CreateAndPopulateFolderWithApps(2);
- ShowAppListAndOpenFolder();
- UpdateFolderName("ab");
- // Get in screen bounds of folder name
- views::View* name_view = folder_header_view_->GetFolderNameViewForTest();
- const gfx::Rect name_view_bounds = name_view->GetBoundsInScreen();
- // Tap folder name and check that folder renaming is triggered.
- SendTap(name_view, name_view_bounds.CenterPoint());
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(name_view->HasFocus());
- // Clear focus from the folder name.
- name_view->GetFocusManager()->ClearFocus();
- ASSERT_FALSE(name_view->HasFocus());
- // Test that tapping near (but not directly on) the folder name still
- // triggers folder rename.
- gfx::Point right_of_name_view = name_view_bounds.right_center();
- right_of_name_view.Offset(2, 0);
- SendTap(name_view, right_of_name_view);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(name_view->HasFocus());
- // Clear focus from the folder name.
- name_view->GetFocusManager()->ClearFocus();
- ASSERT_FALSE(name_view->HasFocus());
- // Test that clicking in the same spot won't trigger folder rename.
- SendPress(name_view, right_of_name_view);
- EXPECT_FALSE(name_view->HasFocus());
- }
- // Test that hitting the return key sets the folder name.
- TEST_F(FolderHeaderViewTest, SetFolderNameOnReturn) {
- // Create a folder with empty folder name.
- AppListFolderItem* folder_item = model_->CreateAndPopulateFolderWithApps(2);
- ShowAppListAndOpenFolder();
- ASSERT_EQ("", GetFolderNameFromUI());
- ASSERT_TRUE(CanEditFolderName());
- // Focus the text.
- FocusText();
- ASSERT_TRUE(HasTextFocus());
- // Set the folder name.
- UpdateFolderName("ret");
- EXPECT_EQ("ret", GetFolderNameFromUI());
- // Press return.
- SendKey(ui::VKEY_RETURN);
- // Make sure the return press unfocused the text and registered the name
- // change.
- EXPECT_FALSE(HasTextFocus());
- EXPECT_EQ("ret", folder_item->name());
- }
- // Test that hitting the escape key reverts the folder name.
- TEST_F(FolderHeaderViewTest, RevertFolderNameOnEscape) {
- // Create a folder with empty folder name.
- AppListFolderItem* folder_item = model_->CreateAndPopulateFolderWithApps(2);
- ShowAppListAndOpenFolder();
- ASSERT_EQ("", GetFolderNameFromUI());
- ASSERT_TRUE(CanEditFolderName());
- // Focus the text.
- FocusText();
- ASSERT_TRUE(HasTextFocus());
- // Set the folder name.
- UpdateFolderName("esc");
- EXPECT_EQ("esc", GetFolderNameFromUI());
- // Press escape.
- SendKey(ui::VKEY_ESCAPE);
- // Make sure the escape press unfocused the text and reverted the name change.
- EXPECT_FALSE(HasTextFocus());
- EXPECT_EQ("", folder_item->name());
- }
- } // namespace ash
|