| // Copyright 2018 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 "cc/input/snap_fling_controller.h" |
| |
| #include "cc/input/snap_fling_curve.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace cc { |
| namespace test { |
| namespace { |
| |
| class MockSnapFlingClient : public SnapFlingClient { |
| public: |
| MOCK_CONST_METHOD3(GetSnapFlingInfo, |
| bool(const gfx::Vector2dF& natural_displacement, |
| gfx::Vector2dF* initial_offset, |
| gfx::Vector2dF* target_offset)); |
| MOCK_METHOD0(ScrollEndForSnapFling, void()); |
| MOCK_METHOD0(RequestAnimationForSnapFling, void()); |
| MOCK_METHOD1(ScrollByForSnapFling, gfx::Vector2dF(const gfx::Vector2dF&)); |
| }; |
| |
| class MockSnapFlingCurve : public SnapFlingCurve { |
| public: |
| MockSnapFlingCurve() |
| : SnapFlingCurve(gfx::Vector2dF(), |
| gfx::Vector2dF(0, 100), |
| base::TimeTicks()) {} |
| MOCK_CONST_METHOD0(IsFinished, bool()); |
| MOCK_METHOD1(GetScrollDelta, gfx::Vector2dF(base::TimeTicks)); |
| }; |
| |
| } // namespace |
| |
| class SnapFlingControllerTest : public testing::Test { |
| public: |
| SnapFlingControllerTest() { |
| controller_ = std::make_unique<SnapFlingController>(&mock_client_); |
| } |
| void SetCurve(std::unique_ptr<SnapFlingCurve> curve) { |
| controller_->SetCurveForTest(std::move(curve)); |
| } |
| void SetActiveState() { controller_->SetActiveStateForTest(); } |
| |
| protected: |
| testing::StrictMock<MockSnapFlingClient> mock_client_; |
| std::unique_ptr<SnapFlingController> controller_; |
| }; |
| |
| TEST_F(SnapFlingControllerTest, DoesNotFilterGSBWhenIdle) { |
| EXPECT_FALSE(controller_->FilterEventForSnap( |
| SnapFlingController::GestureScrollType::kBegin)); |
| } |
| |
| TEST_F(SnapFlingControllerTest, FiltersGSUAndGSEDependingOnState) { |
| // Should not filter GSU and GSE if the fling is not active. |
| EXPECT_FALSE(controller_->FilterEventForSnap( |
| SnapFlingController::GestureScrollType::kUpdate)); |
| EXPECT_FALSE(controller_->FilterEventForSnap( |
| SnapFlingController::GestureScrollType::kEnd)); |
| |
| // Should filter GSU and GSE if the fling is active. |
| SetActiveState(); |
| EXPECT_TRUE(controller_->FilterEventForSnap( |
| SnapFlingController::GestureScrollType::kUpdate)); |
| EXPECT_TRUE(controller_->FilterEventForSnap( |
| SnapFlingController::GestureScrollType::kEnd)); |
| } |
| |
| TEST_F(SnapFlingControllerTest, CreatesAndAnimatesCurveOnFirstInertialGSU) { |
| SnapFlingController::GestureScrollUpdateInfo gsu; |
| gsu.delta = gfx::Vector2dF(0, -10); |
| gsu.is_in_inertial_phase = true; |
| |
| EXPECT_CALL(mock_client_, |
| GetSnapFlingInfo(testing::_, testing::_, testing::_)) |
| .WillOnce(DoAll(testing::SetArgPointee<1>(gfx::Vector2dF(0, 0)), |
| testing::SetArgPointee<2>(gfx::Vector2dF(0, 100)), |
| testing::Return(true))); |
| EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(1); |
| EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(1); |
| EXPECT_TRUE(controller_->HandleGestureScrollUpdate(gsu)); |
| testing::Mock::VerifyAndClearExpectations(&mock_client_); |
| } |
| |
| TEST_F(SnapFlingControllerTest, DoesNotHandleNonInertialGSU) { |
| SnapFlingController::GestureScrollUpdateInfo gsu; |
| gsu.delta = gfx::Vector2dF(0, -10); |
| gsu.is_in_inertial_phase = false; |
| |
| EXPECT_CALL(mock_client_, |
| GetSnapFlingInfo(testing::_, testing::_, testing::_)) |
| .Times(0); |
| EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(0); |
| EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(0); |
| EXPECT_FALSE(controller_->HandleGestureScrollUpdate(gsu)); |
| testing::Mock::VerifyAndClearExpectations(&mock_client_); |
| } |
| |
| TEST_F(SnapFlingControllerTest, AnimatesTheCurve) { |
| std::unique_ptr<MockSnapFlingCurve> mock_curve = |
| std::make_unique<MockSnapFlingCurve>(); |
| MockSnapFlingCurve* curve = mock_curve.get(); |
| SetCurve(std::move(mock_curve)); |
| |
| EXPECT_CALL(*curve, IsFinished()).WillOnce(testing::Return(false)); |
| EXPECT_CALL(*curve, GetScrollDelta(testing::_)) |
| .WillOnce(testing::Return(gfx::Vector2dF(100, 100))); |
| EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(1); |
| EXPECT_CALL(mock_client_, ScrollByForSnapFling(gfx::Vector2dF(100, 100))); |
| controller_->Animate(base::TimeTicks() + base::TimeDelta::FromSeconds(1)); |
| testing::Mock::VerifyAndClearExpectations(&mock_client_); |
| testing::Mock::VerifyAndClearExpectations(curve); |
| } |
| |
| TEST_F(SnapFlingControllerTest, FinishesTheCurve) { |
| std::unique_ptr<MockSnapFlingCurve> mock_curve = |
| std::make_unique<MockSnapFlingCurve>(); |
| MockSnapFlingCurve* curve = mock_curve.get(); |
| SetCurve(std::move(mock_curve)); |
| EXPECT_CALL(*curve, IsFinished()).WillOnce(testing::Return(true)); |
| EXPECT_CALL(*curve, GetScrollDelta(testing::_)).Times(0); |
| EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(0); |
| EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(0); |
| EXPECT_CALL(mock_client_, ScrollEndForSnapFling()).Times(1); |
| controller_->Animate(base::TimeTicks() + base::TimeDelta::FromSeconds(1)); |
| testing::Mock::VerifyAndClearExpectations(curve); |
| testing::Mock::VerifyAndClearExpectations(&mock_client_); |
| |
| EXPECT_CALL(*curve, IsFinished()).Times(0); |
| EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(0); |
| EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(0); |
| EXPECT_CALL(mock_client_, ScrollEndForSnapFling()).Times(0); |
| controller_->Animate(base::TimeTicks() + base::TimeDelta::FromSeconds(2)); |
| testing::Mock::VerifyAndClearExpectations(curve); |
| testing::Mock::VerifyAndClearExpectations(&mock_client_); |
| } |
| |
| TEST_F(SnapFlingControllerTest, GSBNotFilteredAndResetsStateWhenActive) { |
| SetActiveState(); |
| EXPECT_TRUE(controller_->FilterEventForSnap( |
| SnapFlingController::GestureScrollType::kUpdate)); |
| |
| EXPECT_CALL(mock_client_, ScrollEndForSnapFling()).Times(1); |
| EXPECT_FALSE(controller_->FilterEventForSnap( |
| SnapFlingController::GestureScrollType::kBegin)); |
| testing::Mock::VerifyAndClearExpectations(&mock_client_); |
| |
| EXPECT_FALSE(controller_->FilterEventForSnap( |
| SnapFlingController::GestureScrollType::kUpdate)); |
| } |
| |
| } // namespace test |
| } // namespace cc |