| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/system/status_area_animation_controller.h" |
| |
| #include <algorithm> |
| |
| #include "ash/ime/ime_controller_impl.h" |
| #include "ash/shell.h" |
| #include "ash/system/notification_center/notification_center_test_api.h" |
| #include "ash/system/notification_center/notification_center_tray.h" |
| #include "ash/system/status_area_widget.h" |
| #include "ash/system/status_area_widget_test_helper.h" |
| #include "ash/system/unified/notification_counter_view.h" |
| #include "ash/system/unified/notification_icons_controller.h" |
| #include "ash/test/ash_test_base.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/run_loop.h" |
| #include "base/test/task_environment.h" |
| #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
| #include "ui/compositor/test/layer_animation_stopped_waiter.h" |
| #include "ui/display/manager/display_manager.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/message_center/message_center.h" |
| |
| namespace ash { |
| |
| class TrayItemViewAnimationWaiter { |
| public: |
| explicit TrayItemViewAnimationWaiter(TrayItemView* tray_item) |
| : tray_item_(tray_item) {} |
| TrayItemViewAnimationWaiter(const TrayItemViewAnimationWaiter&) = delete; |
| TrayItemViewAnimationWaiter& operator=(const TrayItemViewAnimationWaiter&) = |
| delete; |
| ~TrayItemViewAnimationWaiter() = default; |
| |
| // Waits for `tray_item_`'s visibility animation to finish, or no-op if it is |
| // not currently animating. |
| void Wait() { |
| if (tray_item_->IsAnimating()) { |
| tray_item_->SetAnimationIdleClosureForTest(base::BindOnce( |
| &TrayItemViewAnimationWaiter::OnTrayItemAnimationFinished, |
| weak_ptr_factory_.GetWeakPtr())); |
| run_loop_.Run(); |
| } |
| } |
| |
| private: |
| // Called when `tray_item_`'s visibility animation finishes. |
| void OnTrayItemAnimationFinished() { run_loop_.Quit(); } |
| |
| // The tray item whose animation is being waited for. |
| raw_ptr<TrayItemView> tray_item_ = nullptr; |
| |
| base::RunLoop run_loop_; |
| |
| base::WeakPtrFactory<TrayItemViewAnimationWaiter> weak_ptr_factory_{this}; |
| }; |
| |
| class StatusAreaAnimationControllerTest : public AshTestBase { |
| public: |
| StatusAreaAnimationControllerTest() |
| : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) { |
| } |
| StatusAreaAnimationControllerTest(const StatusAreaAnimationControllerTest&) = |
| delete; |
| StatusAreaAnimationControllerTest& operator=( |
| const StatusAreaAnimationControllerTest&) = delete; |
| ~StatusAreaAnimationControllerTest() override = default; |
| |
| // AshTestBase: |
| void SetUp() override { |
| AshTestBase::SetUp(); |
| test_api = std::make_unique<NotificationCenterTestApi>(); |
| // Tray visibility animations may still be disabled due to changes in |
| // session state not fully propagating. Running all pending tasks guarantees |
| // that the necessary scoped closure runners are executed, thus ensuring |
| // that visibility animations are enabled before proceeding with the rest of |
| // the test. |
| base::RunLoop().RunUntilIdle(); |
| ASSERT_TRUE(test_api->GetTray()->IsShowAnimationEnabled()); |
| } |
| |
| bool IsNotificationCounterAnimationRunning() { |
| return notification_counter()->IsAnimating(); |
| } |
| |
| bool IsCapsLockTrayItemAnimationRunning() { |
| return caps_lock_tray_item()->IsAnimating(); |
| } |
| |
| NotificationCounterView* notification_counter() { |
| return test_api->GetTray() |
| ->notification_icons_controller() |
| ->notification_counter_view(); |
| } |
| |
| NotificationIconTrayItemView* caps_lock_tray_item() { |
| // The last tray item will be used to show the caps lock notification icon. |
| return test_api->GetTray() |
| ->notification_icons_controller() |
| ->tray_items() |
| .back(); |
| } |
| |
| std::unique_ptr<NotificationCenterTestApi> test_api; |
| }; |
| |
| // Tests that the notification center tray's `TrayItemView`s' animations are |
| // disabled while the notification center tray is running its initial show |
| // animation. |
| TEST_F(StatusAreaAnimationControllerTest, |
| TrayItemAnimationDisabledDuringShowAnimation) { |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->IsTrayShown()); |
| ASSERT_FALSE(notification_counter()->GetVisible()); |
| |
| // Add a notification to make the notification center tray visible. |
| test_api->AddNotification(); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| ASSERT_TRUE(test_api->IsTrayShown()); |
| |
| // Verify that the notification counter does not start animating. |
| EXPECT_FALSE(IsNotificationCounterAnimationRunning()); |
| |
| // Wait for the tray's show animation to finish. |
| ui::LayerAnimationStoppedWaiter notification_center_tray_waiter; |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Verify that the notification counter is visible. |
| EXPECT_TRUE(notification_counter()->GetVisible()); |
| EXPECT_EQ(notification_counter()->layer()->opacity(), 1); |
| } |
| |
| // Tests that the notification center tray's `TrayItemView`s' animations are |
| // disabled while the notification center tray is running its initial show |
| // animation on a secondary display. |
| TEST_F(StatusAreaAnimationControllerTest, |
| TrayItemAnimationDisabledDuringShowAnimationOnSecondaryDisplay) { |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| |
| // Create two displays. |
| UpdateDisplay("800x799,800x799"); |
| auto secondary_display_id = display_manager()->GetDisplayAt(1).id(); |
| |
| // Add a notification to make the notification center tray visible on both |
| // displays. |
| test_api->AddNotification(); |
| ASSERT_TRUE(test_api->IsTrayShown()); |
| ASSERT_TRUE(test_api->IsTrayShownOnDisplay(secondary_display_id)); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| ASSERT_TRUE(test_api->IsTrayAnimatingOnDisplay(secondary_display_id)); |
| |
| // Verify that the notification counter on the secondary display does not |
| // start animating. |
| EXPECT_FALSE( |
| test_api->IsNotificationCounterAnimatingOnDisplay(secondary_display_id)); |
| |
| // Wait for the secondary display's tray show animation to finish. |
| ui::LayerAnimationStoppedWaiter notification_center_tray_waiter; |
| notification_center_tray_waiter.Wait( |
| test_api->GetTrayOnDisplay(secondary_display_id)->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimatingOnDisplay(secondary_display_id)); |
| |
| // Verify that the secondary display's notification counter is visible. |
| EXPECT_TRUE( |
| test_api->IsNotificationCounterShownOnDisplay(secondary_display_id)); |
| EXPECT_EQ(test_api->GetNotificationCounterOnDisplay(secondary_display_id) |
| ->layer() |
| ->opacity(), |
| 1); |
| } |
| |
| // Tests that the notification center tray's `TrayItemView`s' animations are |
| // disabled while the notification center tray is running its initial hide |
| // animation. |
| TEST_F(StatusAreaAnimationControllerTest, |
| TrayItemAnimationDisabledDuringHideAnimation) { |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->IsTrayShown()); |
| ASSERT_FALSE(notification_counter()->GetVisible()); |
| |
| // Add a notification to make the notification center tray visible. |
| auto id = test_api->AddNotification(); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| ASSERT_TRUE(test_api->IsTrayShown()); |
| |
| // Wait for the notification center tray's show animation to finish. |
| ui::LayerAnimationStoppedWaiter notification_center_tray_waiter; |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Verify that the notification center tray is visible. |
| ASSERT_TRUE(test_api->IsTrayShown()); |
| |
| // Remove the notification to cause the notification center tray to start its |
| // hide animation. |
| test_api->RemoveNotification(id); |
| |
| // Verify that the notification center tray is running its hide animation. |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->GetTray()->layer()->GetTargetVisibility()); |
| ASSERT_EQ(test_api->GetTray()->layer()->GetTargetOpacity(), 0); |
| |
| // Verify that the notification counter does not start animating. |
| EXPECT_FALSE(IsNotificationCounterAnimationRunning()); |
| |
| // Wait for the tray's hide animation to finish. |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Verify that the notification counter is not visible. |
| EXPECT_FALSE(notification_counter()->GetVisible()); |
| EXPECT_EQ(notification_counter()->layer()->opacity(), 0); |
| } |
| |
| // Tests that `NotificationIconTrayItemView`s are not reset until the end of the |
| // `NotificationCenterTray`'s hide animation. This was added for b/284991444. |
| TEST_F(StatusAreaAnimationControllerTest, |
| NotificationIconNotResetWhileNotificationTrayHideAnimationRunning) { |
| // Note that animations still finish immediately at this stage of the test. |
| |
| // Add a critical warning system notification. |
| auto id = test_api->AddCriticalWarningSystemNotification(); |
| auto* notification_icon = test_api->GetNotificationIconForId(id); |
| CHECK(notification_icon); |
| auto icon_image = notification_icon->image_view()->GetImage(); |
| |
| // Verify that the notification icon is showing in the notification tray, and |
| // that the tray is finished animating. |
| ASSERT_TRUE(test_api->IsNotificationIconShown()); |
| ASSERT_TRUE(test_api->IsTrayShown()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Set the animation duration scale to some small non-zero value for the rest |
| // of the test. |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| |
| // Remove the notification to start the notification tray's hide animation. |
| test_api->RemoveNotification(id); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->GetTray()->layer()->GetTargetVisibility()); |
| ASSERT_EQ(test_api->GetTray()->layer()->GetTargetOpacity(), 0); |
| |
| // Verify that the notification icon has not been reset yet. |
| EXPECT_TRUE(icon_image.BackedBySameObjectAs( |
| notification_icon->image_view()->GetImage())); |
| |
| // Wait for the notification tray to finish its hide animation. |
| ui::LayerAnimationStoppedWaiter notification_center_tray_waiter; |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Verify that the notification icon has been reset. |
| EXPECT_TRUE(notification_icon->image_view()->GetImage().BackedBySameObjectAs( |
| gfx::ImageSkia())); |
| } |
| |
| // Tests that `NotificationIconTrayItemView`s are not reset until the end of |
| // their hide animation. This was added for b/284991444. |
| TEST_F(StatusAreaAnimationControllerTest, |
| NotificationIconNotResetWhileHideAnimationRunning) { |
| // Note that animations still finish immediately at this stage of the test. |
| |
| // Add a standard notification as well as a critical warning system |
| // notification. |
| test_api->AddNotification(); |
| auto id = test_api->AddCriticalWarningSystemNotification(); |
| auto* notification_icon = test_api->GetNotificationIconForId(id); |
| CHECK(notification_icon); |
| auto icon_image = notification_icon->image_view()->GetImage(); |
| |
| // Verify that both the notification counter and a notification icon are |
| // showing in the notification tray, and that the tray is finished animating. |
| ASSERT_TRUE(test_api->IsNotificationCounterShown()); |
| ASSERT_TRUE(test_api->IsNotificationIconShown()); |
| ASSERT_TRUE(test_api->IsTrayShown()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Set the animation duration scale to some small non-zero value for the |
| // rest of the test. |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| |
| // Remove the critical warning system notification to start the notification |
| // icon's hide animation (note that the notification tray should remain |
| // visible due to the presence of the standard notification). |
| test_api->RemoveNotification(id); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->IsNotificationCounterAnimating()); |
| ASSERT_TRUE(notification_icon->IsAnimating()); |
| ASSERT_FALSE(notification_icon->target_visible_for_testing()); |
| |
| // Verify that the notification icon has not been reset yet. |
| EXPECT_TRUE(icon_image.BackedBySameObjectAs( |
| notification_icon->image_view()->GetImage())); |
| |
| // End the notification icon's hide animation. |
| auto* icon_animation = notification_icon->animation_for_testing(); |
| icon_animation->End(); |
| ASSERT_FALSE(notification_icon->IsAnimating()); |
| |
| // Verify that the notification icon has been reset. |
| EXPECT_TRUE(notification_icon->image_view()->GetImage().BackedBySameObjectAs( |
| gfx::ImageSkia())); |
| } |
| |
| // Tests that the notification center tray's `TrayItemView`s' animations are |
| // disabled while the notification center tray is running its show animation, |
| // even when it's not the initial show animation. |
| TEST_F(StatusAreaAnimationControllerTest, |
| TrayItemAnimationDisabledDuringNonInitialShowAnimation) { |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->IsTrayShown()); |
| ASSERT_FALSE(notification_counter()->GetVisible()); |
| |
| // Add a notification to make the notification center tray visible. |
| auto id = test_api->AddNotification(); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| |
| // Wait for the tray's show animation to finish. |
| ui::LayerAnimationStoppedWaiter notification_center_tray_waiter; |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Remove the notification, causing the tray to hide. |
| test_api->RemoveNotification(id); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| |
| // Wait for the hide animation to finish. |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->IsTrayShown()); |
| ASSERT_FALSE(notification_counter()->GetVisible()); |
| |
| // Add another notification to make the tray visible a second time. |
| test_api->AddNotification(); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| ASSERT_TRUE(test_api->IsTrayShown()); |
| |
| // Verify that the notification counter does not start animating. |
| EXPECT_FALSE(IsNotificationCounterAnimationRunning()); |
| |
| // Wait for the tray's show animation to finish. |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Verify that the notification counter is visible. |
| EXPECT_TRUE(notification_counter()->GetVisible()); |
| EXPECT_EQ(notification_counter()->layer()->opacity(), 1); |
| } |
| |
| // Tests that the notification center tray's `TrayItemView`s' animations are |
| // disabled while the notification center tray is running its hide animation, |
| // even when it's not the initial hide animation. |
| TEST_F(StatusAreaAnimationControllerTest, |
| TrayItemAnimationDisabledDuringNonInitialHideAnimation) { |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->IsTrayShown()); |
| ASSERT_FALSE(notification_counter()->GetVisible()); |
| |
| // Add a notification to make the notification center tray visible. |
| auto id = test_api->AddNotification(); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| |
| // Wait for the tray's show animation to finish. |
| ui::LayerAnimationStoppedWaiter notification_center_tray_waiter; |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_TRUE(test_api->IsTrayShown()); |
| ASSERT_TRUE(notification_counter()->GetVisible()); |
| |
| // Remove the notification, causing the tray to hide. |
| test_api->RemoveNotification(id); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| |
| // Wait for the hide animation to finish. |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->IsTrayShown()); |
| ASSERT_FALSE(notification_counter()->GetVisible()); |
| |
| // Add another notification to make the tray visible a second time. |
| id = test_api->AddNotification(); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| |
| // Wait for the notification center tray's second show animation to finish. |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_TRUE(test_api->IsTrayShown()); |
| ASSERT_TRUE(notification_counter()->GetVisible()); |
| |
| // Remove the notification, causing the notification center tray to start its |
| // second hide animation. |
| test_api->RemoveNotification(id); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| |
| // Verify that the notification counter does not start animating. |
| EXPECT_FALSE(IsNotificationCounterAnimationRunning()); |
| |
| // Wait for the notification center tray's hide animation to finish. |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->IsTrayShown()); |
| |
| // Verify that the notification counter is hidden. |
| EXPECT_FALSE(notification_counter()->GetVisible()); |
| EXPECT_EQ(notification_counter()->layer()->opacity(), 0); |
| } |
| |
| // Tests that already-visible `TrayItemView`s do not animate when a new |
| // `TrayItemView` becomes visible. |
| TEST_F(StatusAreaAnimationControllerTest, |
| VisibleTrayItemDoesNotAnimateDuringNewTrayItemAnimation) { |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->IsTrayShown()); |
| |
| // Show the tray by adding a notification. |
| test_api->AddNotification(); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| |
| // Wait for the tray's show animation to finish. |
| ui::LayerAnimationStoppedWaiter notification_center_tray_waiter; |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_TRUE(notification_counter()->GetVisible()); |
| ASSERT_FALSE(IsNotificationCounterAnimationRunning()); |
| |
| // Add a second icon to the tray (caps lock). |
| Shell::Get()->ime_controller()->UpdateCapsLockState(true); |
| |
| // Verify that the new tray item (caps lock) animates in while the existing |
| // tray item (counter) does not animate. |
| EXPECT_TRUE(IsCapsLockTrayItemAnimationRunning()); |
| EXPECT_FALSE(IsNotificationCounterAnimationRunning()); |
| |
| // Wait for the caps lock tray item show animation to finish. |
| TrayItemViewAnimationWaiter(caps_lock_tray_item()).Wait(); |
| EXPECT_FALSE(IsCapsLockTrayItemAnimationRunning()); |
| |
| // Verify that both tray items are visible. |
| EXPECT_TRUE(caps_lock_tray_item()->GetVisible()); |
| EXPECT_EQ(caps_lock_tray_item()->layer()->opacity(), 1); |
| EXPECT_TRUE(notification_counter()->GetVisible()); |
| EXPECT_EQ(notification_counter()->layer()->opacity(), 1); |
| } |
| |
| // Tests that visible `TrayItemView`s can animate out without causing the entire |
| // notification center tray to animate when there are at least two items in the |
| // tray. |
| TEST_F(StatusAreaAnimationControllerTest, |
| VisibleTrayItemAnimatesOutWithoutCausingWholeTrayAnimation) { |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_FALSE(test_api->IsTrayShown()); |
| |
| // Show the tray by adding a notification. |
| auto id = test_api->AddNotification(); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| |
| // Wait for the tray's show animation to finish. |
| ui::LayerAnimationStoppedWaiter notification_center_tray_waiter; |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| ASSERT_TRUE(notification_counter()->GetVisible()); |
| |
| // Add a second icon (caps lock) to the tray (this also adds a second |
| // notification). |
| Shell::Get()->ime_controller()->UpdateCapsLockState(true); |
| |
| // Wait for the caps lock tray item show animation to finish. |
| TrayItemViewAnimationWaiter(caps_lock_tray_item()).Wait(); |
| ASSERT_FALSE(IsCapsLockTrayItemAnimationRunning()); |
| ASSERT_TRUE(caps_lock_tray_item()->GetVisible()); |
| |
| // Remove the initial notification, causing the notification counter to hide. |
| test_api->RemoveNotification(id); |
| ASSERT_EQ(test_api->GetNotificationCount(), 1u); |
| |
| // Verify that the notification counter animates out while the tray remains |
| // visible. |
| EXPECT_TRUE(IsNotificationCounterAnimationRunning()); |
| EXPECT_TRUE(test_api->GetTray()->GetVisible()); |
| EXPECT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Wait for the notification counter hide animation to finish. |
| TrayItemViewAnimationWaiter(notification_counter()).Wait(); |
| EXPECT_FALSE(IsNotificationCounterAnimationRunning()); |
| |
| // Verify that the notification counter is no longer visible, but that the |
| // tray is. |
| EXPECT_FALSE(notification_counter()->GetVisible()); |
| EXPECT_TRUE(test_api->GetTray()->GetVisible()); |
| } |
| |
| // Tests that scheduling the show animation while the hide animation is running |
| // results in the `TrayBackgroundView` being visible once all animations are |
| // finished. |
| TEST_F(StatusAreaAnimationControllerTest, ShowWhileHideAnimationIsRunning) { |
| // Show the tray by adding a notification. Note that animations still finish |
| // immediately at this stage of the test. |
| auto id = test_api->AddNotification(); |
| ASSERT_TRUE(test_api->IsTrayShown()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Set the animation duration scale to some small non-zero value for the rest |
| // of the test. |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| |
| // Remove the notification, causing the notification tray to hide. |
| test_api->RemoveNotification(id); |
| |
| // Verify that the tray's hide animation is running. |
| EXPECT_TRUE(test_api->IsTrayAnimating()); |
| EXPECT_FALSE(test_api->GetTray()->layer()->GetTargetVisibility()); |
| EXPECT_EQ(test_api->GetTray()->layer()->GetTargetOpacity(), 0); |
| |
| // Add another notification to show the tray again. |
| test_api->AddNotification(); |
| |
| // Verify that the tray is still animating, but this time it is the show |
| // animation that is running. |
| EXPECT_TRUE(test_api->IsTrayAnimating()); |
| EXPECT_TRUE(test_api->GetTray()->layer()->GetTargetVisibility()); |
| EXPECT_EQ(test_api->GetTray()->layer()->GetTargetOpacity(), 1); |
| |
| // Wait for the show animation to finish. |
| ui::LayerAnimationStoppedWaiter notification_center_tray_waiter; |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Verify that the tray is visible. |
| EXPECT_TRUE(test_api->GetTray()->GetVisible()); |
| EXPECT_EQ(test_api->GetTray()->layer()->opacity(), 1); |
| } |
| |
| // Tests that scheduling the hide animation while the show animation is running |
| // results in the `TrayBackgroundView` being hidden once all animations are |
| // finished. |
| TEST_F(StatusAreaAnimationControllerTest, HideWhileShowAnimationIsRunning) { |
| ASSERT_FALSE(test_api->IsTrayShown()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Set the animation duration scale to some small non-zero value for the rest |
| // of the test. |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| |
| // Cause the notification tray to start to show by adding a notification. |
| auto id = test_api->AddNotification(); |
| |
| // Verify that the notification tray's show animation is running. |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| ASSERT_TRUE(test_api->GetTray()->layer()->GetTargetVisibility()); |
| ASSERT_EQ(test_api->GetTray()->layer()->GetTargetOpacity(), 1); |
| |
| // Remove the notification, causing the in-progress show animation to be |
| // interrupted by the hide animation. |
| test_api->RemoveNotification(id); |
| |
| // Verify that the tray is still animating, but this time it is the hide |
| // animation that is running. |
| EXPECT_TRUE(test_api->IsTrayAnimating()); |
| EXPECT_FALSE(test_api->GetTray()->layer()->GetTargetVisibility()); |
| EXPECT_EQ(test_api->GetTray()->layer()->GetTargetOpacity(), 0); |
| |
| // Wait for the hide animation to finish. |
| ui::LayerAnimationStoppedWaiter notification_center_tray_waiter; |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Verify that the tray is hidden. |
| EXPECT_FALSE(test_api->IsTrayShown()); |
| EXPECT_EQ(test_api->GetTray()->layer()->opacity(), 0); |
| } |
| |
| // Tests that the notification center tray's tray items have their animations |
| // reset when the tray's hide animation ends. |
| TEST_F(StatusAreaAnimationControllerTest, |
| HideAnimationEndedResetsTrayItemAnimation) { |
| // Show the tray by adding a notification. Note that animations still finish |
| // immediately at this stage of the test. |
| auto id = test_api->AddNotification(); |
| ASSERT_TRUE(test_api->IsTrayShown()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Set the animation duration scale to some small non-zero value for the rest |
| // of the test. |
| ui::ScopedAnimationDurationScaleMode test_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| |
| // Toggle "Do not disturb" mode on and off to ensure that the notification |
| // counter animates at least once (otherwise its animation object will still |
| // be null and the rest of this test will crash). |
| message_center::MessageCenter::Get()->SetQuietMode(true); |
| message_center::MessageCenter::Get()->SetQuietMode(false); |
| |
| // Verify that the notification counter's animation is in its "shown" state. |
| ASSERT_EQ(notification_counter()->animation_for_testing()->GetCurrentValue(), |
| 1); |
| |
| // Remove the notification to hide the notification center tray. |
| test_api->RemoveNotification(id); |
| ASSERT_TRUE(test_api->IsTrayAnimating()); |
| |
| // Wait for the hide animation to finish. |
| ui::LayerAnimationStoppedWaiter notification_center_tray_waiter; |
| notification_center_tray_waiter.Wait(test_api->GetTray()->layer()); |
| ASSERT_FALSE(test_api->IsTrayAnimating()); |
| |
| // Verify that the notification counter's animation is in its "hidden" state. |
| EXPECT_EQ(notification_counter()->animation_for_testing()->GetCurrentValue(), |
| 0); |
| } |
| |
| } // namespace ash |