blob: ebbf5b18cfd54a80761059aaf18013d18a301203 [file] [log] [blame]
// 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(
testing::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