/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "gtest/gtest.h" #include "gmock/gmock.h" #include #include #include "AccessibleCaretManager.h" #include "mozilla/AccessibleCaretEventHub.h" #include "mozilla/BasicEvents.h" #include "mozilla/MouseEvents.h" #include "mozilla/TouchEvents.h" using ::testing::_; using ::testing::AtLeast; using ::testing::DefaultValue; using ::testing::Eq; using ::testing::InSequence; using ::testing::MockFunction; using ::testing::Return; // ----------------------------------------------------------------------------- // This file test the state transitions of AccessibleCaretEventHub under // various combination of events and callbacks. namespace mozilla { class MockAccessibleCaretManager : public AccessibleCaretManager { public: MockAccessibleCaretManager() : AccessibleCaretManager(nullptr) {} MOCK_METHOD2(PressCaret, nsresult(const nsPoint& aPoint, EventClassID aEventClass)); MOCK_METHOD1(DragCaret, nsresult(const nsPoint& aPoint)); MOCK_METHOD0(ReleaseCaret, nsresult()); MOCK_METHOD1(TapCaret, nsresult(const nsPoint& aPoint)); MOCK_METHOD1(SelectWordOrShortcut, nsresult(const nsPoint& aPoint)); MOCK_METHOD0(OnScrollStart, void()); MOCK_METHOD0(OnScrollEnd, void()); MOCK_METHOD0(OnScrollPositionChanged, void()); MOCK_METHOD0(OnBlur, void()); }; class MockAccessibleCaretEventHub : public AccessibleCaretEventHub { public: using AccessibleCaretEventHub::DragCaretState; using AccessibleCaretEventHub::LongTapState; using AccessibleCaretEventHub::NoActionState; using AccessibleCaretEventHub::PressCaretState; using AccessibleCaretEventHub::PressNoCaretState; using AccessibleCaretEventHub::ScrollState; MockAccessibleCaretEventHub() : AccessibleCaretEventHub(nullptr) { mManager = MakeUnique(); mInitialized = true; } nsPoint GetTouchEventPosition(WidgetTouchEvent* aEvent, int32_t aIdentifier) const override { // Return the device point directly. LayoutDeviceIntPoint touchIntPoint = aEvent->mTouches[0]->mRefPoint; return nsPoint(touchIntPoint.x, touchIntPoint.y); } nsPoint GetMouseEventPosition(WidgetMouseEvent* aEvent) const override { // Return the device point directly. LayoutDeviceIntPoint mouseIntPoint = aEvent->AsGUIEvent()->mRefPoint; return nsPoint(mouseIntPoint.x, mouseIntPoint.y); } MockAccessibleCaretManager* GetMockAccessibleCaretManager() { return static_cast(mManager.get()); } }; // Print the name of the state for debugging. static ::std::ostream& operator<<( ::std::ostream& aOstream, const MockAccessibleCaretEventHub::State* aState) { return aOstream << aState->Name(); } class AccessibleCaretEventHubTester : public ::testing::Test { public: AccessibleCaretEventHubTester() { DefaultValue::Set(NS_OK); EXPECT_EQ(mHub->GetState(), MockAccessibleCaretEventHub::NoActionState()); // AccessibleCaretEventHub requires the caller to hold a ref to it. We just // add ref here for the sake of convenience. mHub.get()->AddRef(); } ~AccessibleCaretEventHubTester() override { // Release the ref added in the constructor. mHub.get()->Release(); } static UniquePtr CreateMouseEvent(EventMessage aMessage, nscoord aX, nscoord aY) { auto event = MakeUnique(true, aMessage, nullptr, WidgetMouseEvent::eReal); event->mButton = MouseButton::ePrimary; event->mRefPoint = LayoutDeviceIntPoint(aX, aY); return std::move(event); } static UniquePtr CreateMousePressEvent(nscoord aX, nscoord aY) { return CreateMouseEvent(eMouseDown, aX, aY); } static UniquePtr CreateMouseMoveEvent(nscoord aX, nscoord aY) { return CreateMouseEvent(eMouseMove, aX, aY); } static UniquePtr CreateMouseReleaseEvent(nscoord aX, nscoord aY) { return CreateMouseEvent(eMouseUp, aX, aY); } static UniquePtr CreateLongTapEvent(nscoord aX, nscoord aY) { return CreateMouseEvent(eMouseLongTap, aX, aY); } static UniquePtr CreateTouchEvent(EventMessage aMessage, nscoord aX, nscoord aY) { auto event = MakeUnique(true, aMessage, nullptr); int32_t identifier = 0; LayoutDeviceIntPoint point(aX, aY); LayoutDeviceIntPoint radius(19, 19); float rotationAngle = 0; float force = 1; RefPtr touch( new dom::Touch(identifier, point, radius, rotationAngle, force)); event->mTouches.AppendElement(touch); return std::move(event); } static UniquePtr CreateTouchStartEvent(nscoord aX, nscoord aY) { return CreateTouchEvent(eTouchStart, aX, aY); } static UniquePtr CreateTouchMoveEvent(nscoord aX, nscoord aY) { return CreateTouchEvent(eTouchMove, aX, aY); } static UniquePtr CreateTouchEndEvent(nscoord aX, nscoord aY) { return CreateTouchEvent(eTouchEnd, aX, aY); } static UniquePtr CreateTouchCancelEvent(nscoord aX, nscoord aY) { return CreateTouchEvent(eTouchCancel, aX, aY); } static UniquePtr CreateWheelEvent(EventMessage aMessage) { auto event = MakeUnique(true, aMessage, nullptr); return std::move(event); } MOZ_CAN_RUN_SCRIPT_BOUNDARY void TestAsyncPanZoomScroll(); MOZ_CAN_RUN_SCRIPT_BOUNDARY void HandleEventAndCheckState( UniquePtr aEvent, MockAccessibleCaretEventHub::State* aExpectedState, nsEventStatus aExpectedEventStatus) { RefPtr hub(mHub); nsEventStatus rv = hub->HandleEvent(aEvent.get()); EXPECT_EQ(hub->GetState(), aExpectedState); EXPECT_EQ(rv, aExpectedEventStatus); } void CheckState(MockAccessibleCaretEventHub::State* aExpectedState) { EXPECT_EQ(mHub->GetState(), aExpectedState); } template MOZ_CAN_RUN_SCRIPT_BOUNDARY void TestPressReleaseOnNoCaret( PressEventCreator aPressEventCreator, ReleaseEventCreator aReleaseEventCreator); template MOZ_CAN_RUN_SCRIPT_BOUNDARY void TestPressReleaseOnCaret( PressEventCreator aPressEventCreator, ReleaseEventCreator aReleaseEventCreator); template MOZ_CAN_RUN_SCRIPT_BOUNDARY void TestPressMoveReleaseOnNoCaret( PressEventCreator aPressEventCreator, MoveEventCreator aMoveEventCreator, ReleaseEventCreator aReleaseEventCreator); template MOZ_CAN_RUN_SCRIPT_BOUNDARY void TestPressMoveReleaseOnCaret( PressEventCreator aPressEventCreator, MoveEventCreator aMoveEventCreator, ReleaseEventCreator aReleaseEventCreator); template MOZ_CAN_RUN_SCRIPT_BOUNDARY void TestLongTapWithSelectWordSuccessful( PressEventCreator aPressEventCreator, ReleaseEventCreator aReleaseEventCreator); template MOZ_CAN_RUN_SCRIPT_BOUNDARY void TestLongTapWithSelectWordFailed( PressEventCreator aPressEventCreator, ReleaseEventCreator aReleaseEventCreator); template MOZ_CAN_RUN_SCRIPT_BOUNDARY void TestEventDrivenAsyncPanZoomScroll( PressEventCreator aPressEventCreator, MoveEventCreator aMoveEventCreator, ReleaseEventCreator aReleaseEventCreator); // Member variables RefPtr mHub{new MockAccessibleCaretEventHub()}; }; // class AccessibleCaretEventHubTester TEST_F(AccessibleCaretEventHubTester, TestMousePressReleaseOnNoCaret) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressReleaseOnNoCaret(CreateMousePressEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchPressReleaseOnNoCaret) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressReleaseOnNoCaret(CreateTouchStartEvent, CreateTouchEndEvent); } template void AccessibleCaretEventHubTester::TestPressReleaseOnNoCaret( PressEventCreator aPressEventCreator, ReleaseEventCreator aReleaseEventCreator) { EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _)) .WillOnce(Return(NS_ERROR_FAILURE)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), ReleaseCaret()).Times(0); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), TapCaret(_)).Times(0); HandleEventAndCheckState(aPressEventCreator(0, 0), MockAccessibleCaretEventHub::PressNoCaretState(), nsEventStatus_eIgnore); HandleEventAndCheckState(aReleaseEventCreator(0, 0), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); } TEST_F(AccessibleCaretEventHubTester, TestMousePressReleaseOnCaret) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressReleaseOnCaret(CreateMousePressEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchPressReleaseOnCaret) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressReleaseOnCaret(CreateTouchStartEvent, CreateTouchEndEvent); } template void AccessibleCaretEventHubTester::TestPressReleaseOnCaret( PressEventCreator aPressEventCreator, ReleaseEventCreator aReleaseEventCreator) { { InSequence dummy; EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _)) .WillOnce(Return(NS_OK)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), SelectWordOrShortcut(_)) .Times(0); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), ReleaseCaret()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), TapCaret(_)); } HandleEventAndCheckState(aPressEventCreator(0, 0), MockAccessibleCaretEventHub::PressCaretState(), nsEventStatus_eConsumeNoDefault); HandleEventAndCheckState(CreateLongTapEvent(0, 0), MockAccessibleCaretEventHub::PressCaretState(), nsEventStatus_eConsumeNoDefault); HandleEventAndCheckState(aReleaseEventCreator(0, 0), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eConsumeNoDefault); } TEST_F(AccessibleCaretEventHubTester, TestMousePressMoveReleaseOnNoCaret) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressMoveReleaseOnNoCaret(CreateMousePressEvent, CreateMouseMoveEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchPressMoveReleaseOnNoCaret) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressMoveReleaseOnNoCaret(CreateTouchStartEvent, CreateTouchMoveEvent, CreateTouchEndEvent); } template void AccessibleCaretEventHubTester::TestPressMoveReleaseOnNoCaret( PressEventCreator aPressEventCreator, MoveEventCreator aMoveEventCreator, ReleaseEventCreator aReleaseEventCreator) { nscoord x0 = 0, y0 = 0; nscoord x1 = 100, y1 = 100; nscoord x2 = 300, y2 = 300; nscoord x3 = 400, y3 = 400; { InSequence dummy; EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _)) .WillOnce(Return(NS_ERROR_FAILURE)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), DragCaret(_)).Times(0); } HandleEventAndCheckState(aPressEventCreator(x0, y0), MockAccessibleCaretEventHub::PressNoCaretState(), nsEventStatus_eIgnore); // A small move with the distance between (x0, y0) and (x1, y1) below the // tolerance value. HandleEventAndCheckState(aMoveEventCreator(x1, y1), MockAccessibleCaretEventHub::PressNoCaretState(), nsEventStatus_eIgnore); // A large move to simulate a dragging to select text since the distance // between (x0, y0) and (x2, y2) is above the tolerance value. HandleEventAndCheckState(aMoveEventCreator(x2, y2), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); HandleEventAndCheckState(aReleaseEventCreator(x3, y3), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); } TEST_F(AccessibleCaretEventHubTester, TestMousePressMoveReleaseOnCaret) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressMoveReleaseOnCaret(CreateMousePressEvent, CreateMouseMoveEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchPressMoveReleaseOnCaret) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestPressMoveReleaseOnCaret(CreateTouchStartEvent, CreateTouchMoveEvent, CreateTouchEndEvent); } template void AccessibleCaretEventHubTester::TestPressMoveReleaseOnCaret( PressEventCreator aPressEventCreator, MoveEventCreator aMoveEventCreator, ReleaseEventCreator aReleaseEventCreator) { nscoord x0 = 0, y0 = 0; nscoord x1 = 100, y1 = 100; nscoord x2 = 300, y2 = 300; nscoord x3 = 400, y3 = 400; { InSequence dummy; EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _)) .WillOnce(Return(NS_OK)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), DragCaret(_)) .Times(2) // two valid drag operations .WillRepeatedly(Return(NS_OK)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), ReleaseCaret()) .WillOnce(Return(NS_OK)); } HandleEventAndCheckState(aPressEventCreator(x0, y0), MockAccessibleCaretEventHub::PressCaretState(), nsEventStatus_eConsumeNoDefault); // A small move with the distance between (x0, y0) and (x1, y1) below the // tolerance value. HandleEventAndCheckState(aMoveEventCreator(x1, y1), MockAccessibleCaretEventHub::PressCaretState(), nsEventStatus_eConsumeNoDefault); // A large move forms a valid drag since the distance between (x0, y0) and // (x2, y2) is above the tolerance value. HandleEventAndCheckState(aMoveEventCreator(x2, y2), MockAccessibleCaretEventHub::DragCaretState(), nsEventStatus_eConsumeNoDefault); // Also a valid drag since the distance between (x0, y0) and (x3, y3) above // the tolerance value even if the distance between (x2, y2) and (x3, y3) is // below the tolerance value. HandleEventAndCheckState(aMoveEventCreator(x3, y3), MockAccessibleCaretEventHub::DragCaretState(), nsEventStatus_eConsumeNoDefault); HandleEventAndCheckState(aReleaseEventCreator(x3, y3), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eConsumeNoDefault); } TEST_F(AccessibleCaretEventHubTester, TestTouchStartMoveEndOnCaretWithTouchCancelIgnored) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { nscoord x0 = 0, y0 = 0; nscoord x1 = 100, y1 = 100; nscoord x2 = 300, y2 = 300; nscoord x3 = 400, y3 = 400; { InSequence dummy; EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _)) .WillOnce(Return(NS_OK)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), DragCaret(_)) .WillOnce(Return(NS_OK)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), ReleaseCaret()) .WillOnce(Return(NS_OK)); } // All the eTouchCancel events should be ignored in this test. HandleEventAndCheckState(CreateTouchStartEvent(x0, y0), MockAccessibleCaretEventHub::PressCaretState(), nsEventStatus_eConsumeNoDefault); HandleEventAndCheckState(CreateTouchCancelEvent(x0, y0), MockAccessibleCaretEventHub::PressCaretState(), nsEventStatus_eIgnore); // A small move with the distance between (x0, y0) and (x1, y1) below the // tolerance value. HandleEventAndCheckState(CreateTouchMoveEvent(x1, y1), MockAccessibleCaretEventHub::PressCaretState(), nsEventStatus_eConsumeNoDefault); HandleEventAndCheckState(CreateTouchCancelEvent(x1, y1), MockAccessibleCaretEventHub::PressCaretState(), nsEventStatus_eIgnore); // A large move forms a valid drag since the distance between (x0, y0) and // (x2, y2) is above the tolerance value. HandleEventAndCheckState(CreateTouchMoveEvent(x2, y2), MockAccessibleCaretEventHub::DragCaretState(), nsEventStatus_eConsumeNoDefault); HandleEventAndCheckState(CreateTouchCancelEvent(x2, y2), MockAccessibleCaretEventHub::DragCaretState(), nsEventStatus_eIgnore); HandleEventAndCheckState(CreateTouchEndEvent(x3, y3), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eConsumeNoDefault); HandleEventAndCheckState(CreateTouchCancelEvent(x3, y3), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); } TEST_F(AccessibleCaretEventHubTester, TestMouseLongTapWithSelectWordSuccessful) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestLongTapWithSelectWordSuccessful(CreateMousePressEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchLongTapWithSelectWordSuccessful) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestLongTapWithSelectWordSuccessful(CreateTouchStartEvent, CreateTouchEndEvent); } template void AccessibleCaretEventHubTester::TestLongTapWithSelectWordSuccessful( PressEventCreator aPressEventCreator, ReleaseEventCreator aReleaseEventCreator) { MockFunction check; { InSequence dummy; EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _)) .WillOnce(Return(NS_ERROR_FAILURE)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), SelectWordOrShortcut(_)) .WillOnce(Return(NS_OK)); EXPECT_CALL(check, Call("longtap with scrolling")); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _)) .WillOnce(Return(NS_ERROR_FAILURE)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), SelectWordOrShortcut(_)) .WillOnce(Return(NS_OK)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd()); } // Test long tap without scrolling. HandleEventAndCheckState(aPressEventCreator(0, 0), MockAccessibleCaretEventHub::PressNoCaretState(), nsEventStatus_eIgnore); HandleEventAndCheckState(CreateLongTapEvent(0, 0), MockAccessibleCaretEventHub::LongTapState(), nsEventStatus_eIgnore); HandleEventAndCheckState(aReleaseEventCreator(0, 0), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); // On Fennec, after long tap, the script might scroll and zoom the input field // to the center of the screen to make typing easier before the user lifts the // finger. check.Call("longtap with scrolling"); HandleEventAndCheckState(aPressEventCreator(1, 1), MockAccessibleCaretEventHub::PressNoCaretState(), nsEventStatus_eIgnore); HandleEventAndCheckState(CreateLongTapEvent(1, 1), MockAccessibleCaretEventHub::LongTapState(), nsEventStatus_eIgnore); RefPtr hub(mHub); hub->AsyncPanZoomStarted(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); hub->ScrollPositionChanged(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); hub->AsyncPanZoomStopped(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::NoActionState()); HandleEventAndCheckState(aReleaseEventCreator(1, 1), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); } TEST_F(AccessibleCaretEventHubTester, TestMouseLongTapWithSelectWordFailed) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestLongTapWithSelectWordFailed(CreateMousePressEvent, CreateMouseReleaseEvent); } TEST_F(AccessibleCaretEventHubTester, TestTouchLongTapWithSelectWordFailed) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestLongTapWithSelectWordFailed(CreateTouchStartEvent, CreateTouchEndEvent); } template void AccessibleCaretEventHubTester::TestLongTapWithSelectWordFailed( PressEventCreator aPressEventCreator, ReleaseEventCreator aReleaseEventCreator) { { InSequence dummy; EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _)) .WillOnce(Return(NS_ERROR_FAILURE)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), SelectWordOrShortcut(_)) .WillOnce(Return(NS_ERROR_FAILURE)); } HandleEventAndCheckState(aPressEventCreator(0, 0), MockAccessibleCaretEventHub::PressNoCaretState(), nsEventStatus_eIgnore); HandleEventAndCheckState(CreateLongTapEvent(0, 0), MockAccessibleCaretEventHub::LongTapState(), nsEventStatus_eIgnore); HandleEventAndCheckState(aReleaseEventCreator(0, 0), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); } TEST_F(AccessibleCaretEventHubTester, TestTouchEventDrivenAsyncPanZoomScroll) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestEventDrivenAsyncPanZoomScroll(CreateTouchStartEvent, CreateTouchMoveEvent, CreateTouchEndEvent); } TEST_F(AccessibleCaretEventHubTester, TestMouseEventDrivenAsyncPanZoomScroll) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestEventDrivenAsyncPanZoomScroll(CreateMousePressEvent, CreateMouseMoveEvent, CreateMouseReleaseEvent); } template void AccessibleCaretEventHubTester::TestEventDrivenAsyncPanZoomScroll( PressEventCreator aPressEventCreator, MoveEventCreator aMoveEventCreator, ReleaseEventCreator aReleaseEventCreator) { MockFunction check; { InSequence dummy; EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _)) .WillOnce(Return(NS_ERROR_FAILURE)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), DragCaret(_)).Times(0); EXPECT_CALL(check, Call("1")); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd()); EXPECT_CALL(check, Call("2")); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _)) .WillOnce(Return(NS_ERROR_FAILURE)); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), DragCaret(_)).Times(0); EXPECT_CALL(check, Call("3")); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd()); } // Receive press event. HandleEventAndCheckState(aPressEventCreator(0, 0), MockAccessibleCaretEventHub::PressNoCaretState(), nsEventStatus_eIgnore); HandleEventAndCheckState(aMoveEventCreator(100, 100), MockAccessibleCaretEventHub::PressNoCaretState(), nsEventStatus_eIgnore); check.Call("1"); // Event driven scroll started RefPtr hub(mHub); hub->AsyncPanZoomStarted(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); HandleEventAndCheckState(aMoveEventCreator(160, 160), MockAccessibleCaretEventHub::ScrollState(), nsEventStatus_eIgnore); hub->ScrollPositionChanged(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); // Event driven scroll ended hub->AsyncPanZoomStopped(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::NoActionState()); HandleEventAndCheckState(aReleaseEventCreator(210, 210), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); check.Call("2"); // Receive another press event. HandleEventAndCheckState(aPressEventCreator(220, 220), MockAccessibleCaretEventHub::PressNoCaretState(), nsEventStatus_eIgnore); HandleEventAndCheckState(aMoveEventCreator(230, 230), MockAccessibleCaretEventHub::PressNoCaretState(), nsEventStatus_eIgnore); check.Call("3"); // Another APZ scroll started hub->AsyncPanZoomStarted(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); hub->ScrollPositionChanged(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); // Another APZ scroll ended hub->AsyncPanZoomStopped(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::NoActionState()); HandleEventAndCheckState(aReleaseEventCreator(310, 310), MockAccessibleCaretEventHub::NoActionState(), nsEventStatus_eIgnore); } TEST_F(AccessibleCaretEventHubTester, TestAsyncPanZoomScroll) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { TestAsyncPanZoomScroll(); } void AccessibleCaretEventHubTester::TestAsyncPanZoomScroll() { MockFunction check; { InSequence dummy; EXPECT_CALL(check, Call("1")); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollPositionChanged()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd()); EXPECT_CALL(check, Call("2")); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollPositionChanged()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd()); } // First APZ scrolling. check.Call("1"); RefPtr hub(mHub); hub->AsyncPanZoomStarted(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); hub->ScrollPositionChanged(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); hub->AsyncPanZoomStopped(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::NoActionState()); // Second APZ scrolling. check.Call("2"); hub->AsyncPanZoomStarted(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); hub->ScrollPositionChanged(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); hub->AsyncPanZoomStopped(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::NoActionState()); } TEST_F(AccessibleCaretEventHubTester, TestAsyncPanZoomScrollStartedThenBlur) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { { InSequence dummy; EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd()).Times(0); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnBlur()); } RefPtr hub(mHub); hub->AsyncPanZoomStarted(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); hub->ScrollPositionChanged(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); hub->NotifyBlur(true); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::NoActionState()); } TEST_F(AccessibleCaretEventHubTester, TestAsyncPanZoomScrollEndedThenBlur) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { { InSequence dummy; EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd()); EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnBlur()); } RefPtr hub(mHub); hub->AsyncPanZoomStarted(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); hub->ScrollPositionChanged(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::ScrollState()); hub->AsyncPanZoomStopped(); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::NoActionState()); hub->NotifyBlur(true); EXPECT_EQ(hub->GetState(), MockAccessibleCaretEventHub::NoActionState()); } } // namespace mozilla