| // Copyright 2021 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/native_theme/scrollbar_animator_mac.h" |
| |
| #include "base/logging.h" |
| #include "base/test/task_environment.h" |
| #include "base/time/time.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using testing::Return; |
| |
| namespace ui { |
| |
| namespace { |
| |
| constexpr int kExpandedWidth = 32; |
| constexpr int kUnexpandedWidth = 16; |
| constexpr auto kTimeToFadeOut = base::Milliseconds(500); |
| constexpr auto kAnimationTime = base::Milliseconds(250); |
| |
| class MockClient : public OverlayScrollbarAnimatorMac::Client { |
| public: |
| MOCK_CONST_METHOD0(IsMouseInScrollbarFrameRect, bool()); |
| MOCK_METHOD1(SetHidden, void(bool)); |
| MOCK_METHOD0(SetThumbNeedsDisplay, void()); |
| MOCK_METHOD0(SetTrackNeedsDisplay, void()); |
| }; |
| |
| class MacScrollbarAnimatorTest : public ::testing::Test { |
| public: |
| MacScrollbarAnimatorTest() |
| : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) { |
| scrollbar_ = std::make_unique<OverlayScrollbarAnimatorMac>( |
| &client_, kExpandedWidth, kUnexpandedWidth, |
| task_environment_.GetMainThreadTaskRunner()); |
| } |
| |
| ~MacScrollbarAnimatorTest() override = default; |
| |
| base::test::TaskEnvironment task_environment_; |
| MockClient client_; |
| std::unique_ptr<OverlayScrollbarAnimatorMac> scrollbar_; |
| }; |
| |
| TEST_F(MacScrollbarAnimatorTest, DidScrollThenFadeOut) { |
| // The scrollbar_ starts as invisible. |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 0.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 0.f); |
| |
| // Scroll with the mouse not in the track. |
| EXPECT_CALL(client_, IsMouseInScrollbarFrameRect()).WillOnce(Return(false)); |
| EXPECT_CALL(client_, SetHidden(false)); |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()); |
| scrollbar_->DidScroll(); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 0.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kUnexpandedWidth); |
| |
| // Fast-forward until just before the timeout threshold is hit. |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).Times(0); |
| task_environment_.FastForwardBy(kTimeToFadeOut); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 0.f); |
| |
| // Fast-forward through half of the fade-out animation. |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).WillRepeatedly(Return()); |
| task_environment_.FastForwardBy(kAnimationTime / 2); |
| EXPECT_GT(scrollbar_->GetThumbAlpha(), 0.f); |
| EXPECT_LT(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kUnexpandedWidth); |
| |
| // Fast-forward through past the end of the fade-out animation. The scrollbar_ |
| // should be hidden. |
| EXPECT_CALL(client_, SetHidden(true)); |
| task_environment_.FastForwardBy(kAnimationTime); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 0.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 0.f); |
| } |
| |
| TEST_F(MacScrollbarAnimatorTest, DidScrollStartsInTrack) { |
| // Scroll with the mouse in the track. |
| EXPECT_CALL(client_, IsMouseInScrollbarFrameRect()).WillOnce(Return(true)); |
| EXPECT_CALL(client_, SetHidden(false)); |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()); |
| scrollbar_->DidScroll(); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Fast-forward long past the fade-out animation would happen. Nothing should |
| // happen. |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).Times(0); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()).Times(0); |
| task_environment_.FastForwardBy(10 * kTimeToFadeOut); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Scroll again. Again, nothing should happen. |
| scrollbar_->DidScroll(); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Have the mouse leave the scrollbar_. Fast-forward not enough time for the |
| // scrollbar_ to fade out, then have the mouse re-enter. Exit again. Still |
| // nothing should happen. |
| scrollbar_->MouseDidExit(); |
| task_environment_.FastForwardBy(kTimeToFadeOut / 2); |
| scrollbar_->MouseDidEnter(); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| scrollbar_->MouseDidExit(); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Wait most of the fade-out timer's time. Nothing should happen in this |
| // interval. |
| task_environment_.FastForwardBy(3 * kTimeToFadeOut / 4); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Allow the fade-out animation to progress about halfway through. |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).WillRepeatedly(Return()); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()).WillRepeatedly(Return()); |
| task_environment_.FastForwardBy(kTimeToFadeOut / 4 + kAnimationTime / 2); |
| EXPECT_GT(scrollbar_->GetThumbAlpha(), 0.f); |
| EXPECT_LT(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_GT(scrollbar_->GetTrackAlpha(), 0.f); |
| EXPECT_LT(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Scroll, interrupting the fade-out animation. |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).Times(1); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()).Times(1); |
| scrollbar_->DidScroll(); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Wait most of the fade-out timer's time. Nothing should happen in this time. |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).Times(0); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()).Times(0); |
| task_environment_.FastForwardBy(3 * kTimeToFadeOut / 4); |
| |
| // Allow the fade-out animation to progress halfway again. |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).WillRepeatedly(Return()); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()).WillRepeatedly(Return()); |
| task_environment_.FastForwardBy(kTimeToFadeOut / 4 + kAnimationTime / 2); |
| EXPECT_GT(scrollbar_->GetThumbAlpha(), 0.f); |
| EXPECT_LT(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_GT(scrollbar_->GetTrackAlpha(), 0.f); |
| EXPECT_LT(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // And let it progress to completion. The scrollbar_ should hide itself. |
| EXPECT_CALL(client_, SetHidden(true)); |
| task_environment_.FastForwardBy(kAnimationTime); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 0.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 0.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kUnexpandedWidth); |
| } |
| |
| TEST_F(MacScrollbarAnimatorTest, EnterTrack) { |
| // First try to enter the track before showing the scrollbar_. Nothing should |
| // happen. |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 0.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 0.f); |
| scrollbar_->MouseDidEnter(); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 0.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 0.f); |
| |
| // Scroll with the mouse in the track. |
| EXPECT_CALL(client_, IsMouseInScrollbarFrameRect()).WillOnce(Return(false)); |
| EXPECT_CALL(client_, SetHidden(false)); |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()); |
| scrollbar_->DidScroll(); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 0.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kUnexpandedWidth); |
| |
| // Have the mouse enter the scrollbar_ area. |
| scrollbar_->MouseDidEnter(); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 0.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kUnexpandedWidth); |
| |
| // Fast-forward part of the animation. |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).WillRepeatedly(Return()); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()).WillRepeatedly(Return()); |
| task_environment_.FastForwardBy(kAnimationTime / 2); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_GT(scrollbar_->GetTrackAlpha(), 0.f); |
| EXPECT_LT(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_GT(scrollbar_->GetThumbWidth(), kUnexpandedWidth); |
| EXPECT_LT(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Fast-forward through the rest of the animation. |
| task_environment_.FastForwardBy(kAnimationTime); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Fast-forward for a long time. Nothing should happen (no fade-out). |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).Times(0); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()).Times(0); |
| task_environment_.FastForwardBy(10 * kTimeToFadeOut); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Move the mouse out and wait for the the fade-out should start. |
| scrollbar_->MouseDidExit(); |
| task_environment_.FastForwardBy(kTimeToFadeOut); |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).WillRepeatedly(Return()); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()).WillRepeatedly(Return()); |
| task_environment_.FastForwardBy(kAnimationTime / 2); |
| EXPECT_GT(scrollbar_->GetThumbAlpha(), 0.f); |
| EXPECT_LT(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_GT(scrollbar_->GetTrackAlpha(), 0.f); |
| EXPECT_LT(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Re-enter. This will immediately return us to full opacity. |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).Times(1); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()).Times(1); |
| scrollbar_->MouseDidEnter(); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Wait for a long time. Nothing should happen. |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).Times(0); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()).Times(0); |
| task_environment_.FastForwardBy(10 * kTimeToFadeOut); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Re-leave the track. Again nothing should happen. |
| scrollbar_->MouseDidExit(); |
| |
| // Fast-forward through the start of the fade-out. |
| task_environment_.FastForwardBy(kTimeToFadeOut); |
| EXPECT_CALL(client_, SetThumbNeedsDisplay()).WillRepeatedly(Return()); |
| EXPECT_CALL(client_, SetTrackNeedsDisplay()).WillRepeatedly(Return()); |
| task_environment_.FastForwardBy(kAnimationTime / 2); |
| EXPECT_GT(scrollbar_->GetThumbAlpha(), 0.f); |
| EXPECT_LT(scrollbar_->GetThumbAlpha(), 1.f); |
| EXPECT_GT(scrollbar_->GetTrackAlpha(), 0.f); |
| EXPECT_LT(scrollbar_->GetTrackAlpha(), 1.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kExpandedWidth); |
| |
| // Fast-forward until the fade-out completes. |
| EXPECT_CALL(client_, SetHidden(true)); |
| task_environment_.FastForwardBy(kAnimationTime); |
| EXPECT_EQ(scrollbar_->GetThumbAlpha(), 0.f); |
| EXPECT_EQ(scrollbar_->GetTrackAlpha(), 0.f); |
| EXPECT_EQ(scrollbar_->GetThumbWidth(), kUnexpandedWidth); |
| } |
| |
| } // namespace |
| |
| } // namespace ui |