chrome_render_widget_host_view_mac_history_swiper_unit_test.mm revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/scoped_nsobject.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "base/mac/sdk_forward_declarations.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "third_party/ocmock/OCMock/OCMock.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "third_party/ocmock/ocmock_extensions.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@interface HistorySwiper (MacHistorySwiperTest)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)systemSettingsAllowHistorySwiping:(NSEvent*)event;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)browserCanNavigateInDirection:
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (history_swiper::NavigationDirection)forward
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                event:(NSEvent*)event;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)endHistorySwipe;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)beginHistorySwipeInDirection:
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (history_swiper::NavigationDirection)goForward
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               event:(NSEvent*)event;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)navigateBrowserInDirection:(history_swiper::NavigationDirection)forward;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)initiateMagicMouseHistorySwipe:(BOOL)isRightScroll
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 event:(NSEvent*)event;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MacHistorySwiperTest : public CocoaTest {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CocoaTest::SetUp();
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [HistorySwiper resetMagicMouseState];
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_ = [[NSView alloc] init];
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    id mockDelegate =
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        [OCMockObject mockForProtocol:@protocol(HistorySwiperDelegate)];
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[mockDelegate stub] andReturn:view_] viewThatWantsHistoryOverlay];
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[mockDelegate stub] andReturnBool:YES] shouldAllowHistorySwiping];
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::scoped_nsobject<HistorySwiper> historySwiper(
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        [[HistorySwiper alloc] initWithDelegate:mockDelegate]);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    id mockHistorySwiper = [OCMockObject partialMockForObject:historySwiper];
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[mockHistorySwiper stub] andReturnBool:YES]
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        systemSettingsAllowHistorySwiping:[OCMArg any]];
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[mockHistorySwiper stub] andReturnBool:YES]
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browserCanNavigateInDirection:history_swiper::kForwards
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                event:[OCMArg any]];
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[mockHistorySwiper stub] andReturnBool:YES]
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browserCanNavigateInDirection:history_swiper::kBackwards
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                event:[OCMArg any]];
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++begin_count_;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // beginHistorySwipeInDirection: calls endHistorySwipe internally.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      --end_count_;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }] andForwardToRealObject]
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        beginHistorySwipeInDirection:history_swiper::kForwards
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               event:[OCMArg any]];
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++begin_count_;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // beginHistorySwipeInDirection: calls endHistorySwipe internally.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      --end_count_;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }] andForwardToRealObject]
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        beginHistorySwipeInDirection:history_swiper::kBackwards
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               event:[OCMArg any]];
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++end_count_;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }] andForwardToRealObject] endHistorySwipe];
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        navigated_right_ = true;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }] navigateBrowserInDirection:history_swiper::kForwards];
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        navigated_left_ = true;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }] navigateBrowserInDirection:history_swiper::kBackwards];
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        magic_mouse_history_swipe_ = true;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }] initiateMagicMouseHistorySwipe:YES event:[OCMArg any]];
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        magic_mouse_history_swipe_ = true;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }] initiateMagicMouseHistorySwipe:NO event:[OCMArg any]];
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    historySwiper_ = [mockHistorySwiper retain];
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    begin_count_ = 0;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    end_count_ = 0;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    navigated_right_ = false;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    navigated_left_ = false;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    magic_mouse_history_swipe_ = false;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [view_ release];
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [historySwiper_ release];
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CocoaTest::TearDown();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void startGestureInMiddle();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void moveGestureInMiddle();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void moveGestureAtPoint(NSPoint point);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void momentumMoveGestureAtPoint(NSPoint point);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void endGestureAtPoint(NSPoint point);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HistorySwiper* historySwiper_;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSView* view_;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int begin_count_;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int end_count_;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool navigated_right_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool navigated_left_;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool magic_mouse_history_swipe_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSPoint makePoint(CGFloat x, CGFloat y) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSPoint point;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  point.x = x;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  point.y = y;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return point;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)id mockEventWithPoint(NSPoint point, NSEventType type) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id mockEvent = [OCMockObject mockForClass:[NSEvent class]];
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id mockTouch = [OCMockObject mockForClass:[NSTouch class]];
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [[[mockTouch stub] andReturnNSPoint:point] normalizedPosition];
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSArray* touches = @[mockTouch];
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [[[mockEvent stub] andReturn:touches] touchesMatchingPhase:NSTouchPhaseAny
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inView:[OCMArg any]];
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [[[mockEvent stub] andReturnBool:NO] isDirectionInvertedFromDevice];
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [(NSEvent*)[[mockEvent stub] andReturnValue:OCMOCK_VALUE(type)] type];
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return mockEvent;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)id scrollWheelEventWithPhase(NSEventPhase phase,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             NSEventPhase momentumPhase,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             CGFloat scrollingDeltaX,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             CGFloat scrollingDeltaY) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The point isn't used, so we pass in bogus data.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id event = mockEventWithPoint(makePoint(0,0), NSScrollWheel);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [(NSEvent*)[[event stub] andReturnValue:OCMOCK_VALUE(phase)] phase];
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [(NSEvent*)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [[event stub] andReturnValue:OCMOCK_VALUE(momentumPhase)] momentumPhase];
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [(NSEvent*)[[event stub]
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       andReturnValue:OCMOCK_VALUE(scrollingDeltaX)] scrollingDeltaX];
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [(NSEvent*)[[event stub]
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       andReturnValue:OCMOCK_VALUE(scrollingDeltaY)] scrollingDeltaY];
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return event;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)id scrollWheelEventWithPhase(NSEventPhase phase,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             NSEventPhase momentumPhase) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scrollWheelEventWithPhase(phase, momentumPhase, 0, 0);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)id scrollWheelEventWithPhase(NSEventPhase phase) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scrollWheelEventWithPhase(phase, NSEventPhaseNone);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MacHistorySwiperTest::startGestureInMiddle() {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSEvent* event = mockEventWithPoint(makePoint(0.5, 0.5), NSEventTypeGesture);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ touchesBeganWithEvent:event];
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ beginGestureWithEvent:event];
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseBegan);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ handleEvent:scrollEvent];
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MacHistorySwiperTest::moveGestureInMiddle() {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureAtPoint(makePoint(0.5, 0.5));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callbacks from blink to set the relevant state for history swiping.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ gotUnhandledWheelEvent];
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ scrollOffsetPinnedToLeft:YES toRight:YES];
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ setHasHorizontalScrollbar:NO];
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MacHistorySwiperTest::moveGestureAtPoint(NSPoint point) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSEvent* event = mockEventWithPoint(point, NSEventTypeGesture);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ touchesMovedWithEvent:event];
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseChanged);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ handleEvent:scrollEvent];
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MacHistorySwiperTest::momentumMoveGestureAtPoint(NSPoint point) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSEvent* event = mockEventWithPoint(point, NSEventTypeGesture);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ touchesMovedWithEvent:event];
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSEvent* scrollEvent =
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scrollWheelEventWithPhase(NSEventPhaseNone, NSEventPhaseChanged);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ handleEvent:scrollEvent];
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MacHistorySwiperTest::endGestureAtPoint(NSPoint point) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSEvent* event = mockEventWithPoint(point, NSEventTypeGesture);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ touchesEndedWithEvent:event];
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseEnded);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [historySwiper_ handleEvent:scrollEvent];
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a simple left-swipe causes navigation.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacHistorySwiperTest, SwipeLeft) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These tests require 10.7+ APIs.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (![NSEvent
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  startGestureInMiddle();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureInMiddle();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(begin_count_, 0);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(end_count_, 0);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureAtPoint(makePoint(0.2, 0.5));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(begin_count_, 1);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(end_count_, 0);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(navigated_right_);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(navigated_left_);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  endGestureAtPoint(makePoint(0.2, 0.5));
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(begin_count_, 1);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(end_count_, 1);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(navigated_right_);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(navigated_left_);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a simple right-swipe causes navigation.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacHistorySwiperTest, SwipeRight) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These tests require 10.7+ APIs.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (![NSEvent
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  startGestureInMiddle();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureInMiddle();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(begin_count_, 0);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(end_count_, 0);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureAtPoint(makePoint(0.8, 0.5));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(begin_count_, 1);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(end_count_, 0);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(navigated_right_);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(navigated_left_);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  endGestureAtPoint(makePoint(0.8, 0.5));
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(begin_count_, 1);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(end_count_, 1);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(navigated_right_);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(navigated_left_);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the user doesn't swipe enough, the history swiper should begin, but the
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// browser should not navigate.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacHistorySwiperTest, SwipeLeftSmallAmount) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These tests require 10.7+ APIs.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (![NSEvent
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  startGestureInMiddle();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureInMiddle();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureAtPoint(makePoint(0.45, 0.5));
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  endGestureAtPoint(makePoint(0.45, 0.5));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(begin_count_, 1);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(end_count_, 1);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(navigated_right_);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(navigated_left_);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Diagonal swipes with a slight horizontal bias should not start the history
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// swiper.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacHistorySwiperTest, SwipeDiagonal) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These tests require 10.7+ APIs.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (![NSEvent
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  startGestureInMiddle();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureInMiddle();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureAtPoint(makePoint(0.6, 0.59));
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  endGestureAtPoint(makePoint(0.6, 0.59));
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(begin_count_, 0);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(end_count_, 0);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(navigated_right_);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(navigated_left_);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Swiping left and then down should cancel the history swiper without
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// navigating.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacHistorySwiperTest, SwipeLeftThenDown) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These tests require 10.7+ APIs.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (![NSEvent
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  startGestureInMiddle();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureInMiddle();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureAtPoint(makePoint(0.4, 0.5));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  moveGestureAtPoint(makePoint(0.4, 0.3));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  endGestureAtPoint(makePoint(0.2, 0.2));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(begin_count_, 1);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(end_count_, 1);
305  EXPECT_FALSE(navigated_right_);
306  EXPECT_FALSE(navigated_left_);
307}
308
309// Sometimes Cocoa gets confused and sends us a momentum swipe event instead of
310// a swipe gesture event. We should still function appropriately.
311TEST_F(MacHistorySwiperTest, MomentumSwipeLeft) {
312  // These tests require 10.7+ APIs.
313  if (![NSEvent
314          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
315    return;
316
317  startGestureInMiddle();
318
319  // Send a momentum move gesture.
320  momentumMoveGestureAtPoint(makePoint(0.5, 0.5));
321  EXPECT_EQ(begin_count_, 0);
322  EXPECT_EQ(end_count_, 0);
323
324  // Callbacks from blink to set the relevant state for history swiping.
325  [historySwiper_ gotUnhandledWheelEvent];
326  [historySwiper_ scrollOffsetPinnedToLeft:YES toRight:YES];
327  [historySwiper_ setHasHorizontalScrollbar:NO];
328
329  momentumMoveGestureAtPoint(makePoint(0.2, 0.5));
330  EXPECT_EQ(begin_count_, 1);
331  EXPECT_EQ(end_count_, 0);
332  EXPECT_FALSE(navigated_right_);
333  EXPECT_FALSE(navigated_left_);
334
335  endGestureAtPoint(makePoint(0.2, 0.5));
336  EXPECT_EQ(begin_count_, 1);
337  EXPECT_EQ(end_count_, 1);
338  EXPECT_FALSE(navigated_right_);
339  EXPECT_TRUE(navigated_left_);
340}
341
342// Momentum scroll events for magic mouse should not attempt to trigger the
343// `trackSwipeEventWithOptions:` api, as that throws an exception.
344TEST_F(MacHistorySwiperTest, MagicMouseMomentumSwipe) {
345  // These tests require 10.7+ APIs.
346  if (![NSEvent
347          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
348    return;
349
350  // Magic mouse events don't generate 'touches*' callbacks.
351  NSEvent* event = mockEventWithPoint(makePoint(0.5, 0.5), NSEventTypeGesture);
352  [historySwiper_ beginGestureWithEvent:event];
353  NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseBegan);
354  [historySwiper_ handleEvent:scrollEvent];
355
356  // Callbacks from blink to set the relevant state for history swiping.
357  [historySwiper_ gotUnhandledWheelEvent];
358  [historySwiper_ scrollOffsetPinnedToLeft:YES toRight:YES];
359  [historySwiper_ setHasHorizontalScrollbar:NO];
360
361  // Send a momentum move gesture.
362  scrollEvent =
363      scrollWheelEventWithPhase(NSEventPhaseNone, NSEventPhaseChanged, 5.0, 0);
364  [historySwiper_ handleEvent:scrollEvent];
365
366  EXPECT_FALSE(magic_mouse_history_swipe_);
367}
368
369// User starts a swipe but doesn't move.
370TEST_F(MacHistorySwiperTest, NoSwipe) {
371  // These tests require 10.7+ APIs.
372  if (![NSEvent
373          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
374    return;
375
376  startGestureInMiddle();
377  moveGestureInMiddle();
378  moveGestureAtPoint(makePoint(0.5, 0.5));
379  endGestureAtPoint(makePoint(0.5, 0.5));
380
381  EXPECT_EQ(begin_count_, 0);
382  EXPECT_EQ(end_count_, 0);
383}
384
385// After a gesture is successfully recognized, momentum events should be
386// swallowed, but new events should pass through.
387TEST_F(MacHistorySwiperTest, TouchEventAfterGestureFinishes) {
388  // These tests require 10.7+ APIs.
389  if (![NSEvent
390          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
391    return;
392
393  // Successfully pass through a gesture.
394  startGestureInMiddle();
395  moveGestureInMiddle();
396  moveGestureAtPoint(makePoint(0.8, 0.5));
397  endGestureAtPoint(makePoint(0.8, 0.5));
398  EXPECT_TRUE(navigated_right_);
399
400  // Momentum events should be swallowed.
401  NSEvent* momentumEvent = scrollWheelEventWithPhase(NSEventPhaseNone,
402                                                     NSEventPhaseChanged);
403  EXPECT_TRUE([historySwiper_ handleEvent:momentumEvent]);
404
405  // New events should not be swallowed.
406  NSEvent* beganEvent = scrollWheelEventWithPhase(NSEventPhaseBegan);
407  EXPECT_FALSE([historySwiper_ handleEvent:beganEvent]);
408}
409