blob: 4c5d2459aa5cf9af3d571dd4526111975b25b03e [file] [log] [blame]
// Copyright 2019 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/message_center/unified_message_center_bubble.h"
#include <memory>
#include "ash/public/cpp/ash_features.h"
#include "ash/shell.h"
#include "ash/system/message_center/unified_message_center_view.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/unified/unified_system_tray.h"
#include "ash/system/unified/unified_system_tray_bubble.h"
#include "ash/system/unified/unified_system_tray_controller.h"
#include "ash/system/unified/unified_system_tray_view.h"
#include "ash/test/ash_test_base.h"
#include "ui/message_center/message_center.h"
using message_center::MessageCenter;
using message_center::Notification;
#include <iostream>
namespace ash {
class UnifiedMessageCenterBubbleTest : public AshTestBase {
public:
UnifiedMessageCenterBubbleTest() = default;
~UnifiedMessageCenterBubbleTest() override = default;
// AshTestBase:
void SetUp() override {
AshTestBase::SetUp();
}
protected:
std::string AddNotification() {
std::string id = base::NumberToString(id_++);
MessageCenter::Get()->AddNotification(std::make_unique<Notification>(
message_center::NOTIFICATION_TYPE_BASE_FORMAT, id,
base::UTF8ToUTF16("test title"), base::UTF8ToUTF16("test message"),
gfx::Image(), base::string16() /* display_source */, GURL(),
message_center::NotifierId(), message_center::RichNotificationData(),
new message_center::NotificationDelegate()));
return id;
}
UnifiedMessageCenterBubble* GetMessageCenterBubble() {
return GetPrimaryUnifiedSystemTray()->message_center_bubble();
}
UnifiedSystemTrayBubble* GetSystemTrayBubble() {
return GetPrimaryUnifiedSystemTray()->bubble();
}
int MessageCenterSeparationHeight() {
gfx::Rect message_bubble_bounds =
GetMessageCenterBubble()->GetBubbleView()->GetBoundsInScreen();
gfx::Rect tray_bounds =
GetSystemTrayBubble()->GetBubbleView()->GetBoundsInScreen();
return message_bubble_bounds.y() + message_bubble_bounds.height() -
tray_bounds.y();
}
bool IsMessageCenterCollapsed() {
return GetMessageCenterBubble()->message_center_view()->collapsed();
}
bool IsQuickSettingsCollapsed() {
return !GetSystemTrayBubble()->controller_for_test()->IsExpanded();
}
// Helper functions for focus cycle testing.
void DoTab() {
ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
generator.PressKey(ui::KeyboardCode::VKEY_TAB, ui::EventFlags::EF_NONE);
}
void DoShiftTab() {
ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
generator.PressKey(ui::KeyboardCode::VKEY_TAB,
ui::EventFlags::EF_SHIFT_DOWN);
}
void ToggleExpanded() {
GetSystemTrayBubble()->controller_for_test()->ToggleExpanded();
}
void WaitForAnimation() {
while (GetSystemTrayBubble()
->controller_for_test()
->animation_->is_animating())
base::RunLoop().RunUntilIdle();
}
views::View* GetFirstMessageCenterFocusable() {
return GetMessageCenterBubble()
->message_center_view()
->GetFirstFocusableChild();
}
views::View* GetLastMessageCenterFocusable() {
return GetMessageCenterBubble()
->message_center_view()
->GetLastFocusableChild();
}
views::View* GetFirstQuickSettingsFocusable() {
return GetSystemTrayBubble()->unified_view()->GetFirstFocusableChild();
}
views::View* GetLastQuickSettingsFocusable() {
return GetSystemTrayBubble()->unified_view()->GetLastFocusableChild();
}
private:
int id_ = 0;
DISALLOW_COPY_AND_ASSIGN(UnifiedMessageCenterBubbleTest);
};
TEST_F(UnifiedMessageCenterBubbleTest, PositionedAboveSystemTray) {
const int total_notifications = 5;
GetPrimaryUnifiedSystemTray()->ShowBubble(true);
AddNotification();
const int reference_separation = MessageCenterSeparationHeight();
// The message center should be positioned a constant distance above
// the tray as it grows in size.
for (int i = 0; i < total_notifications; i++) {
AddNotification();
EXPECT_EQ(reference_separation, MessageCenterSeparationHeight());
}
// When the system tray is collapsing, message view should stay at a constant
// height above it.
for (double i = 1.0; i >= 0; i -= 0.1) {
GetSystemTrayBubble()->unified_view()->SetExpandedAmount(i);
EXPECT_EQ(reference_separation, MessageCenterSeparationHeight());
}
// When the system tray is collapsing, message view should stay at a constant
// height above it.
for (double i = 0.0; i <= 1.0; i += 0.1) {
GetSystemTrayBubble()->unified_view()->SetExpandedAmount(i);
EXPECT_EQ(reference_separation, MessageCenterSeparationHeight());
}
}
TEST_F(UnifiedMessageCenterBubbleTest, FocusCycle) {
GetPrimaryUnifiedSystemTray()->ShowBubble(true);
AddNotification();
AddNotification();
views::Widget* quick_settings_widget =
GetSystemTrayBubble()->GetBubbleWidget();
views::Widget* message_center_widget =
GetMessageCenterBubble()->GetBubbleWidget();
// First tab should focus the first element in the quick settings bubble.
DoTab();
EXPECT_TRUE(quick_settings_widget->IsActive());
EXPECT_FALSE(message_center_widget->IsActive());
EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(),
GetFirstQuickSettingsFocusable());
// Keep tabbing until we reach the last focusable element in the quick
// settings bubble.
while (quick_settings_widget->GetFocusManager()->GetFocusedView() !=
GetLastQuickSettingsFocusable()) {
DoTab();
}
// Tab at the last element in the quick settings bubble should move focus to
// the first element in the message center.
DoTab();
EXPECT_TRUE(message_center_widget->IsActive());
EXPECT_FALSE(quick_settings_widget->IsActive());
EXPECT_EQ(message_center_widget->GetFocusManager()->GetFocusedView(),
GetFirstMessageCenterFocusable());
// Keep tabbing until we reach the last focusable element in the message
// center bubble.
while (message_center_widget->GetFocusManager()->GetFocusedView() !=
GetLastMessageCenterFocusable()) {
DoTab();
}
// Tab at the last element in the message center bubble should move focus to
// the first element in the quick settings bubble.
DoTab();
EXPECT_TRUE(quick_settings_widget->IsActive());
EXPECT_FALSE(message_center_widget->IsActive());
EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(),
GetFirstQuickSettingsFocusable());
}
TEST_F(UnifiedMessageCenterBubbleTest, ReverseFocusCycle) {
GetPrimaryUnifiedSystemTray()->ShowBubble(true);
AddNotification();
AddNotification();
views::Widget* quick_settings_widget =
GetSystemTrayBubble()->GetBubbleWidget();
views::Widget* message_center_widget =
GetMessageCenterBubble()->GetBubbleWidget();
// First shift tab should focus the last element in the quick settings bubble.
DoShiftTab();
EXPECT_TRUE(quick_settings_widget->IsActive());
EXPECT_FALSE(message_center_widget->IsActive());
EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(),
GetLastQuickSettingsFocusable());
// Keep shift tabbing until we reach the first focusable element in the quick
// settings bubble.
while (quick_settings_widget->GetFocusManager()->GetFocusedView() !=
GetFirstQuickSettingsFocusable()) {
DoShiftTab();
}
// Shift tab at the first element in the quick settings bubble should move
// focus to the last element in the message center.
DoShiftTab();
EXPECT_TRUE(message_center_widget->IsActive());
EXPECT_FALSE(quick_settings_widget->IsActive());
EXPECT_EQ(message_center_widget->GetFocusManager()->GetFocusedView(),
GetLastMessageCenterFocusable());
// Keep shift tabbing until we reach the first focusable element in the
// message center bubble.
while (message_center_widget->GetFocusManager()->GetFocusedView() !=
GetFirstMessageCenterFocusable()) {
DoShiftTab();
}
// Shift tab at the first element in the message center bubble should move
// focus to the last element in the quick settings bubble.
DoShiftTab();
EXPECT_TRUE(quick_settings_widget->IsActive());
EXPECT_FALSE(message_center_widget->IsActive());
EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(),
GetLastQuickSettingsFocusable());
}
TEST_F(UnifiedMessageCenterBubbleTest, CollapseState) {
AddNotification();
AddNotification();
GetPrimaryUnifiedSystemTray()->ShowBubble(true);
int small_display_height =
GetSystemTrayBubble()->unified_view()->GetCollapsedSystemTrayHeight() +
(2 * kMessageCenterCollapseThreshold);
int large_display_height =
GetSystemTrayBubble()->unified_view()->GetExpandedSystemTrayHeight() +
(4 * kMessageCenterCollapseThreshold);
GetPrimaryUnifiedSystemTray()->CloseBubble();
// Message center should open in expanded state when screen height is
// limited.
UpdateDisplay(base::StringPrintf("1000x%d", small_display_height));
GetPrimaryUnifiedSystemTray()->ShowBubble(true);
WaitForAnimation();
EXPECT_TRUE(IsQuickSettingsCollapsed());
EXPECT_FALSE(IsMessageCenterCollapsed());
// Message center should be collapsed when quick settings is expanded
// with limited screen height.
ToggleExpanded();
WaitForAnimation();
EXPECT_TRUE(IsMessageCenterCollapsed());
ToggleExpanded();
WaitForAnimation();
EXPECT_FALSE(IsMessageCenterCollapsed());
GetPrimaryUnifiedSystemTray()->CloseBubble();
UpdateDisplay(base::StringPrintf("1000x%d", large_display_height));
GetPrimaryUnifiedSystemTray()->ShowBubble(true);
EXPECT_FALSE(IsMessageCenterCollapsed());
ToggleExpanded();
WaitForAnimation();
EXPECT_FALSE(IsMessageCenterCollapsed());
ToggleExpanded();
WaitForAnimation();
EXPECT_FALSE(IsMessageCenterCollapsed());
}
TEST_F(UnifiedMessageCenterBubbleTest, FocusCycleWithNoNotifications) {
GetPrimaryUnifiedSystemTray()->ShowBubble(true);
views::Widget* quick_settings_widget =
GetSystemTrayBubble()->GetBubbleWidget();
views::Widget* message_center_widget =
GetMessageCenterBubble()->GetBubbleWidget();
// First tab should focus the first element in the quick settings bubble.
DoTab();
EXPECT_TRUE(quick_settings_widget->IsActive());
EXPECT_FALSE(message_center_widget->IsActive());
EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(),
GetFirstQuickSettingsFocusable());
// Keep tabbing until we reach the last focusable element in the quick
// settings bubble.
while (quick_settings_widget->GetFocusManager()->GetFocusedView() !=
GetLastQuickSettingsFocusable()) {
DoTab();
}
// Tab at the last element in the quick settings bubble should move focus to
// the first element in the quick settings bubble.
DoTab();
EXPECT_TRUE(quick_settings_widget->IsActive());
EXPECT_FALSE(message_center_widget->IsActive());
EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(),
GetFirstQuickSettingsFocusable());
}
} // namespace ash