| // Copyright 2016 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/shelf/shelf_background_animator.h" |
| |
| #include <memory> |
| |
| #include "ash/animation/animation_change_type.h" |
| #include "ash/public/cpp/ash_switches.h" |
| #include "ash/session/test_session_controller_client.h" |
| #include "ash/shelf/shelf_background_animator_observer.h" |
| #include "ash/shelf/shelf_constants.h" |
| #include "ash/test/ash_test_base.h" |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/macros.h" |
| #include "base/test/test_mock_time_task_runner.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "ui/gfx/animation/slide_animation.h" |
| |
| namespace ash { |
| namespace { |
| |
| static auto kMaxAlpha = ShelfBackgroundAnimator::kMaxAlpha; |
| |
| // A valid color value that is distinct from any final animation state values. |
| // Used to check if color values are changed during animations. |
| const SkColor kDummyColor = SK_ColorBLUE; |
| |
| // Helper function to get the base color from |color|, i.e., remove the alpha. |
| SkColor GetBaseColor(SkColor color) { |
| return SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), |
| SkColorGetB(color)); |
| } |
| |
| // Observer that caches color values for the last observation. |
| class TestShelfBackgroundObserver : public ShelfBackgroundAnimatorObserver { |
| public: |
| TestShelfBackgroundObserver() = default; |
| ~TestShelfBackgroundObserver() override = default; |
| |
| SkColor background_color() const { return background_color_; } |
| |
| // Convenience function to get the alpha value from |background_color_|. |
| int GetBackgroundAlpha() const; |
| |
| SkColor item_background_color() const { return item_background_color_; } |
| |
| // Convenience function to get the alpha value from |item_background_color_|. |
| int GetItemBackgroundAlpha() const; |
| |
| // ShelfBackgroundObserver: |
| void UpdateShelfBackground(SkColor color) override; |
| void UpdateShelfItemBackground(SkColor color) override; |
| |
| private: |
| int background_color_ = SK_ColorTRANSPARENT; |
| int item_background_color_ = SK_ColorTRANSPARENT; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestShelfBackgroundObserver); |
| }; |
| |
| int TestShelfBackgroundObserver::GetBackgroundAlpha() const { |
| return SkColorGetA(background_color_); |
| } |
| |
| int TestShelfBackgroundObserver::GetItemBackgroundAlpha() const { |
| return SkColorGetA(item_background_color_); |
| } |
| |
| void TestShelfBackgroundObserver::UpdateShelfBackground(SkColor color) { |
| background_color_ = color; |
| } |
| |
| void TestShelfBackgroundObserver::UpdateShelfItemBackground(SkColor color) { |
| item_background_color_ = color; |
| } |
| |
| } // namespace |
| |
| // Provides internal access to a ShelfBackgroundAnimator instance. |
| class ShelfBackgroundAnimatorTestApi { |
| public: |
| explicit ShelfBackgroundAnimatorTestApi(ShelfBackgroundAnimator* animator) |
| : animator_(animator) {} |
| |
| ~ShelfBackgroundAnimatorTestApi() = default; |
| |
| ShelfBackgroundType previous_background_type() const { |
| return animator_->previous_background_type_; |
| } |
| |
| gfx::SlideAnimation* animator() const { return animator_->animator_.get(); } |
| |
| SkColor shelf_background_target_color() const { |
| return animator_->shelf_background_values_.target_color(); |
| } |
| |
| SkColor item_background_target_color() const { |
| return animator_->item_background_values_.target_color(); |
| } |
| |
| private: |
| // The instance to provide internal access to. |
| ShelfBackgroundAnimator* animator_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ShelfBackgroundAnimatorTestApi); |
| }; |
| |
| class ShelfBackgroundAnimatorTest : public testing::Test { |
| public: |
| ShelfBackgroundAnimatorTest() = default; |
| ~ShelfBackgroundAnimatorTest() override = default; |
| |
| // testing::Test: |
| void SetUp() override; |
| |
| protected: |
| // Convenience wrapper for |animator_|'s PaintBackground(). |
| void PaintBackground( |
| ShelfBackgroundType background_type, |
| AnimationChangeType change_type = AnimationChangeType::IMMEDIATE); |
| |
| // Set all of the color values for the |observer_|. |
| void SetColorValuesOnObserver(SkColor color); |
| |
| // Completes all the animations. |
| void CompleteAnimations(); |
| |
| TestShelfBackgroundObserver observer_; |
| |
| // Test target. |
| std::unique_ptr<ShelfBackgroundAnimator> animator_; |
| |
| // Provides internal access to |animator_|. |
| std::unique_ptr<ShelfBackgroundAnimatorTestApi> test_api_; |
| |
| // Used to control the animations. |
| scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; |
| |
| private: |
| std::unique_ptr<base::ThreadTaskRunnerHandle> task_runner_handle_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ShelfBackgroundAnimatorTest); |
| }; |
| |
| void ShelfBackgroundAnimatorTest::SetUp() { |
| task_runner_ = new base::TestMockTimeTaskRunner(); |
| task_runner_handle_.reset(new base::ThreadTaskRunnerHandle(task_runner_)); |
| |
| animator_.reset( |
| new ShelfBackgroundAnimator(SHELF_BACKGROUND_DEFAULT, nullptr, nullptr)); |
| animator_->AddObserver(&observer_); |
| |
| test_api_.reset(new ShelfBackgroundAnimatorTestApi(animator_.get())); |
| } |
| |
| void ShelfBackgroundAnimatorTest::PaintBackground( |
| ShelfBackgroundType background_type, |
| AnimationChangeType change_type) { |
| animator_->PaintBackground(background_type, change_type); |
| } |
| |
| void ShelfBackgroundAnimatorTest::SetColorValuesOnObserver(SkColor color) { |
| observer_.UpdateShelfBackground(color); |
| observer_.UpdateShelfItemBackground(color); |
| } |
| |
| void ShelfBackgroundAnimatorTest::CompleteAnimations() { |
| task_runner_->FastForwardUntilNoTasksRemain(); |
| } |
| |
| // Verify the |previous_background_type_| and |target_background_type_| values |
| // when animating to the same target type multiple times. |
| TEST_F(ShelfBackgroundAnimatorTest, BackgroundTypesWhenAnimatingToSameTarget) { |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED); |
| EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, animator_->target_background_type()); |
| |
| PaintBackground(SHELF_BACKGROUND_DEFAULT); |
| EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, animator_->target_background_type()); |
| EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, test_api_->previous_background_type()); |
| |
| PaintBackground(SHELF_BACKGROUND_DEFAULT); |
| EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, animator_->target_background_type()); |
| EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, test_api_->previous_background_type()); |
| } |
| |
| // Verify subsequent calls to PaintBackground() using the |
| // AnimationChangeType::ANIMATE change type are ignored. |
| TEST_F(ShelfBackgroundAnimatorTest, |
| MultipleAnimateCallsToSameTargetAreIgnored) { |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED); |
| SetColorValuesOnObserver(kDummyColor); |
| animator_->PaintBackground(SHELF_BACKGROUND_DEFAULT, |
| AnimationChangeType::ANIMATE); |
| CompleteAnimations(); |
| |
| EXPECT_NE(observer_.background_color(), kDummyColor); |
| EXPECT_NE(observer_.item_background_color(), kDummyColor); |
| |
| SetColorValuesOnObserver(kDummyColor); |
| animator_->PaintBackground(SHELF_BACKGROUND_DEFAULT, |
| AnimationChangeType::ANIMATE); |
| CompleteAnimations(); |
| |
| EXPECT_EQ(observer_.background_color(), kDummyColor); |
| EXPECT_EQ(observer_.item_background_color(), kDummyColor); |
| } |
| |
| // Verify observers are updated with the current values when they are added. |
| TEST_F(ShelfBackgroundAnimatorTest, ObserversUpdatedWhenAdded) { |
| animator_->RemoveObserver(&observer_); |
| SetColorValuesOnObserver(kDummyColor); |
| |
| animator_->AddObserver(&observer_); |
| |
| EXPECT_NE(observer_.background_color(), kDummyColor); |
| EXPECT_NE(observer_.item_background_color(), kDummyColor); |
| } |
| |
| // Verify the alpha values for the SHELF_BACKGROUND_DEFAULT state. |
| TEST_F(ShelfBackgroundAnimatorTest, DefaultBackground) { |
| PaintBackground(SHELF_BACKGROUND_DEFAULT); |
| |
| EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, animator_->target_background_type()); |
| EXPECT_EQ(0, observer_.GetBackgroundAlpha()); |
| EXPECT_EQ(kShelfTranslucentAlpha, observer_.GetItemBackgroundAlpha()); |
| } |
| |
| // Verify the alpha values for the SHELF_BACKGROUND_OVERLAP state. |
| TEST_F(ShelfBackgroundAnimatorTest, OverlapBackground) { |
| PaintBackground(SHELF_BACKGROUND_OVERLAP); |
| |
| EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, animator_->target_background_type()); |
| EXPECT_EQ(kShelfTranslucentAlpha, observer_.GetBackgroundAlpha()); |
| EXPECT_EQ(0, observer_.GetItemBackgroundAlpha()); |
| } |
| |
| // Verify the alpha values for the SHELF_BACKGROUND_MAXIMIZED state. |
| TEST_F(ShelfBackgroundAnimatorTest, MaximizedBackground) { |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED); |
| |
| EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, animator_->target_background_type()); |
| EXPECT_EQ(kMaxAlpha, observer_.GetBackgroundAlpha()); |
| EXPECT_EQ(0, observer_.GetItemBackgroundAlpha()); |
| } |
| |
| // Verify the alpha values for the SHELF_BACKGROUND_APP_LIST state. |
| TEST_F(ShelfBackgroundAnimatorTest, FullscreenAppListBackground) { |
| PaintBackground(SHELF_BACKGROUND_APP_LIST); |
| |
| EXPECT_EQ(SHELF_BACKGROUND_APP_LIST, animator_->target_background_type()); |
| EXPECT_EQ(0, observer_.GetBackgroundAlpha()); |
| EXPECT_EQ(0, observer_.GetItemBackgroundAlpha()); |
| } |
| |
| TEST_F(ShelfBackgroundAnimatorTest, |
| AnimatorIsDetroyedWhenCompletingSuccessfully) { |
| PaintBackground(SHELF_BACKGROUND_OVERLAP, AnimationChangeType::ANIMATE); |
| EXPECT_TRUE(test_api_->animator()); |
| CompleteAnimations(); |
| EXPECT_FALSE(test_api_->animator()); |
| } |
| |
| TEST_F(ShelfBackgroundAnimatorTest, |
| AnimatorDestroyedWhenChangingBackgroundImmediately) { |
| PaintBackground(SHELF_BACKGROUND_OVERLAP, AnimationChangeType::ANIMATE); |
| EXPECT_TRUE(test_api_->animator()); |
| |
| PaintBackground(SHELF_BACKGROUND_OVERLAP, AnimationChangeType::IMMEDIATE); |
| EXPECT_FALSE(test_api_->animator()); |
| } |
| |
| // Verify that existing animator is used when animating to the previous state. |
| TEST_F(ShelfBackgroundAnimatorTest, |
| ExistingAnimatorIsReusedWhenAnimatingToPreviousState) { |
| PaintBackground(SHELF_BACKGROUND_DEFAULT, AnimationChangeType::ANIMATE); |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED, AnimationChangeType::ANIMATE); |
| |
| const gfx::SlideAnimation* animator = test_api_->animator(); |
| EXPECT_TRUE(animator); |
| |
| PaintBackground(SHELF_BACKGROUND_DEFAULT, AnimationChangeType::ANIMATE); |
| |
| EXPECT_EQ(animator, test_api_->animator()); |
| } |
| |
| // Verify that existing animator is not re-used when the target background isn't |
| // the same as the previous background. |
| TEST_F(ShelfBackgroundAnimatorTest, |
| ExistingAnimatorNotReusedWhenTargetBackgroundNotPreviousBackground) { |
| PaintBackground(SHELF_BACKGROUND_DEFAULT, AnimationChangeType::ANIMATE); |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED, AnimationChangeType::ANIMATE); |
| |
| const gfx::SlideAnimation* animator = test_api_->animator(); |
| EXPECT_TRUE(animator); |
| |
| EXPECT_NE(SHELF_BACKGROUND_OVERLAP, test_api_->previous_background_type()); |
| PaintBackground(SHELF_BACKGROUND_OVERLAP, AnimationChangeType::ANIMATE); |
| |
| EXPECT_NE(animator, test_api_->animator()); |
| } |
| |
| // Verify observers are always notified, even when alpha values don't change. |
| TEST_F(ShelfBackgroundAnimatorTest, |
| ObserversAreNotifiedWhenSnappingToSameTargetBackground) { |
| PaintBackground(SHELF_BACKGROUND_DEFAULT); |
| SetColorValuesOnObserver(kDummyColor); |
| PaintBackground(SHELF_BACKGROUND_DEFAULT); |
| |
| EXPECT_NE(observer_.background_color(), kDummyColor); |
| EXPECT_NE(observer_.item_background_color(), kDummyColor); |
| } |
| |
| class ShelfBackgroundTargetColorTest : public NoSessionAshTestBase { |
| public: |
| ShelfBackgroundTargetColorTest() = default; |
| ~ShelfBackgroundTargetColorTest() override = default; |
| |
| // AshTestBase: |
| void SetUp() override { |
| // Do not allow the shelf color to be derived from the wallpaper, in order |
| // to have a fixed color in tests. |
| base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( |
| switches::kAshShelfColor, switches::kAshShelfColorDisabled); |
| AshTestBase::SetUp(); |
| |
| animator_.reset(new ShelfBackgroundAnimator(SHELF_BACKGROUND_DEFAULT, |
| nullptr, nullptr)); |
| test_api_.reset(new ShelfBackgroundAnimatorTestApi(animator_.get())); |
| } |
| |
| protected: |
| // Helper function to notify session state changes. |
| void NotifySessionStateChanged(session_manager::SessionState state) { |
| GetSessionControllerClient()->SetSessionState(state); |
| } |
| |
| // Test target. |
| std::unique_ptr<ShelfBackgroundAnimator> animator_; |
| |
| // Provides internal access to |animator_|. |
| std::unique_ptr<ShelfBackgroundAnimatorTestApi> test_api_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ShelfBackgroundTargetColorTest); |
| }; |
| |
| // Verify the target colors of the shelf and item backgrounds are updated after |
| // session state changes. Only compare the base color, because different alpha |
| // values may be applied based on |ShelfBackgroundType|, which is verifed by |
| // |ShelfBackgroundAnimatorTest|. |
| TEST_F(ShelfBackgroundTargetColorTest, |
| ShelfAndItemBackgroundColorUpdatedWithSessionState) { |
| // The shelf is not initialized until session state becomes active, so the |
| // following two cases don't have visible effects until we support views-based |
| // shelf for all session states, but it's still good to check them here. |
| NotifySessionStateChanged(session_manager::SessionState::OOBE); |
| EXPECT_EQ(GetBaseColor(test_api_->shelf_background_target_color()), |
| GetBaseColor(SK_ColorTRANSPARENT)); |
| EXPECT_EQ(GetBaseColor(test_api_->item_background_target_color()), |
| GetBaseColor(SK_ColorTRANSPARENT)); |
| |
| NotifySessionStateChanged(session_manager::SessionState::LOGIN_PRIMARY); |
| EXPECT_EQ(GetBaseColor(test_api_->shelf_background_target_color()), |
| GetBaseColor(SK_ColorTRANSPARENT)); |
| EXPECT_EQ(GetBaseColor(test_api_->item_background_target_color()), |
| GetBaseColor(SK_ColorTRANSPARENT)); |
| |
| SimulateUserLogin("user1@test.com"); |
| |
| NotifySessionStateChanged( |
| session_manager::SessionState::LOGGED_IN_NOT_ACTIVE); |
| EXPECT_EQ(GetBaseColor(test_api_->shelf_background_target_color()), |
| GetBaseColor(SK_ColorTRANSPARENT)); |
| EXPECT_EQ(GetBaseColor(test_api_->item_background_target_color()), |
| GetBaseColor(SK_ColorTRANSPARENT)); |
| |
| // The shelf has a non-transparent background only when session state is |
| // active. |
| NotifySessionStateChanged(session_manager::SessionState::ACTIVE); |
| EXPECT_EQ(GetBaseColor(test_api_->shelf_background_target_color()), |
| GetBaseColor(kShelfDefaultBaseColor)); |
| EXPECT_EQ(GetBaseColor(test_api_->item_background_target_color()), |
| GetBaseColor(kShelfDefaultBaseColor)); |
| |
| NotifySessionStateChanged(session_manager::SessionState::LOCKED); |
| EXPECT_EQ(GetBaseColor(test_api_->shelf_background_target_color()), |
| GetBaseColor(SK_ColorTRANSPARENT)); |
| EXPECT_EQ(GetBaseColor(test_api_->item_background_target_color()), |
| GetBaseColor(SK_ColorTRANSPARENT)); |
| |
| // Ensure the shelf background color is correct after unlocking. |
| NotifySessionStateChanged(session_manager::SessionState::ACTIVE); |
| EXPECT_EQ(GetBaseColor(test_api_->shelf_background_target_color()), |
| GetBaseColor(kShelfDefaultBaseColor)); |
| EXPECT_EQ(GetBaseColor(test_api_->item_background_target_color()), |
| GetBaseColor(kShelfDefaultBaseColor)); |
| |
| NotifySessionStateChanged(session_manager::SessionState::LOGIN_SECONDARY); |
| EXPECT_EQ(GetBaseColor(test_api_->shelf_background_target_color()), |
| GetBaseColor(SK_ColorTRANSPARENT)); |
| EXPECT_EQ(GetBaseColor(test_api_->item_background_target_color()), |
| GetBaseColor(SK_ColorTRANSPARENT)); |
| |
| // Ensure the shelf background color is correct after closing the user adding |
| // screen. |
| NotifySessionStateChanged(session_manager::SessionState::ACTIVE); |
| EXPECT_EQ(GetBaseColor(test_api_->shelf_background_target_color()), |
| GetBaseColor(kShelfDefaultBaseColor)); |
| EXPECT_EQ(GetBaseColor(test_api_->item_background_target_color()), |
| GetBaseColor(kShelfDefaultBaseColor)); |
| } |
| |
| } // namespace ash |