123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- // Copyright 2018 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/system/unified/feature_pods_container_view.h"
- #include "ash/public/cpp/pagination/pagination_controller.h"
- #include "ash/public/cpp/pagination/pagination_model.h"
- #include "ash/system/tray/tray_constants.h"
- #include "ash/system/unified/feature_pod_button.h"
- #include "ash/system/unified/feature_pod_controller_base.h"
- #include "ash/system/unified/unified_system_tray_controller.h"
- #include "ash/system/unified/unified_system_tray_model.h"
- #include "ash/test/ash_test_base.h"
- #include "base/memory/scoped_refptr.h"
- #include "ui/accessibility/ax_enums.mojom.h"
- #include "ui/accessibility/ax_node_data.h"
- #include "ui/views/view_observer.h"
- namespace ash {
- class FeaturePodsContainerViewTest : public NoSessionAshTestBase,
- public FeaturePodControllerBase,
- public views::ViewObserver {
- public:
- FeaturePodsContainerViewTest() = default;
- FeaturePodsContainerViewTest(const FeaturePodsContainerViewTest&) = delete;
- FeaturePodsContainerViewTest& operator=(const FeaturePodsContainerViewTest&) =
- delete;
- ~FeaturePodsContainerViewTest() override = default;
- // AshTestBase:
- void SetUp() override {
- AshTestBase::SetUp();
- model_ = base::MakeRefCounted<UnifiedSystemTrayModel>(nullptr);
- controller_ = std::make_unique<UnifiedSystemTrayController>(model_.get());
- container_ = std::make_unique<FeaturePodsContainerView>(
- controller_.get(), true /* initially_expanded */);
- container_->AddObserver(this);
- preferred_size_changed_count_ = 0;
- }
- void TearDown() override {
- controller_.reset();
- container_.reset();
- model_.reset();
- NoSessionAshTestBase::TearDown();
- }
- // FeaturePodControllerBase:
- FeaturePodButton* CreateButton() override { return nullptr; }
- void OnIconPressed() override {}
- SystemTrayItemUmaType GetUmaType() const override {
- return SystemTrayItemUmaType::UMA_TEST;
- }
- // views::ViewObserver:
- void OnViewPreferredSizeChanged(views::View* observed_view) override {
- ++preferred_size_changed_count_;
- }
- protected:
- void AddButton(FeaturePodButton* button) {
- buttons_.push_back(button);
- container()->AddChildView(button);
- }
- void AddButtons(int count) {
- for (int i = 0; i < count; ++i)
- AddButton(new FeaturePodButton(this));
- container()->SetBoundsRect(gfx::Rect(container_->GetPreferredSize()));
- container()->Layout();
- }
- FeaturePodsContainerView* container() { return container_.get(); }
- PaginationModel* pagination_model() { return model_->pagination_model(); }
- UnifiedSystemTrayController* controller() { return controller_.get(); }
- int preferred_size_changed_count() const {
- return preferred_size_changed_count_;
- }
- std::vector<FeaturePodButton*> buttons_;
- private:
- std::unique_ptr<FeaturePodsContainerView> container_;
- scoped_refptr<UnifiedSystemTrayModel> model_;
- std::unique_ptr<UnifiedSystemTrayController> controller_;
- int preferred_size_changed_count_ = 0;
- };
- TEST_F(FeaturePodsContainerViewTest, ExpandedAndCollapsed) {
- const int kNumberOfAddedButtons = kUnifiedFeaturePodItemsInRow * 3;
- EXPECT_LT(kUnifiedFeaturePodMaxItemsInCollapsed, kNumberOfAddedButtons);
- AddButtons(kNumberOfAddedButtons);
- // In expanded state, buttons are laid out in plane.
- EXPECT_LT(buttons_[0]->x(), buttons_[1]->x());
- EXPECT_EQ(buttons_[0]->y(), buttons_[1]->y());
- // If the row exceeds kUnifiedFeaturePodItemsInRow, the next button is placed
- // right under the first button.
- EXPECT_EQ(buttons_[0]->x(), buttons_[kUnifiedFeaturePodItemsInRow]->x());
- EXPECT_LT(buttons_[0]->y(), buttons_[kUnifiedFeaturePodItemsInRow]->y());
- // All buttons are visible.
- for (auto* button : buttons_)
- EXPECT_TRUE(button->GetVisible());
- container()->SetExpandedAmount(0.0);
- // In collapsed state, all buttons are laid out horizontally.
- for (int i = 1; i < kUnifiedFeaturePodMaxItemsInCollapsed; ++i)
- EXPECT_EQ(buttons_[0]->y(), buttons_[i]->y());
- // Buttons exceed kUnifiedFeaturePodMaxItemsInCollapsed are invisible.
- for (int i = 0; i < kNumberOfAddedButtons; ++i) {
- EXPECT_EQ(i < kUnifiedFeaturePodMaxItemsInCollapsed,
- buttons_[i]->GetVisible());
- }
- }
- TEST_F(FeaturePodsContainerViewTest, HiddenButtonRemainsHidden) {
- AddButtons(kUnifiedFeaturePodMaxItemsInCollapsed);
- // The button is invisible in expanded state.
- buttons_.front()->SetVisible(false);
- container()->SetExpandedAmount(0.0);
- EXPECT_FALSE(buttons_.front()->GetVisible());
- container()->SetExpandedAmount(1.0);
- EXPECT_FALSE(buttons_.front()->GetVisible());
- }
- TEST_F(FeaturePodsContainerViewTest, BecomeVisibleInCollapsed) {
- AddButtons(kUnifiedFeaturePodMaxItemsInCollapsed);
- // The button is invisible in expanded state.
- buttons_.back()->SetVisible(false);
- container()->SetExpandedAmount(0.0);
- // The button becomes visible in collapsed state.
- buttons_.back()->SetVisible(true);
- // As the container still has remaining space, the button will be visible.
- EXPECT_TRUE(buttons_.back()->GetVisible());
- }
- TEST_F(FeaturePodsContainerViewTest, StillHiddenInCollapsed) {
- AddButtons(kUnifiedFeaturePodMaxItemsInCollapsed + 1);
- // The button is invisible in expanded state.
- buttons_.back()->SetVisible(false);
- container()->SetExpandedAmount(0.0);
- // The button becomes visible in collapsed state.
- buttons_.back()->SetVisible(true);
- // As the container doesn't have remaining space, the button won't be visible.
- EXPECT_FALSE(buttons_.back()->GetVisible());
- container()->SetExpandedAmount(1.0);
- // The button becomes visible in expanded state.
- EXPECT_TRUE(buttons_.back()->GetVisible());
- }
- TEST_F(FeaturePodsContainerViewTest, DifferentButtonBecomeVisibleInCollapsed) {
- AddButtons(kUnifiedFeaturePodMaxItemsInCollapsed + 1);
- container()->SetExpandedAmount(0.0);
- // The last button is not visible as it doesn't have enough space.
- EXPECT_FALSE(buttons_.back()->GetVisible());
- // The first button becomes invisible.
- buttons_.front()->SetVisible(false);
- // The last button now has the space for it.
- EXPECT_TRUE(buttons_.back()->GetVisible());
- }
- TEST_F(FeaturePodsContainerViewTest, SizeChangeByExpanding) {
- // SetExpandedAmount() should not trigger PreferredSizeChanged().
- AddButtons(kUnifiedFeaturePodItemsInRow * 3 - 1);
- EXPECT_EQ(0, preferred_size_changed_count());
- container()->SetExpandedAmount(0.0);
- container()->SetExpandedAmount(0.5);
- container()->SetExpandedAmount(1.0);
- EXPECT_EQ(0, preferred_size_changed_count());
- }
- TEST_F(FeaturePodsContainerViewTest, SizeChangeByVisibility) {
- // Visibility change should trigger PreferredSizeChanged().
- AddButtons(kUnifiedFeaturePodItemsInRow * 2 + 1);
- EXPECT_EQ(0, preferred_size_changed_count());
- // The first button becomes invisible.
- buttons_.front()->SetVisible(false);
- EXPECT_EQ(1, preferred_size_changed_count());
- // The first button becomes visible.
- buttons_.front()->SetVisible(true);
- EXPECT_EQ(2, preferred_size_changed_count());
- }
- TEST_F(FeaturePodsContainerViewTest, NumberOfPagesChanged) {
- const int kNumberOfPages = 8;
- AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodMaxRows *
- kNumberOfPages);
- // Adding buttons to fill kNumberOfPages should cause the the same number of
- // pages to be created.
- EXPECT_EQ(kNumberOfPages, pagination_model()->total_pages());
- // Adding an additional button causes a new page to be added.
- AddButtons(1);
- EXPECT_EQ(pagination_model()->total_pages(), kNumberOfPages + 1);
- }
- TEST_F(FeaturePodsContainerViewTest, PaginationTransition) {
- const int kNumberOfPages = 8;
- AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodMaxRows *
- kNumberOfPages);
- // Position of a button should slide to the left during a page
- // transition to the next page.
- gfx::Rect current_bounds;
- gfx::Rect initial_bounds = buttons_[0]->bounds();
- gfx::Rect previous_bounds = initial_bounds;
- PaginationModel::Transition transition(
- pagination_model()->selected_page() + 1, 0);
- for (double i = 0.1; i <= 1.0; i += 0.1) {
- transition.progress = i;
- pagination_model()->SetTransition(transition);
- current_bounds = buttons_[0]->bounds();
- EXPECT_LT(current_bounds.x(), previous_bounds.x());
- EXPECT_EQ(current_bounds.y(), previous_bounds.y());
- previous_bounds = current_bounds;
- }
- // Button Position after page switch should move to the left by a page offset.
- int page_offset = container()->CalculatePreferredSize().width() +
- kUnifiedFeaturePodsPageSpacing;
- gfx::Rect final_bounds =
- gfx::Rect(initial_bounds.x() - page_offset, initial_bounds.y(),
- initial_bounds.width(), initial_bounds.height());
- pagination_model()->SelectPage(1, false);
- container()->Layout();
- EXPECT_EQ(final_bounds, buttons_[0]->bounds());
- }
- TEST_F(FeaturePodsContainerViewTest, PaginationDynamicRows) {
- const int kNumberOfFeaturePods = kUnifiedFeaturePodItemsInRow * 3;
- const int padding =
- kUnifiedFeaturePodTopPadding + kUnifiedFeaturePodBottomPadding;
- int row_height =
- kUnifiedFeaturePodSize.height() + kUnifiedFeaturePodVerticalPadding;
- int min_height_for_three_rows = kUnifiedFeaturePodMaxRows * row_height +
- padding + kMessageCenterCollapseThreshold;
- AddButtons(kNumberOfFeaturePods);
- // Expect 1 row of feature pods even if there is 0 height.
- container()->SetMaxHeight(0);
- int expected_number_of_pages =
- kNumberOfFeaturePods / kUnifiedFeaturePodItemsInRow;
- if (kNumberOfFeaturePods % kUnifiedFeaturePodItemsInRow)
- expected_number_of_pages += 1;
- EXPECT_EQ(expected_number_of_pages, pagination_model()->total_pages());
- // Expect 2 rows of feature pods when there is enough height to display them
- // but less than enough to display 3 rows.
- container()->SetMaxHeight(min_height_for_three_rows - 1);
- expected_number_of_pages =
- kNumberOfFeaturePods / (2 * kUnifiedFeaturePodItemsInRow);
- if (kNumberOfFeaturePods % (2 * kUnifiedFeaturePodItemsInRow))
- expected_number_of_pages += 1;
- EXPECT_EQ(expected_number_of_pages, pagination_model()->total_pages());
- // Expect 3 rows of feature pods at max even when the max height is very
- // large.
- container()->SetMaxHeight(min_height_for_three_rows + 1);
- expected_number_of_pages =
- kNumberOfFeaturePods / (3 * kUnifiedFeaturePodItemsInRow);
- if (kNumberOfFeaturePods % (3 * kUnifiedFeaturePodItemsInRow))
- expected_number_of_pages += 1;
- EXPECT_EQ(expected_number_of_pages, pagination_model()->total_pages());
- }
- TEST_F(FeaturePodsContainerViewTest, PaginationGestureHandling) {
- const int kNumberOfPages = 8;
- AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodMaxRows *
- kNumberOfPages);
- gfx::Point container_origin = container()->GetBoundsInScreen().origin();
- ui::GestureEvent swipe_left_begin(
- container_origin.x(), container_origin.y(), 0, base::TimeTicks(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, -1, 0));
- ui::GestureEvent swipe_left_update(
- container_origin.x(), container_origin.y(), 0, base::TimeTicks(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, -1000, 0));
- ui::GestureEvent swipe_right_begin(
- container_origin.x(), container_origin.y(), 0, base::TimeTicks(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 1, 0));
- ui::GestureEvent swipe_right_update(
- container_origin.x(), container_origin.y(), 0, base::TimeTicks(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 1000, 0));
- ui::GestureEvent swipe_end(container_origin.x(), container_origin.y(), 0,
- base::TimeTicks(),
- ui::GestureEventDetails(ui::ET_GESTURE_END));
- int previous_page = pagination_model()->selected_page();
- // Swipe left takes to next page
- for (int i = 0; i < kNumberOfPages - 1; i++) {
- // Simulate swipe left
- container()->OnGestureEvent(&swipe_left_begin);
- container()->OnGestureEvent(&swipe_left_update);
- container()->OnGestureEvent(&swipe_end);
- int current_page = pagination_model()->selected_page();
- // Expect next page
- EXPECT_EQ(previous_page + 1, current_page);
- previous_page = current_page;
- }
- // Swipe left on last page does nothing
- container()->OnGestureEvent(&swipe_left_begin);
- container()->OnGestureEvent(&swipe_left_update);
- container()->OnGestureEvent(&swipe_end);
- EXPECT_EQ(previous_page, pagination_model()->selected_page());
- // Swipe right takes to previous page
- for (int i = 0; i < kNumberOfPages - 1; i++) {
- // Simulate swipe right
- container()->OnGestureEvent(&swipe_right_begin);
- container()->OnGestureEvent(&swipe_right_update);
- container()->OnGestureEvent(&swipe_end);
- int current_page = pagination_model()->selected_page();
- // Expect previous page
- EXPECT_EQ(previous_page - 1, current_page);
- previous_page = current_page;
- }
- // Swipe right on first page does nothing
- container()->OnGestureEvent(&swipe_right_begin);
- container()->OnGestureEvent(&swipe_right_update);
- container()->OnGestureEvent(&swipe_end);
- EXPECT_EQ(previous_page, pagination_model()->selected_page());
- }
- TEST_F(FeaturePodsContainerViewTest, PaginationScrollHandling) {
- const int kNumberOfPages = 8;
- const int num_fingers = 2;
- AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodMaxRows *
- kNumberOfPages);
- EXPECT_EQ(kNumberOfPages, pagination_model()->total_pages());
- gfx::Point container_origin = container()->GetBoundsInScreen().origin();
- ui::ScrollEvent fling_up_start(ui::ET_SCROLL_FLING_START, container_origin,
- base::TimeTicks(), 0, 0, 100, 0, 10,
- num_fingers);
- ui::ScrollEvent fling_down_start(ui::ET_SCROLL_FLING_START, container_origin,
- base::TimeTicks(), 0, 0, -100, 0, 10,
- num_fingers);
- ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL, container_origin,
- base::TimeTicks(), 0, 0, 0, 0, 0, num_fingers);
- int previous_page = pagination_model()->selected_page();
- // Scroll down takes to next page
- for (int i = 0; i < kNumberOfPages - 1; i++) {
- // Simulate Scroll left
- container()->OnScrollEvent(&fling_down_start);
- container()->OnScrollEvent(&fling_cancel);
- pagination_model()->FinishAnimation();
- int current_page = pagination_model()->selected_page();
- // Expect next page
- EXPECT_EQ(previous_page + 1, current_page);
- previous_page = current_page;
- }
- // Scroll up takes to previous page
- for (int i = 0; i < kNumberOfPages - 1; i++) {
- // Simulate Scroll up
- container()->OnScrollEvent(&fling_up_start);
- container()->OnScrollEvent(&fling_cancel);
- pagination_model()->FinishAnimation();
- int current_page = pagination_model()->selected_page();
- // Expect previous page
- EXPECT_EQ(previous_page - 1, current_page);
- previous_page = current_page;
- }
- }
- TEST_F(FeaturePodsContainerViewTest, PaginationMouseWheelHandling) {
- const int kNumberOfPages = 8;
- AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodMaxRows *
- kNumberOfPages);
- gfx::Point container_origin = container()->GetBoundsInScreen().origin();
- ui::MouseWheelEvent wheel_up(gfx::Vector2d(0, 1000), container_origin,
- container_origin, base::TimeTicks(), 0, 0);
- ui::MouseWheelEvent wheel_down(gfx::Vector2d(0, -1000), container_origin,
- container_origin, base::TimeTicks(), 0, 0);
- int previous_page = pagination_model()->selected_page();
- // Mouse wheel down takes to next page
- for (int i = 0; i < kNumberOfPages - 1; i++) {
- // Simulate mouse wheel down
- container()->OnMouseWheel(wheel_down);
- pagination_model()->FinishAnimation();
- int current_page = pagination_model()->selected_page();
- // Expect next page
- EXPECT_EQ(previous_page + 1, current_page);
- previous_page = current_page;
- }
- // Mouse wheel up takes to previous page
- for (int i = 0; i < kNumberOfPages - 1; i++) {
- // Simulate mouse wheel up
- container()->OnMouseWheel(wheel_up);
- pagination_model()->FinishAnimation();
- int current_page = pagination_model()->selected_page();
- // Expect previous page
- EXPECT_EQ(previous_page - 1, current_page);
- previous_page = current_page;
- }
- }
- TEST_F(FeaturePodsContainerViewTest, NonTogglableButton) {
- // Add one togglable and one non-tobblable button.
- AddButton(new FeaturePodButton(this, /*is_togglable=*/false));
- AddButtons(1);
- // Non-togglable buttons should be labelled as a regular button for
- // accessibility and vice versa.
- ui::AXNodeData ax_node_data;
- buttons_[0]->icon_button()->GetAccessibleNodeData(&ax_node_data);
- EXPECT_EQ(ax_node_data.role, ax::mojom::Role::kButton);
- buttons_[1]->icon_button()->GetAccessibleNodeData(&ax_node_data);
- EXPECT_EQ(ax_node_data.role, ax::mojom::Role::kToggleButton);
- }
- } // namespace ash
|