| // Copyright 2013 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/message_center/views/message_popup_collection.h" |
| |
| #include <vector> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "build/build_config.h" |
| #include "ui/display/display.h" |
| #include "ui/events/base_event_utils.h" |
| #include "ui/gfx/animation/linear_animation.h" |
| #include "ui/message_center/message_center.h" |
| #include "ui/message_center/public/cpp/message_center_constants.h" |
| #include "ui/message_center/public/cpp/notification_types.h" |
| #include "ui/message_center/views/desktop_message_popup_collection.h" |
| #include "ui/message_center/views/message_popup_view.h" |
| #include "ui/views/test/views_test_base.h" |
| |
| using message_center::MessageCenter; |
| using message_center::Notification; |
| |
| namespace message_center { |
| |
| namespace { |
| |
| class MockMessagePopupView; |
| |
| class MockMessagePopupCollection : public DesktopMessagePopupCollection { |
| public: |
| explicit MockMessagePopupCollection(gfx::NativeWindow context) |
| : context_(context) {} |
| |
| MockMessagePopupCollection(const MockMessagePopupCollection&) = delete; |
| MockMessagePopupCollection& operator=(const MockMessagePopupCollection&) = |
| delete; |
| |
| ~MockMessagePopupCollection() override = default; |
| |
| void SetAnimationValue(double current) { |
| animation()->SetCurrentValue(current); |
| if (current == 1.0) |
| animation()->End(); |
| else |
| AnimationProgressed(animation()); |
| } |
| |
| void RemovePopup(MockMessagePopupView* popup) { std::erase(popups_, popup); } |
| |
| bool IsAnimating() { return animation()->is_animating(); } |
| |
| void set_is_primary_display(bool is_primary_display) { |
| is_primary_display_ = is_primary_display; |
| } |
| |
| void set_is_fullscreen(bool is_fullscreen) { is_fullscreen_ = is_fullscreen; } |
| |
| void set_new_popup_height(int new_popup_height) { |
| new_popup_height_ = new_popup_height; |
| } |
| |
| std::vector<raw_ptr<MockMessagePopupView, VectorExperimental>>& popups() { |
| return popups_; |
| } |
| |
| bool popup_timer_started() const { return popup_timer_started_; } |
| |
| int popup_collection_height_changed() const { |
| return popup_collection_height_changed_; |
| } |
| |
| int notify_silent_notification_count() const { |
| return notify_silent_notification_count_; |
| } |
| |
| protected: |
| MessagePopupView* CreatePopup(const Notification& notification) override; |
| |
| void ConfigureWidgetInitParamsForContainer( |
| views::Widget* widget, |
| views::Widget::InitParams* init_params) override { |
| // Provides an aura window context for widget creation. |
| init_params->context = context_; |
| } |
| |
| void RestartPopupTimers() override { |
| MessagePopupCollection::RestartPopupTimers(); |
| popup_timer_started_ = true; |
| } |
| |
| void PausePopupTimers() override { |
| MessagePopupCollection::PausePopupTimers(); |
| popup_timer_started_ = false; |
| } |
| |
| bool IsPrimaryDisplayForNotification() const override { |
| return is_primary_display_; |
| } |
| |
| bool BlockForMixedFullscreen( |
| const Notification& notification) const override { |
| return is_fullscreen_; |
| } |
| |
| void NotifyPopupCollectionHeightChanged() override { |
| ++popup_collection_height_changed_; |
| } |
| |
| void NotifySilentNotification(const std::string& notification_id) override { |
| ++notify_silent_notification_count_; |
| } |
| |
| private: |
| gfx::NativeWindow context_; |
| |
| std::vector<raw_ptr<MockMessagePopupView, VectorExperimental>> popups_; |
| |
| bool popup_timer_started_ = false; |
| bool is_primary_display_ = true; |
| bool is_fullscreen_ = false; |
| int new_popup_height_ = 84; |
| int popup_collection_height_changed_ = 0; |
| int notify_silent_notification_count_ = 0; |
| }; |
| |
| class MockMessagePopupView : public MessagePopupView { |
| public: |
| MockMessagePopupView(const std::string& id, |
| int init_height, |
| MockMessagePopupCollection* popup_collection) |
| : MessagePopupView(popup_collection), |
| popup_collection_(popup_collection), |
| id_(id), |
| title_(base::UTF16ToUTF8( |
| MessageCenter::Get()->FindVisibleNotificationById(id)->title())) { |
| auto* view = new views::View; |
| view->SetPreferredSize(gfx::Size(GetNotificationWidth(), init_height)); |
| AddChildView(view); |
| } |
| |
| ~MockMessagePopupView() override = default; |
| |
| void Close() override { |
| popup_collection_->RemovePopup(this); |
| MessagePopupView::Close(); |
| } |
| |
| void UpdateContents(const Notification& notification) override { |
| if (height_after_update_.has_value()) |
| SetPreferredHeight(height_after_update_.value()); |
| popup_collection_->NotifyPopupResized(); |
| updated_ = true; |
| title_ = base::UTF16ToUTF8(notification.title()); |
| } |
| |
| void UpdateContentsForChildNotification( |
| const std::string& notification_id, |
| const Notification& notification) override { |
| child_updated_ = true; |
| child_updated_notification_id_ = notification_id; |
| child_updated_title_ = base::UTF16ToUTF8(notification.title()); |
| } |
| |
| void AutoCollapse() override { |
| if (expandable_) |
| children().front()->SetPreferredSize( |
| gfx::Size(GetNotificationWidth(), 42)); |
| } |
| |
| void SetPreferredHeight(int height) { |
| children().front()->SetPreferredSize( |
| gfx::Size(GetNotificationWidth(), height)); |
| } |
| |
| void SetHovered(bool is_hovered) { |
| if (is_hovered) { |
| ui::MouseEvent enter_event(ui::ET_MOUSE_ENTERED, gfx::Point(), |
| gfx::Point(), ui::EventTimeForNow(), 0, 0); |
| OnMouseEntered(enter_event); |
| } else { |
| ui::MouseEvent exit_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), |
| ui::EventTimeForNow(), 0, 0); |
| OnMouseExited(exit_event); |
| } |
| } |
| |
| void SimulateFocused() { OnDidChangeFocus(nullptr, children().front()); } |
| |
| void Activate() { |
| SetCanActivate(true); |
| GetWidget()->Activate(); |
| } |
| |
| const std::string& id() const { return id_; } |
| bool updated() const { return updated_; } |
| |
| bool child_updated() const { return child_updated_; } |
| const std::string& child_updated_notification_id() { |
| return child_updated_notification_id_; |
| } |
| const std::string& child_updated_title() { return child_updated_title_; } |
| |
| const std::string& title() const { return title_; } |
| |
| void set_expandable(bool expandable) { expandable_ = expandable; } |
| |
| void set_height_after_update(std::optional<int> height_after_update) { |
| height_after_update_ = height_after_update; |
| } |
| |
| private: |
| const raw_ptr<MockMessagePopupCollection> popup_collection_; |
| |
| std::string id_; |
| bool updated_ = false; |
| |
| bool child_updated_ = false; |
| std::string child_updated_notification_id_; |
| std::string child_updated_title_; |
| |
| bool expandable_ = false; |
| std::string title_; |
| |
| std::optional<int> height_after_update_; |
| }; |
| |
| MessagePopupView* MockMessagePopupCollection::CreatePopup( |
| const Notification& notification) { |
| auto* popup = |
| new MockMessagePopupView(notification.id(), new_popup_height_, this); |
| popups_.push_back(popup); |
| return popup; |
| } |
| |
| } // namespace |
| |
| class MessagePopupCollectionTest : public views::ViewsTestBase, |
| public MessageCenterObserver { |
| public: |
| MessagePopupCollectionTest() = default; |
| |
| MessagePopupCollectionTest(const MessagePopupCollectionTest&) = delete; |
| MessagePopupCollectionTest& operator=(const MessagePopupCollectionTest&) = |
| delete; |
| |
| ~MessagePopupCollectionTest() override = default; |
| |
| // views::ViewTestBase: |
| void SetUp() override { |
| views::ViewsTestBase::SetUp(); |
| MessageCenter::Initialize(); |
| MessageCenter::Get()->DisableTimersForTest(); |
| MessageCenter::Get()->AddObserver(this); |
| |
| popup_collection_ = |
| std::make_unique<MockMessagePopupCollection>(GetContext()); |
| |
| // This size fits test machines resolution and also can keep a few popups |
| // w/o ill effects of hitting the screen overflow. This allows us to assume |
| // and verify normal layout of the toast stack. |
| SetDisplayInfo(gfx::Rect(0, 0, 1920, 1070), // taskbar at the bottom. |
| gfx::Rect(0, 0, 1920, 1080)); |
| } |
| |
| void TearDown() override { |
| MessageCenter::Get()->RemoveAllNotifications( |
| false /* by_user */, MessageCenter::RemoveType::ALL); |
| AnimateUntilIdle(); |
| popup_collection_.reset(); |
| |
| MessageCenter::Get()->RemoveObserver(this); |
| MessageCenter::Shutdown(); |
| views::ViewsTestBase::TearDown(); |
| } |
| |
| // MessageCenterObserver: |
| void OnNotificationDisplayed(const std::string& notification_id, |
| const DisplaySource source) override { |
| last_displayed_id_ = notification_id; |
| } |
| |
| protected: |
| std::unique_ptr<Notification> CreateNotification(const std::string& id) { |
| return CreateNotification(id, "test title"); |
| } |
| |
| std::unique_ptr<Notification> CreateNotification(const std::string& id, |
| const std::string& title) { |
| return std::make_unique<Notification>( |
| NOTIFICATION_TYPE_SIMPLE, id, base::UTF8ToUTF16(title), u"test message", |
| ui::ImageModel(), std::u16string() /* display_source */, GURL(), |
| NotifierId(), RichNotificationData(), new NotificationDelegate()); |
| } |
| |
| std::unique_ptr<Notification> CreateLowPriorityNotification() { |
| std::unique_ptr<Notification> notification = |
| CreateNotification(base::NumberToString(id_++)); |
| notification->set_priority(LOW_PRIORITY); |
| return notification; |
| } |
| |
| std::string AddNotification() { |
| std::string id = base::NumberToString(id_++); |
| MessageCenter::Get()->AddNotification(CreateNotification(id)); |
| return id; |
| } |
| |
| void AddNotification(std::unique_ptr<Notification> notification) { |
| MessageCenter::Get()->AddNotification(std::move(notification)); |
| } |
| |
| void Update() { popup_collection_->Update(); } |
| |
| void SetAnimationValue(double current) { |
| popup_collection_->SetAnimationValue(current); |
| } |
| |
| bool IsAnimating() const { return popup_collection_->IsAnimating(); } |
| |
| void AnimateUntilIdle() { |
| while (popup_collection_->IsAnimating()) { |
| popup_collection_->SetAnimationValue(1.0); |
| } |
| } |
| |
| void AnimateToMiddle() { |
| EXPECT_TRUE(popup_collection_->IsAnimating()); |
| popup_collection_->SetAnimationValue(0.5); |
| } |
| |
| void AnimateToEnd() { |
| EXPECT_TRUE(popup_collection_->IsAnimating()); |
| popup_collection_->SetAnimationValue(1.0); |
| } |
| |
| MockMessagePopupView* GetPopup(const std::string& id) { |
| for (MockMessagePopupView* popup : popup_collection_->popups()) { |
| if (popup->id() == id) |
| return popup; |
| } |
| return nullptr; |
| } |
| |
| MockMessagePopupView* GetPopupAt(size_t index) { |
| return popup_collection_->popups()[index]; |
| } |
| |
| void CloseAllPopupsNow() { popup_collection()->CloseAllPopupsNow(); } |
| |
| size_t GetPopupCounts() const { return popup_collection_->popups().size(); } |
| |
| void SetDisplayInfo(const gfx::Rect& work_area, |
| const gfx::Rect& display_bounds) { |
| display::Display dummy_display; |
| dummy_display.set_bounds(display_bounds); |
| dummy_display.set_work_area(work_area); |
| work_area_ = work_area; |
| popup_collection_->RecomputeAlignment(dummy_display); |
| } |
| |
| bool IsPopupTimerStarted() const { |
| return popup_collection_->popup_timer_started(); |
| } |
| |
| MockMessagePopupCollection* popup_collection() const { |
| return popup_collection_.get(); |
| } |
| const gfx::Rect& work_area() const { return work_area_; } |
| |
| const std::string& last_displayed_id() const { return last_displayed_id_; } |
| |
| private: |
| int id_ = 0; |
| |
| std::unique_ptr<MockMessagePopupCollection> popup_collection_; |
| |
| gfx::Rect work_area_; |
| std::string last_displayed_id_; |
| }; |
| |
| TEST_F(MessagePopupCollectionTest, Nothing) { |
| EXPECT_FALSE(IsAnimating()); |
| Update(); |
| // If no popups are available, nothing changes. |
| EXPECT_FALSE(IsAnimating()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, FadeInFadeOutNotification) { |
| // Add a notification. |
| std::string id = AddNotification(); |
| EXPECT_TRUE(IsAnimating()); |
| EXPECT_EQ(1u, GetPopupCounts()); |
| |
| // The popup will fade in from right. |
| const int before_x = GetPopup(id)->GetBoundsInScreen().x(); |
| EXPECT_EQ(0.0f, GetPopup(id)->GetOpacity()); |
| |
| AnimateToMiddle(); |
| EXPECT_GT(before_x, GetPopup(id)->GetBoundsInScreen().x()); |
| EXPECT_LT(0.0f, GetPopup(id)->GetOpacity()); |
| |
| AnimateToEnd(); |
| EXPECT_EQ(1.0f, GetPopup(id)->GetOpacity()); |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_TRUE(work_area().Contains(GetPopup(id)->GetBoundsInScreen())); |
| EXPECT_EQ(id, last_displayed_id()); |
| |
| // The popup will fade out because of timeout. |
| MessageCenter::Get()->MarkSinglePopupAsShown(id, false); |
| EXPECT_TRUE(IsAnimating()); |
| |
| AnimateToMiddle(); |
| EXPECT_GT(1.0f, GetPopup(id)->GetOpacity()); |
| |
| AnimateToEnd(); |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_FALSE(GetPopup(id)); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, FadeInMultipleNotifications) { |
| std::vector<std::string> ids; |
| for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i) |
| ids.push_back(AddNotification()); |
| |
| for (size_t i = 0; i < ids.size(); ++i) { |
| EXPECT_EQ(ids[i], last_displayed_id()); |
| EXPECT_EQ(i + 1, GetPopupCounts()); |
| AnimateToMiddle(); |
| EXPECT_LT(0.0f, GetPopupAt(i)->GetOpacity()); |
| AnimateToEnd(); |
| EXPECT_EQ(1.0f, GetPopupAt(i)->GetOpacity()); |
| EXPECT_TRUE(work_area().Contains(GetPopupAt(i)->GetBoundsInScreen())); |
| } |
| EXPECT_FALSE(IsAnimating()); |
| |
| EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); |
| |
| for (size_t i = 0; i < ids.size(); ++i) |
| EXPECT_EQ(ids[i], GetPopupAt(i)->id()); |
| |
| for (size_t i = 0; i < ids.size() - 1; ++i) { |
| EXPECT_GT(GetPopupAt(i)->GetBoundsInScreen().x(), |
| GetPopupAt(i + 1)->GetBoundsInScreen().bottom()); |
| } |
| } |
| |
| TEST_F(MessagePopupCollectionTest, UpdateContents) { |
| std::string id = AddNotification(); |
| AnimateToEnd(); |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_EQ(1u, GetPopupCounts()); |
| EXPECT_FALSE(GetPopup(id)->updated()); |
| |
| auto updated_notification = CreateNotification(id); |
| updated_notification->set_message(u"updated"); |
| MessageCenter::Get()->UpdateNotification(id, std::move(updated_notification)); |
| EXPECT_EQ(1u, GetPopupCounts()); |
| EXPECT_TRUE(GetPopup(id)->updated()); |
| } |
| |
| // TODO(crbug.com/40885754): Flaky on all platforms. |
| TEST_F(MessagePopupCollectionTest, DISABLED_UpdateContentsCausesPopupClose) { |
| std::string id = AddNotification(); |
| AnimateToEnd(); |
| RunPendingMessages(); |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_EQ(1u, GetPopupCounts()); |
| EXPECT_FALSE(GetPopup(id)->updated()); |
| |
| GetPopup(id)->set_height_after_update(2048); |
| |
| auto updated_notification = CreateNotification(id); |
| updated_notification->set_message(u"updated"); |
| MessageCenter::Get()->UpdateNotification(id, std::move(updated_notification)); |
| RunPendingMessages(); |
| EXPECT_EQ(0u, GetPopupCounts()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, OnChildNotificationViewUpdated) { |
| std::string parent_id = AddNotification(); |
| std::string child_id = AddNotification(); |
| |
| const std::string new_notification_title("new_title"); |
| auto new_notification = CreateNotification(child_id, new_notification_title); |
| MessageCenter::Get()->UpdateNotification(child_id, |
| std::move(new_notification)); |
| |
| // Calling `OnChildNotificationViewUpdated()` should update the child |
| // notification in parent's popup. |
| popup_collection()->OnChildNotificationViewUpdated(parent_id, child_id); |
| |
| EXPECT_TRUE(GetPopup(parent_id)->child_updated()); |
| EXPECT_EQ(child_id, GetPopup(parent_id)->child_updated_notification_id()); |
| EXPECT_EQ(new_notification_title, GetPopup(parent_id)->child_updated_title()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, MessageCenterVisibility) { |
| // It only applies to a platform with MessageCenterView i.e. Chrome OS. |
| MessageCenter::Get()->SetHasMessageCenterView(true); |
| |
| for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i) |
| AddNotification(); |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); |
| |
| EXPECT_EQ(3u, GetPopupCounts()); |
| EXPECT_EQ(3u, MessageCenter::Get()->GetPopupNotifications().size()); |
| |
| // The notification should be hidden when MessageCenterView is visible. |
| MessageCenter::Get()->SetVisibility(Visibility::VISIBILITY_MESSAGE_CENTER); |
| // It should not animate in order to show ARC++ notifications properly. |
| EXPECT_FALSE(IsAnimating()); |
| |
| MessageCenter::Get()->SetVisibility(Visibility::VISIBILITY_TRANSIENT); |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_EQ(0u, GetPopupCounts()); |
| EXPECT_EQ(0u, MessageCenter::Get()->GetPopupNotifications().size()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, ShowCustomOnPrimaryDisplay) { |
| // TODO(yoshiki): Support custom popup notification on multiple display |
| // (crbug.com/715370). |
| popup_collection()->set_is_primary_display(true); |
| auto custom = CreateNotification("id"); |
| custom->set_type(NOTIFICATION_TYPE_CUSTOM); |
| MessageCenter::Get()->AddNotification(std::move(custom)); |
| EXPECT_TRUE(IsAnimating()); |
| EXPECT_EQ(1u, GetPopupCounts()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, NotShowCustomOnSubDisplay) { |
| // Disables popup of custom notification on non-primary displays, since |
| // currently custom notification supports only on one display at the same |
| // time. |
| // TODO(yoshiki): Support custom popup notification on multiple display |
| // (crbug.com/715370). |
| |
| popup_collection()->set_is_primary_display(false); |
| auto custom = CreateNotification("id"); |
| custom->set_type(NOTIFICATION_TYPE_CUSTOM); |
| MessageCenter::Get()->AddNotification(std::move(custom)); |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_EQ(0u, GetPopupCounts()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, MixedFullscreenShow) { |
| popup_collection()->set_is_fullscreen(false); |
| AddNotification(); |
| EXPECT_TRUE(IsAnimating()); |
| EXPECT_EQ(1u, GetPopupCounts()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, MixedFullscreenBlock) { |
| popup_collection()->set_is_fullscreen(true); |
| AddNotification(); |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_EQ(0u, GetPopupCounts()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, NotificationsMoveDown) { |
| std::vector<std::string> ids; |
| for (size_t i = 0; i < kMaxVisiblePopupNotifications + 1; ++i) |
| ids.push_back(AddNotification()); |
| |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); |
| EXPECT_FALSE(IsAnimating()); |
| |
| gfx::Rect dismissed = GetPopup(ids.front())->GetBoundsInScreen(); |
| |
| MessageCenter::Get()->MarkSinglePopupAsShown(ids.front(), false); |
| EXPECT_TRUE(IsAnimating()); |
| |
| AnimateToMiddle(); |
| EXPECT_GT(1.0f, GetPopup(ids[0])->GetOpacity()); |
| EXPECT_EQ(ids[0], GetPopup(ids[0])->id()); |
| |
| AnimateToEnd(); |
| EXPECT_EQ(ids[1], GetPopup(ids[1])->id()); |
| EXPECT_TRUE(IsAnimating()); |
| |
| gfx::Rect before = GetPopup(ids[1])->GetBoundsInScreen(); |
| |
| AnimateToMiddle(); |
| gfx::Rect moving = GetPopup(ids[1])->GetBoundsInScreen(); |
| EXPECT_GT(moving.bottom(), before.bottom()); |
| EXPECT_GT(dismissed.bottom(), moving.bottom()); |
| |
| AnimateToEnd(); |
| gfx::Rect after = GetPopup(ids[1])->GetBoundsInScreen(); |
| EXPECT_EQ(dismissed, after); |
| EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); |
| EXPECT_TRUE(IsAnimating()); |
| |
| EXPECT_EQ(0.f, GetPopup(ids.back())->GetOpacity()); |
| |
| AnimateToMiddle(); |
| EXPECT_LT(0.0f, GetPopup(ids.back())->GetOpacity()); |
| |
| AnimateToEnd(); |
| EXPECT_EQ(1.0f, GetPopup(ids.back())->GetOpacity()); |
| EXPECT_FALSE(IsAnimating()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, PopupResized) { |
| std::vector<std::string> ids; |
| for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i) |
| ids.push_back(AddNotification()); |
| AnimateUntilIdle(); |
| |
| std::vector<gfx::Rect> previous_bounds; |
| for (const auto& id : ids) |
| previous_bounds.push_back(GetPopup(id)->GetBoundsInScreen()); |
| |
| const int changed_height = 256; |
| GetPopup(ids[1])->SetPreferredHeight(changed_height); |
| |
| EXPECT_TRUE(IsAnimating()); |
| |
| AnimateToMiddle(); |
| EXPECT_EQ(previous_bounds[0], GetPopup(ids[0])->GetBoundsInScreen()); |
| EXPECT_EQ(previous_bounds[1].bottom(), |
| GetPopup(ids[1])->GetBoundsInScreen().bottom()); |
| EXPECT_GT(previous_bounds[1].y(), GetPopup(ids[1])->GetBoundsInScreen().y()); |
| EXPECT_GT(previous_bounds[2].bottom(), |
| GetPopup(ids[2])->GetBoundsInScreen().bottom()); |
| EXPECT_GT(previous_bounds[2].y(), GetPopup(ids[2])->GetBoundsInScreen().y()); |
| |
| AnimateToEnd(); |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_EQ(previous_bounds[0], GetPopup(ids[0])->GetBoundsInScreen()); |
| EXPECT_EQ(changed_height, GetPopup(ids[1])->GetBoundsInScreen().height()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, ExpandLatest) { |
| std::string id = AddNotification(); |
| AnimateToEnd(); |
| GetPopup(id)->set_expandable(true); |
| const int top_y = GetPopup(id)->GetBoundsInScreen().y(); |
| |
| AddNotification(); |
| EXPECT_TRUE(IsAnimating()); |
| EXPECT_EQ(1u, GetPopupCounts()); |
| AnimateToMiddle(); |
| EXPECT_LT(top_y, GetPopup(id)->GetBoundsInScreen().y()); |
| AnimateToEnd(); |
| EXPECT_LT(top_y, GetPopup(id)->GetBoundsInScreen().y()); |
| |
| EXPECT_TRUE(IsAnimating()); |
| EXPECT_EQ(2u, GetPopupCounts()); |
| AnimateToEnd(); |
| EXPECT_FALSE(IsAnimating()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, ExpandLatestWithMoveDown) { |
| std::vector<std::string> ids; |
| for (size_t i = 0; i < kMaxVisiblePopupNotifications + 1; ++i) |
| ids.push_back(AddNotification()); |
| |
| AnimateUntilIdle(); |
| EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); |
| |
| GetPopup(ids[1])->set_expandable(true); |
| |
| const int top_y = GetPopup(ids[1])->GetBoundsInScreen().y(); |
| |
| MessageCenter::Get()->MarkSinglePopupAsShown(ids.front(), false); |
| AnimateToEnd(); |
| EXPECT_TRUE(IsAnimating()); |
| EXPECT_EQ(kMaxVisiblePopupNotifications - 1, GetPopupCounts()); |
| |
| AnimateToMiddle(); |
| EXPECT_LT(top_y, GetPopup(ids[2])->GetBoundsInScreen().y()); |
| AnimateToEnd(); |
| EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); |
| EXPECT_TRUE(IsAnimating()); |
| AnimateToEnd(); |
| EXPECT_FALSE(IsAnimating()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, HoverClose) { |
| std::string id0 = AddNotification(); |
| AnimateToEnd(); |
| popup_collection()->set_new_popup_height(256); |
| std::string id1 = AddNotification(); |
| AnimateToEnd(); |
| popup_collection()->set_new_popup_height(84); |
| std::string id2 = AddNotification(); |
| AnimateToEnd(); |
| EXPECT_FALSE(IsAnimating()); |
| |
| EXPECT_TRUE(IsPopupTimerStarted()); |
| GetPopup(id0)->SetHovered(true); |
| EXPECT_FALSE(IsPopupTimerStarted()); |
| |
| const int first_popup_bottom = GetPopup(id0)->GetBoundsInScreen().bottom(); |
| |
| MessageCenter::Get()->RemoveNotification(id0, true); |
| EXPECT_TRUE(IsAnimating()); |
| AnimateToEnd(); |
| EXPECT_TRUE(IsAnimating()); |
| AnimateToMiddle(); |
| GetPopup(id1)->SetHovered(true); |
| AnimateToEnd(); |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_EQ(first_popup_bottom, GetPopup(id1)->GetBoundsInScreen().bottom()); |
| |
| EXPECT_FALSE(IsPopupTimerStarted()); |
| GetPopup(id1)->SetHovered(false); |
| EXPECT_TRUE(IsPopupTimerStarted()); |
| EXPECT_EQ(first_popup_bottom, GetPopup(id1)->GetBoundsInScreen().bottom()); |
| } |
| |
| // Popup timers should be paused if a notification has focus. |
| // Once the focus is lost or the notification is resumed, popup timers |
| // should restart. |
| TEST_F(MessagePopupCollectionTest, FocusedClose) { |
| std::string id0 = AddNotification(); |
| AnimateToEnd(); |
| popup_collection()->set_new_popup_height(256); |
| std::string id1 = AddNotification(); |
| AnimateToEnd(); |
| popup_collection()->set_new_popup_height(84); |
| std::string id2 = AddNotification(); |
| AnimateToEnd(); |
| EXPECT_FALSE(IsAnimating()); |
| |
| EXPECT_TRUE(IsPopupTimerStarted()); |
| GetPopup(id0)->Activate(); |
| // Activating a popup should not pause timers. |
| EXPECT_TRUE(IsPopupTimerStarted()); |
| // If the popup gets keyboard focus the timers should pause. |
| GetPopup(id0)->SimulateFocused(); |
| EXPECT_FALSE(IsPopupTimerStarted()); |
| |
| const int first_popup_top = GetPopup(id0)->GetBoundsInScreen().y(); |
| |
| MessageCenter::Get()->RemoveNotification(id0, true); |
| AnimateToEnd(); |
| AnimateToEnd(); |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_GT(first_popup_top, GetPopup(id1)->GetBoundsInScreen().y()); |
| EXPECT_TRUE(IsPopupTimerStarted()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, SlideOutClose) { |
| std::vector<std::string> ids; |
| for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i) |
| ids.push_back(AddNotification()); |
| |
| AnimateUntilIdle(); |
| |
| GetPopup(ids[1])->SetOpacity(0); |
| MessageCenter::Get()->RemoveNotification(ids[1], true); |
| AnimateToEnd(); |
| |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_TRUE(IsPopupTimerStarted()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, TooTallNotification) { |
| SetDisplayInfo(gfx::Rect(0, 0, 800, 470), // taskbar at the bottom. |
| gfx::Rect(0, 0, 800, 480)); |
| |
| std::string id0 = AddNotification(); |
| std::string id1 = AddNotification(); |
| |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(2u, GetPopupCounts()); |
| |
| popup_collection()->set_new_popup_height(400); |
| std::string id2 = AddNotification(); |
| |
| EXPECT_FALSE(IsAnimating()); |
| EXPECT_EQ(2u, GetPopupCounts()); |
| EXPECT_TRUE(GetPopup(id0)); |
| EXPECT_TRUE(GetPopup(id1)); |
| EXPECT_FALSE(GetPopup(id2)); |
| |
| MessageCenter::Get()->MarkSinglePopupAsShown(id0, false); |
| AnimateUntilIdle(); |
| EXPECT_EQ(1u, GetPopupCounts()); |
| EXPECT_FALSE(GetPopup(id2)); |
| |
| MessageCenter::Get()->MarkSinglePopupAsShown(id1, false); |
| AnimateUntilIdle(); |
| EXPECT_EQ(1u, GetPopupCounts()); |
| EXPECT_TRUE(GetPopup(id2)); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, DisplaySizeChanged) { |
| std::string id0 = AddNotification(); |
| AnimateToEnd(); |
| std::string id1 = AddNotification(); |
| AnimateToEnd(); |
| popup_collection()->set_new_popup_height(400); |
| std::string id2 = AddNotification(); |
| AnimateToEnd(); |
| EXPECT_FALSE(IsAnimating()); |
| |
| EXPECT_TRUE(GetPopup(id0)); |
| EXPECT_TRUE(GetPopup(id1)); |
| EXPECT_TRUE(GetPopup(id2)); |
| |
| SetDisplayInfo(gfx::Rect(0, 0, 800, 470), // taskbar at the bottom. |
| gfx::Rect(0, 0, 800, 480)); |
| popup_collection()->ResetBounds(); |
| |
| EXPECT_TRUE(GetPopup(id0)); |
| EXPECT_TRUE(work_area().Contains(GetPopup(id0)->GetBoundsInScreen())); |
| EXPECT_TRUE(GetPopup(id1)); |
| EXPECT_TRUE(work_area().Contains(GetPopup(id1)->GetBoundsInScreen())); |
| EXPECT_FALSE(GetPopup(id2)); |
| |
| MessageCenter::Get()->MarkSinglePopupAsShown(id0, false); |
| MessageCenter::Get()->MarkSinglePopupAsShown(id1, false); |
| AnimateUntilIdle(); |
| EXPECT_EQ(1u, GetPopupCounts()); |
| EXPECT_TRUE(GetPopup(id2)); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, PopupResizedAndOverflown) { |
| SetDisplayInfo(gfx::Rect(0, 0, 800, 470), // taskbar at the bottom. |
| gfx::Rect(0, 0, 800, 480)); |
| |
| std::string id0 = AddNotification(); |
| std::string id1 = AddNotification(); |
| std::string id2 = AddNotification(); |
| AnimateUntilIdle(); |
| |
| EXPECT_TRUE(GetPopup(id0)); |
| EXPECT_TRUE(GetPopup(id1)); |
| EXPECT_TRUE(GetPopup(id2)); |
| |
| const int changed_height = 300; |
| GetPopup(id1)->SetPreferredHeight(changed_height); |
| |
| AnimateUntilIdle(); |
| RunPendingMessages(); |
| |
| EXPECT_TRUE(GetPopup(id0)); |
| EXPECT_TRUE(work_area().Contains(GetPopup(id0)->GetBoundsInScreen())); |
| EXPECT_TRUE(GetPopup(id1)); |
| EXPECT_TRUE(work_area().Contains(GetPopup(id1)->GetBoundsInScreen())); |
| EXPECT_FALSE(GetPopup(id2)); |
| |
| MessageCenter::Get()->MarkSinglePopupAsShown(id0, false); |
| AnimateUntilIdle(); |
| EXPECT_EQ(2u, GetPopupCounts()); |
| EXPECT_TRUE(GetPopup(id2)); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, DismissOnClick) { |
| MessageCenter::Get()->SetHasMessageCenterView(true); |
| |
| std::string id1 = AddNotification(); |
| std::string id2 = AddNotification(); |
| |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(2u, GetPopupCounts()); |
| EXPECT_TRUE(GetPopup(id1)); |
| EXPECT_TRUE(GetPopup(id2)); |
| |
| MessageCenter::Get()->ClickOnNotification(id2); |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(1u, GetPopupCounts()); |
| EXPECT_TRUE(GetPopup(id1)); |
| EXPECT_FALSE(GetPopup(id2)); |
| |
| MessageCenter::Get()->ClickOnNotificationButton(id1, 0); |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(0u, GetPopupCounts()); |
| EXPECT_FALSE(GetPopup(id1)); |
| EXPECT_FALSE(GetPopup(id2)); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, NotDismissedOnClick) { |
| MessageCenter::Get()->SetHasMessageCenterView(false); |
| |
| std::string id1 = AddNotification(); |
| std::string id2 = AddNotification(); |
| |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(2u, GetPopupCounts()); |
| EXPECT_TRUE(GetPopup(id1)); |
| EXPECT_TRUE(GetPopup(id2)); |
| |
| MessageCenter::Get()->ClickOnNotification(id2); |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(2u, GetPopupCounts()); |
| EXPECT_TRUE(GetPopup(id1)); |
| EXPECT_TRUE(GetPopup(id2)); |
| |
| MessageCenter::Get()->ClickOnNotificationButton(id1, 0); |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(2u, GetPopupCounts()); |
| EXPECT_TRUE(GetPopup(id1)); |
| EXPECT_TRUE(GetPopup(id2)); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, PopupCollectionBounds) { |
| EXPECT_EQ(gfx::Rect(), popup_collection()->popup_collection_bounds()); |
| |
| std::string id0 = AddNotification(); |
| AnimateUntilIdle(); |
| |
| gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); |
| |
| // The popup collection bounds should be the bounds of the only popup. |
| EXPECT_EQ(r0, popup_collection()->popup_collection_bounds()); |
| |
| std::string id1 = AddNotification(); |
| std::string id2 = AddNotification(); |
| |
| AnimateUntilIdle(); |
| |
| r0 = GetPopup(id0)->GetBoundsInScreen(); |
| gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); |
| gfx::Rect r2 = GetPopup(id2)->GetBoundsInScreen(); |
| |
| // The height of the entire popup collection bounds should be the total |
| // heights of all popups, plus all the margins between them. |
| int expected_height = r0.height() + kMarginBetweenPopups + r1.height() + |
| kMarginBetweenPopups + r2.height(); |
| |
| EXPECT_EQ(gfx::Rect(r2.x(), r2.y(), GetNotificationWidth(), expected_height), |
| popup_collection()->popup_collection_bounds()); |
| |
| MessageCenter::Get()->RemoveNotification(id0, true); |
| AnimateUntilIdle(); |
| |
| r1 = GetPopup(id1)->GetBoundsInScreen(); |
| r2 = GetPopup(id2)->GetBoundsInScreen(); |
| |
| EXPECT_EQ(gfx::Rect(r2.x(), r2.y(), GetNotificationWidth(), |
| r1.height() + kMarginBetweenPopups + r2.height()), |
| popup_collection()->popup_collection_bounds()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, PopupCollectionHeightChanged) { |
| EXPECT_EQ(0, popup_collection()->popup_collection_height_changed()); |
| |
| std::string id0 = AddNotification(); |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(1, popup_collection()->popup_collection_height_changed()); |
| |
| std::string id1 = AddNotification(); |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(2, popup_collection()->popup_collection_height_changed()); |
| |
| std::string id2 = AddNotification(); |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(3, popup_collection()->popup_collection_height_changed()); |
| |
| MessageCenter::Get()->RemoveNotification(id0, true); |
| AnimateUntilIdle(); |
| |
| EXPECT_EQ(4, popup_collection()->popup_collection_height_changed()); |
| } |
| |
| // Tests that `MessagePopupCollection` notifies when there is an incoming silent |
| // notification. |
| TEST_F(MessagePopupCollectionTest, NotifySilentNotification) { |
| ASSERT_EQ(0, popup_collection()->notify_silent_notification_count()); |
| |
| // Add a silent notification. |
| AddNotification(CreateLowPriorityNotification()); |
| |
| // Assert that clients are notified of the incoming silent notification. |
| EXPECT_EQ(1, popup_collection()->notify_silent_notification_count()); |
| |
| // Add a non-silent notification. |
| AddNotification(); |
| |
| // Assert that clients are not notified for the incoming non-silent |
| // notification. |
| EXPECT_EQ(1, popup_collection()->notify_silent_notification_count()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, DefaultPositioning) { |
| std::string id0 = AddNotification(); |
| std::string id1 = AddNotification(); |
| std::string id2 = AddNotification(); |
| std::string id3 = AddNotification(); |
| |
| AnimateUntilIdle(); |
| |
| gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); |
| gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); |
| gfx::Rect r2 = GetPopup(id2)->GetBoundsInScreen(); |
| |
| // The 4th toast is not shown yet. |
| EXPECT_FALSE(GetPopup(id3)); |
| |
| // 3 toasts are shown, equal size, vertical stack. |
| EXPECT_EQ(r0.width(), r1.width()); |
| EXPECT_EQ(r1.width(), r2.width()); |
| |
| EXPECT_EQ(r0.height(), r1.height()); |
| EXPECT_EQ(r1.height(), r2.height()); |
| |
| EXPECT_GT(r0.y(), r1.y()); |
| EXPECT_GT(r1.y(), r2.y()); |
| |
| EXPECT_EQ(r0.x(), r1.x()); |
| EXPECT_EQ(r1.x(), r2.x()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, DefaultPositioningWithRightTaskbar) { |
| // If taskbar is on the right we show the toasts bottom to top as usual. |
| |
| // Simulate a taskbar at the right. |
| SetDisplayInfo(gfx::Rect(0, 0, 590, 400), // Work-area. |
| gfx::Rect(0, 0, 600, 400)); // Display-bounds. |
| std::string id0 = AddNotification(); |
| std::string id1 = AddNotification(); |
| |
| AnimateUntilIdle(); |
| |
| gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); |
| gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); |
| |
| // 2 toasts are shown, equal size, vertical stack. |
| EXPECT_EQ(r0.width(), r1.width()); |
| EXPECT_EQ(r0.height(), r1.height()); |
| EXPECT_GT(r0.y(), r1.y()); |
| EXPECT_EQ(r0.x(), r1.x()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, TopDownPositioningWithTopTaskbar) { |
| // Simulate a taskbar at the top. |
| SetDisplayInfo(gfx::Rect(0, 10, 600, 390), // Work-area. |
| gfx::Rect(0, 0, 600, 400)); // Display-bounds. |
| std::string id0 = AddNotification(); |
| std::string id1 = AddNotification(); |
| |
| AnimateUntilIdle(); |
| |
| gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); |
| gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); |
| |
| // 2 toasts are shown, equal size, vertical stack. |
| EXPECT_EQ(r0.width(), r1.width()); |
| EXPECT_EQ(r0.height(), r1.height()); |
| EXPECT_LT(r0.y(), r1.y()); |
| EXPECT_EQ(r0.x(), r1.x()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, TopDownPositioningWithLeftAndTopTaskbar) { |
| // If there "seems" to be a taskbar on left and top (like in Unity), it is |
| // assumed that the actual taskbar is the top one. |
| |
| // Simulate a taskbar at the top and left. |
| SetDisplayInfo(gfx::Rect(10, 10, 590, 390), // Work-area. |
| gfx::Rect(0, 0, 600, 400)); // Display-bounds. |
| std::string id0 = AddNotification(); |
| std::string id1 = AddNotification(); |
| |
| AnimateUntilIdle(); |
| |
| gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); |
| gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); |
| |
| // 2 toasts are shown, equal size, vertical stack. |
| EXPECT_EQ(r0.width(), r1.width()); |
| EXPECT_EQ(r0.height(), r1.height()); |
| EXPECT_LT(r0.y(), r1.y()); |
| EXPECT_EQ(r0.x(), r1.x()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, TopDownPositioningWithBottomAndTopTaskbar) { |
| // If there "seems" to be a taskbar on bottom and top (like in Gnome), it is |
| // assumed that the actual taskbar is the top one. |
| |
| // Simulate a taskbar at the top and bottom. |
| SetDisplayInfo(gfx::Rect(0, 10, 580, 400), // Work-area. |
| gfx::Rect(0, 0, 600, 400)); // Display-bounds. |
| std::string id0 = AddNotification(); |
| std::string id1 = AddNotification(); |
| |
| AnimateUntilIdle(); |
| |
| gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); |
| gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); |
| |
| // 2 toasts are shown, equal size, vertical stack. |
| EXPECT_EQ(r0.width(), r1.width()); |
| EXPECT_EQ(r0.height(), r1.height()); |
| EXPECT_LT(r0.y(), r1.y()); |
| EXPECT_EQ(r0.x(), r1.x()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, LeftPositioningWithLeftTaskbar) { |
| // Simulate a taskbar at the left. |
| SetDisplayInfo(gfx::Rect(10, 0, 590, 400), // Work-area. |
| gfx::Rect(0, 0, 600, 400)); // Display-bounds. |
| std::string id0 = AddNotification(); |
| std::string id1 = AddNotification(); |
| |
| AnimateUntilIdle(); |
| |
| gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); |
| gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); |
| |
| EXPECT_EQ(r0.width(), r1.width()); |
| EXPECT_EQ(r0.height(), r1.height()); |
| EXPECT_GT(r0.y(), r1.y()); |
| EXPECT_EQ(r0.x(), r1.x()); |
| |
| // Ensure that toasts are on the left. |
| EXPECT_LT(r1.x(), work_area().CenterPoint().x()); |
| EXPECT_TRUE(work_area().Contains(r0)); |
| EXPECT_TRUE(work_area().Contains(r1)); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, PopupWidgetClosedOutsideDuringFadeOut) { |
| std::string id = AddNotification(); |
| AnimateUntilIdle(); |
| |
| MessageCenter::Get()->MarkSinglePopupAsShown(id, false); |
| AnimateToMiddle(); |
| |
| // On Windows it might be possible that the widget is closed outside |
| // MessagePopupCollection? https://crbug.com/871199 |
| GetPopup(id)->GetWidget()->CloseNow(); |
| AnimateToEnd(); |
| |
| EXPECT_FALSE(IsAnimating()); |
| } |
| |
| TEST_F(MessagePopupCollectionTest, NotifyPopupClosedThenCloseAllPopups) { |
| std::string id1 = AddNotification(); |
| std::string id2 = AddNotification(); |
| AnimateUntilIdle(); |
| |
| // This test make sure that when `NotifyPopupClosed()` is called and then |
| // `CloseAllPopupsNow()` is triggered, no crash would happen. This scenerio |
| // can happen when `MessagePopupView::~MessagePopupView()` is called, and then |
| // at the same time another entity (i.e. |
| // AshMessagePopupCollection::NotifierCollisionHandler) calls |
| // `CloseAllPopupsNow()` (b/312515706). |
| popup_collection()->NotifyPopupClosed(GetPopup(id1)); |
| CloseAllPopupsNow(); |
| } |
| |
| // Notification removing may occur while the animation triggered by the previous |
| // operation is running. As result, notification is removed from the message |
| // center but its popup is still kept. At this moment, a new notification with |
| // the same notification id may be added to the message center. This can happen |
| // on Chrome OS when an external display is connected with the Chromebook device |
| // (see https://crbug.com/921402). This test case emulates the procedure of |
| // the external display connection that is mentioned in the link above. Verifies |
| // that under this circumstance the notification popup is updated. |
| TEST_F(MessagePopupCollectionTest, RemoveNotificationWhileAnimating) { |
| const std::string notification_id("test_id"); |
| const std::string old_notification_title("old_title"); |
| const std::string new_notification_title("new_title"); |
| |
| // Create a notification and add it to message center. |
| auto old_notification = |
| CreateNotification(notification_id, old_notification_title); |
| MessageCenter::Get()->AddNotification(std::move(old_notification)); |
| AnimateToMiddle(); |
| |
| // On real device, MessageCenter::RemoveNotification is called before the |
| // animation ends. As result, notification is removed while popup keeps still. |
| EXPECT_TRUE(IsAnimating()); |
| MessageCenter::Get()->RemoveNotification(notification_id, false); |
| EXPECT_FALSE(MessageCenter::Get()->HasPopupNotifications()); |
| EXPECT_EQ(1u, GetPopupCounts()); |
| EXPECT_EQ(old_notification_title, GetPopup(notification_id)->title()); |
| |
| // On real device, the new notification with the same notification id is |
| // created and added to message center before the animation ends. |
| auto new_notification = |
| CreateNotification(notification_id, new_notification_title); |
| EXPECT_TRUE(IsAnimating()); |
| MessageCenter::Get()->AddNotification(std::move(new_notification)); |
| AnimateUntilIdle(); |
| |
| // Verifies that the new notification popup is shown. |
| EXPECT_EQ(1u, GetPopupCounts()); |
| EXPECT_EQ(new_notification_title, GetPopup(notification_id)->title()); |
| } |
| |
| } // namespace message_center |