| // Copyright 2013 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. |
| |
| #import "chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h" |
| |
| #include "base/mac/scoped_nsobject.h" |
| #import "base/mac/sdk_forward_declarations.h" |
| #import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/platform/web_input_event.h" |
| #include "third_party/blink/public/platform/web_mouse_wheel_event.h" |
| #import "third_party/ocmock/OCMock/OCMock.h" |
| #import "third_party/ocmock/ocmock_extensions.h" |
| #include "ui/events/blink/did_overscroll_params.h" |
| |
| @interface HistorySwiper (MacHistorySwiperTest) |
| - (BOOL)systemSettingsAllowHistorySwiping:(NSEvent*)event; |
| - (BOOL)browserCanNavigateInDirection: |
| (history_swiper::NavigationDirection)forward |
| event:(NSEvent*)event; |
| - (void)removeHistoryOverlay; |
| - (void)showHistoryOverlay:(history_swiper::NavigationDirection)direction; |
| - (void)navigateBrowserInDirection:(history_swiper::NavigationDirection)forward; |
| - (void)initiateMagicMouseHistorySwipe:(BOOL)isRightScroll |
| event:(NSEvent*)event; |
| @end |
| |
| class MacHistorySwiperTest : public CocoaTest { |
| public: |
| void SetUp() override { |
| CocoaTest::SetUp(); |
| |
| [HistorySwiper resetMagicMouseState]; |
| |
| view_ = [[NSView alloc] init]; |
| id mockDelegate = |
| [OCMockObject mockForProtocol:@protocol(HistorySwiperDelegate)]; |
| [[[mockDelegate stub] andReturn:view_] viewThatWantsHistoryOverlay]; |
| [[[mockDelegate stub] andReturnBool:YES] shouldAllowHistorySwiping]; |
| |
| base::scoped_nsobject<HistorySwiper> historySwiper( |
| [[HistorySwiper alloc] initWithDelegate:mockDelegate]); |
| id mockHistorySwiper = [OCMockObject partialMockForObject:historySwiper]; |
| [[[mockHistorySwiper stub] andReturnBool:YES] |
| systemSettingsAllowHistorySwiping:[OCMArg any]]; |
| [[[mockHistorySwiper stub] andReturnBool:YES] |
| browserCanNavigateInDirection:history_swiper::kForwards |
| event:[OCMArg any]]; |
| [[[mockHistorySwiper stub] andReturnBool:YES] |
| browserCanNavigateInDirection:history_swiper::kBackwards |
| event:[OCMArg any]]; |
| [[[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) { |
| ++begin_count_; |
| // showHistoryOverlay: calls removeHistoryOverlay internally. |
| --end_count_; |
| }] andForwardToRealObject] showHistoryOverlay:history_swiper::kForwards]; |
| [[[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) { |
| ++begin_count_; |
| // showHistoryOverlay: calls removeHistoryOverlay internally. |
| --end_count_; |
| }] andForwardToRealObject] showHistoryOverlay:history_swiper::kBackwards]; |
| [[[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) { |
| ++end_count_; |
| }] andForwardToRealObject] removeHistoryOverlay]; |
| [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) { |
| navigated_right_ = true; |
| }] navigateBrowserInDirection:history_swiper::kForwards]; |
| [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) { |
| navigated_left_ = true; |
| }] navigateBrowserInDirection:history_swiper::kBackwards]; |
| |
| [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) { |
| magic_mouse_history_swipe_ = true; |
| }] initiateMagicMouseHistorySwipe:YES event:[OCMArg any]]; |
| [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) { |
| magic_mouse_history_swipe_ = true; |
| }] initiateMagicMouseHistorySwipe:NO event:[OCMArg any]]; |
| |
| historySwiper_ = [mockHistorySwiper retain]; |
| |
| begin_count_ = 0; |
| end_count_ = 0; |
| navigated_right_ = false; |
| navigated_left_ = false; |
| magic_mouse_history_swipe_ = false; |
| } |
| |
| void TearDown() override { |
| [view_ release]; |
| [historySwiper_ release]; |
| CocoaTest::TearDown(); |
| } |
| |
| // These methods send all 3 types of events: gesture, scroll, and touch. |
| void startGestureInMiddle(); |
| void moveGestureInMiddle(); |
| void moveGestureAtPoint(NSPoint point); |
| void momentumMoveGestureAtPoint(NSPoint point); |
| void endGestureAtPoint(NSPoint point); |
| void rendererACKForBeganEvent(); |
| void onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType); |
| |
| // These methods send a single type of event. |
| void sendBeginGestureEventInMiddle(); |
| void sendEndGestureEventAtPoint(NSPoint point); |
| |
| HistorySwiper* historySwiper_; |
| NSView* view_; |
| int begin_count_; |
| int end_count_; |
| bool navigated_right_; |
| bool navigated_left_; |
| bool magic_mouse_history_swipe_; |
| }; |
| |
| NSPoint makePoint(CGFloat x, CGFloat y) { |
| NSPoint point; |
| point.x = x; |
| point.y = y; |
| return point; |
| } |
| |
| id mockEventWithPoint(NSPoint point, NSEventType type) { |
| id mockEvent = [OCMockObject mockForClass:[NSEvent class]]; |
| id mockTouch = [OCMockObject mockForClass:[NSTouch class]]; |
| [[[mockTouch stub] andReturnNSPoint:point] normalizedPosition]; |
| NSArray* touches = @[mockTouch]; |
| [[[mockEvent stub] andReturn:touches] touchesMatchingPhase:NSTouchPhaseAny |
| inView:[OCMArg any]]; |
| [[[mockEvent stub] andReturnBool:NO] isDirectionInvertedFromDevice]; |
| [(NSEvent*)[[mockEvent stub] andReturnValue:OCMOCK_VALUE(type)] type]; |
| |
| return mockEvent; |
| } |
| |
| id scrollWheelEventWithPhase(NSEventPhase phase, |
| NSEventPhase momentumPhase, |
| CGFloat scrollingDeltaX, |
| CGFloat scrollingDeltaY) { |
| // The point isn't used, so we pass in bogus data. |
| id event = mockEventWithPoint(makePoint(0,0), NSScrollWheel); |
| [(NSEvent*)[[event stub] andReturnValue:OCMOCK_VALUE(phase)] phase]; |
| [(NSEvent*) |
| [[event stub] andReturnValue:OCMOCK_VALUE(momentumPhase)] momentumPhase]; |
| [(NSEvent*)[[event stub] |
| andReturnValue:OCMOCK_VALUE(scrollingDeltaX)] scrollingDeltaX]; |
| [(NSEvent*)[[event stub] |
| andReturnValue:OCMOCK_VALUE(scrollingDeltaY)] scrollingDeltaY]; |
| return event; |
| } |
| |
| id scrollWheelEventWithPhase(NSEventPhase phase, |
| NSEventPhase momentumPhase) { |
| return scrollWheelEventWithPhase(phase, momentumPhase, 0, 0); |
| } |
| |
| id scrollWheelEventWithPhase(NSEventPhase phase) { |
| return scrollWheelEventWithPhase(phase, NSEventPhaseNone); |
| } |
| |
| void MacHistorySwiperTest::startGestureInMiddle() { |
| NSEvent* event = mockEventWithPoint(makePoint(0.5, 0.5), NSEventTypeGesture); |
| [historySwiper_ touchesBeganWithEvent:event]; |
| [historySwiper_ beginGestureWithEvent:event]; |
| NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseBegan); |
| [historySwiper_ handleEvent:scrollEvent]; |
| } |
| |
| void MacHistorySwiperTest::moveGestureInMiddle() { |
| moveGestureAtPoint(makePoint(0.5, 0.5)); |
| |
| // Callbacks from blink to set the relevant state for history swiping. |
| rendererACKForBeganEvent(); |
| } |
| |
| void MacHistorySwiperTest::moveGestureAtPoint(NSPoint point) { |
| NSEvent* event = mockEventWithPoint(point, NSEventTypeGesture); |
| [historySwiper_ touchesMovedWithEvent:event]; |
| |
| NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseChanged); |
| [historySwiper_ handleEvent:scrollEvent]; |
| } |
| |
| void MacHistorySwiperTest::momentumMoveGestureAtPoint(NSPoint point) { |
| NSEvent* event = mockEventWithPoint(point, NSEventTypeGesture); |
| [historySwiper_ touchesMovedWithEvent:event]; |
| |
| NSEvent* scrollEvent = |
| scrollWheelEventWithPhase(NSEventPhaseNone, NSEventPhaseChanged); |
| [historySwiper_ handleEvent:scrollEvent]; |
| } |
| |
| void MacHistorySwiperTest::endGestureAtPoint(NSPoint point) { |
| NSEvent* event = mockEventWithPoint(point, NSEventTypeGesture); |
| [historySwiper_ touchesEndedWithEvent:event]; |
| |
| NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseEnded); |
| [historySwiper_ handleEvent:scrollEvent]; |
| |
| sendEndGestureEventAtPoint(point); |
| } |
| |
| void MacHistorySwiperTest::onOverscrolled( |
| cc::OverscrollBehavior::OverscrollBehaviorType behavior) { |
| ui::DidOverscrollParams params; |
| params.overscroll_behavior.x = behavior; |
| [historySwiper_ onOverscrolled:params]; |
| } |
| |
| void MacHistorySwiperTest::rendererACKForBeganEvent() { |
| blink::WebMouseWheelEvent event; |
| event.phase = blink::WebMouseWheelEvent::kPhaseBegan; |
| [historySwiper_ rendererHandledWheelEvent:event consumed:NO]; |
| } |
| |
| void MacHistorySwiperTest::sendBeginGestureEventInMiddle() { |
| NSEvent* event = mockEventWithPoint(makePoint(0.5, 0.5), NSEventTypeGesture); |
| [historySwiper_ beginGestureWithEvent:event]; |
| } |
| |
| void MacHistorySwiperTest::sendEndGestureEventAtPoint(NSPoint point) { |
| NSEvent* event = mockEventWithPoint(point, NSEventTypeGesture); |
| [historySwiper_ endGestureWithEvent:event]; |
| } |
| |
| // Test that a simple left-swipe causes navigation. |
| TEST_F(MacHistorySwiperTest, SwipeLeft) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| startGestureInMiddle(); |
| moveGestureInMiddle(); |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| |
| moveGestureAtPoint(makePoint(0.2, 0.5)); |
| EXPECT_EQ(begin_count_, 1); |
| EXPECT_EQ(end_count_, 0); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| |
| endGestureAtPoint(makePoint(0.2, 0.5)); |
| EXPECT_EQ(begin_count_, 1); |
| EXPECT_EQ(end_count_, 1); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_TRUE(navigated_left_); |
| } |
| |
| // Test that a simple right-swipe causes navigation. |
| TEST_F(MacHistorySwiperTest, SwipeRight) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| startGestureInMiddle(); |
| moveGestureInMiddle(); |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| |
| moveGestureAtPoint(makePoint(0.8, 0.5)); |
| EXPECT_EQ(begin_count_, 1); |
| EXPECT_EQ(end_count_, 0); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| |
| endGestureAtPoint(makePoint(0.8, 0.5)); |
| EXPECT_EQ(begin_count_, 1); |
| EXPECT_EQ(end_count_, 1); |
| EXPECT_TRUE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| } |
| |
| // If the user doesn't swipe enough, the history swiper should begin, but the |
| // browser should not navigate. |
| TEST_F(MacHistorySwiperTest, SwipeLeftSmallAmount) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| startGestureInMiddle(); |
| moveGestureInMiddle(); |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| moveGestureAtPoint(makePoint(0.45, 0.5)); |
| endGestureAtPoint(makePoint(0.45, 0.5)); |
| EXPECT_EQ(begin_count_, 1); |
| EXPECT_EQ(end_count_, 1); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| } |
| |
| // Diagonal swipes with a slight horizontal bias should not start the history |
| // swiper. |
| TEST_F(MacHistorySwiperTest, SwipeDiagonal) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| startGestureInMiddle(); |
| moveGestureInMiddle(); |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| moveGestureInMiddle(); |
| moveGestureAtPoint(makePoint(0.6, 0.59)); |
| endGestureAtPoint(makePoint(0.6, 0.59)); |
| |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 1); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| } |
| |
| // Swiping left and then down should cancel the history swiper without |
| // navigating. |
| TEST_F(MacHistorySwiperTest, SwipeLeftThenDown) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| startGestureInMiddle(); |
| moveGestureInMiddle(); |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| moveGestureAtPoint(makePoint(0.4, 0.5)); |
| moveGestureAtPoint(makePoint(0.4, 0.3)); |
| endGestureAtPoint(makePoint(0.2, 0.2)); |
| EXPECT_EQ(begin_count_, 1); |
| EXPECT_EQ(end_count_, 1); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| } |
| |
| // Sometimes Cocoa gets confused and sends us a momentum swipe event instead of |
| // a swipe gesture event. Momentum events should not cause history swiping. |
| TEST_F(MacHistorySwiperTest, MomentumSwipeLeft) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| startGestureInMiddle(); |
| |
| // Send a momentum move gesture. |
| momentumMoveGestureAtPoint(makePoint(0.5, 0.5)); |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| |
| // Callbacks from blink to set the relevant state for history swiping. |
| rendererACKForBeganEvent(); |
| |
| momentumMoveGestureAtPoint(makePoint(0.2, 0.5)); |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| |
| endGestureAtPoint(makePoint(0.2, 0.5)); |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| } |
| |
| // Momentum scroll events for magic mouse should not attempt to trigger the |
| // `trackSwipeEventWithOptions:` api, as that throws an exception. |
| TEST_F(MacHistorySwiperTest, MagicMouseMomentumSwipe) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| // Magic mouse events don't generate 'touches*' callbacks. |
| NSEvent* event = mockEventWithPoint(makePoint(0.5, 0.5), NSEventTypeGesture); |
| [historySwiper_ beginGestureWithEvent:event]; |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseBegan); |
| [historySwiper_ handleEvent:scrollEvent]; |
| |
| // Callbacks from blink to set the relevant state for history swiping. |
| rendererACKForBeganEvent(); |
| |
| // Send a momentum move gesture. |
| scrollEvent = |
| scrollWheelEventWithPhase(NSEventPhaseNone, NSEventPhaseChanged, 5.0, 0); |
| [historySwiper_ handleEvent:scrollEvent]; |
| |
| EXPECT_FALSE(magic_mouse_history_swipe_); |
| } |
| |
| // User starts a swipe but doesn't move. |
| TEST_F(MacHistorySwiperTest, NoSwipe) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| startGestureInMiddle(); |
| moveGestureInMiddle(); |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| |
| // Starts the gesture. |
| moveGestureAtPoint(makePoint(0.44, 0.44)); |
| |
| // No movement. |
| endGestureAtPoint(makePoint(0.44, 0.44)); |
| |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 1); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| } |
| |
| // After a gesture is successfully recognized, momentum events should be |
| // swallowed, but new events should pass through. |
| TEST_F(MacHistorySwiperTest, TouchEventAfterGestureFinishes) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| // Successfully pass through a gesture. |
| startGestureInMiddle(); |
| moveGestureInMiddle(); |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| moveGestureAtPoint(makePoint(0.8, 0.5)); |
| endGestureAtPoint(makePoint(0.8, 0.5)); |
| EXPECT_TRUE(navigated_right_); |
| |
| // Momentum events should be swallowed. |
| NSEvent* momentumEvent = scrollWheelEventWithPhase(NSEventPhaseNone, |
| NSEventPhaseChanged); |
| EXPECT_TRUE([historySwiper_ handleEvent:momentumEvent]); |
| |
| // New events should not be swallowed. |
| NSEvent* beganEvent = scrollWheelEventWithPhase(NSEventPhaseBegan); |
| EXPECT_FALSE([historySwiper_ handleEvent:beganEvent]); |
| } |
| |
| // The history swipe logic should be resilient against the timing of the |
| // different callbacks that result from scrolling. |
| TEST_F(MacHistorySwiperTest, SwipeRightEventOrdering) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| // Touches began. |
| NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseBegan); |
| NSEvent* event = mockEventWithPoint(makePoint(0.5, 0.5), NSEventTypeGesture); |
| [historySwiper_ touchesBeganWithEvent:event]; |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| [historySwiper_ handleEvent:scrollEvent]; |
| rendererACKForBeganEvent(); |
| |
| // Touches moved. |
| moveGestureAtPoint(makePoint(0.5, 0.5)); |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| |
| // Touches moved. |
| moveGestureAtPoint(makePoint(0.52, 0.5)); |
| |
| // Begin gesture callback is delayed. |
| [historySwiper_ beginGestureWithEvent:event]; |
| |
| // Touches moved. |
| moveGestureAtPoint(makePoint(0.52, 0.5)); |
| |
| // Complete the rest of the gesture. |
| moveGestureAtPoint(makePoint(0.60, 0.5)); |
| scrollEvent = scrollWheelEventWithPhase(NSEventPhaseChanged); |
| [historySwiper_ handleEvent:scrollEvent]; |
| endGestureAtPoint(makePoint(0.70, 0.5)); |
| |
| EXPECT_EQ(begin_count_, 1); |
| EXPECT_EQ(end_count_, 1); |
| EXPECT_TRUE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| } |
| |
| // Substantial vertical scrolling followed by horizontal scrolling should not |
| // result in navigation. |
| TEST_F(MacHistorySwiperTest, SubstantialVerticalThenHorizontal) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| startGestureInMiddle(); |
| moveGestureInMiddle(); |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| |
| // Move up, then move down. |
| for (CGFloat y = 0.51; y < 0.6; y += 0.01) |
| moveGestureAtPoint(makePoint(0.5, y)); |
| for (CGFloat y = 0.59; y > 0.5; y -= 0.01) |
| moveGestureAtPoint(makePoint(0.5, y)); |
| |
| // Large movement to the right. |
| moveGestureAtPoint(makePoint(0.6, 0.51)); |
| endGestureAtPoint(makePoint(0.6, 0.51)); |
| |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 1); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| } |
| |
| // Magic Mouse gestures don't send -touches*WithEvent: callbacks. The history |
| // swiper should still handle this gracefully. It should not turn vertical |
| // motion into history swipes. |
| TEST_F(MacHistorySwiperTest, MagicMouseStateResetsCorrectly) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| // Magic mouse events don't generate '-touches*WithEvent:' callbacks. |
| // Send the following events: |
| // - beginGesture |
| // - scrollWheel: (phase=Began) |
| // - scrollWheel: (phase=Changed), significant horizontal motion. |
| // - scrollWheel: (phase=Ended) |
| // - endGesture |
| sendBeginGestureEventInMiddle(); |
| [historySwiper_ handleEvent:scrollWheelEventWithPhase(NSEventPhaseBegan)]; |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeAuto); |
| |
| // Callback from Blink to set the relevant state for history swiping. |
| rendererACKForBeganEvent(); |
| |
| NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseChanged, |
| NSEventPhaseNone, 200.0, 0); |
| [historySwiper_ handleEvent:scrollEvent]; |
| [historySwiper_ handleEvent:scrollWheelEventWithPhase(NSEventPhaseEnded)]; |
| sendEndGestureEventAtPoint(makePoint(0.7, 0.5)); |
| |
| // Expect this sequence of events to trigger a magic mouse history swipe. |
| EXPECT_TRUE(magic_mouse_history_swipe_); |
| |
| // Reset state. |
| magic_mouse_history_swipe_ = false; |
| |
| // Send the following events: |
| // - beginGesture |
| // - scrollWheel: (phase=Began) |
| // - scrollWheel: (phase=Changed), significant vertical motion. |
| // - scrollWheel: (phase=Ended) |
| // - endGesture |
| sendBeginGestureEventInMiddle(); |
| [historySwiper_ handleEvent:scrollWheelEventWithPhase(NSEventPhaseBegan)]; |
| |
| // Callback from Blink to set the relevant state for history swiping. |
| rendererACKForBeganEvent(); |
| |
| scrollEvent = |
| scrollWheelEventWithPhase(NSEventPhaseChanged, NSEventPhaseNone, 0, 20); |
| [historySwiper_ handleEvent:scrollEvent]; |
| [historySwiper_ handleEvent:scrollWheelEventWithPhase(NSEventPhaseEnded)]; |
| sendEndGestureEventAtPoint(makePoint(0.5, 0.7)); |
| |
| // Vertical motion should never trigger a history swipe! |
| EXPECT_FALSE(magic_mouse_history_swipe_); |
| } |
| |
| // With overscroll-behavior value as contain, the page should not navigate, |
| // nor should the history overlay appear. |
| TEST_F(MacHistorySwiperTest, OverscrollBehaviorContainPreventsNavigation) { |
| // These tests require 10.7+ APIs. |
| if (![NSEvent |
| respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)]) |
| return; |
| |
| startGestureInMiddle(); |
| moveGestureInMiddle(); |
| |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeContain); |
| moveGestureAtPoint(makePoint(0.2, 0.5)); |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| |
| endGestureAtPoint(makePoint(0.2, 0.5)); |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| } |
| |
| // With overscroll-behavior value as none, the page should not navigate, |
| // nor should the history overlay appear. |
| TEST_F(MacHistorySwiperTest, OverscrollBehaviorNonePreventsNavigation) { |
| startGestureInMiddle(); |
| moveGestureInMiddle(); |
| |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| |
| onOverscrolled(cc::OverscrollBehavior::OverscrollBehaviorType:: |
| kOverscrollBehaviorTypeNone); |
| moveGestureAtPoint(makePoint(0.2, 0.5)); |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| |
| endGestureAtPoint(makePoint(0.2, 0.5)); |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| } |
| |
| // Without overscroll msg from renderer, the page should not navigate, nor |
| // should the history overlay appear. |
| TEST_F(MacHistorySwiperTest, NoNavigationWithoutOverscrollMsg) { |
| startGestureInMiddle(); |
| moveGestureInMiddle(); |
| |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| |
| moveGestureAtPoint(makePoint(0.2, 0.5)); |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| |
| endGestureAtPoint(makePoint(0.2, 0.5)); |
| EXPECT_EQ(begin_count_, 0); |
| EXPECT_EQ(end_count_, 0); |
| EXPECT_FALSE(navigated_right_); |
| EXPECT_FALSE(navigated_left_); |
| } |