chrome_render_widget_host_view_mac_history_swiper_unit_test.mm revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1a0d5878b7e1c54551c0445354788e4259900c03cDavid Tweed// Copyright 2013 The Chromium Authors. All rights reserved.
2994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith// Use of this source code is governed by a BSD-style license that can be
3994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith// found in the LICENSE file.
4994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith
5994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith#include "testing/gtest/include/gtest/gtest.h"
6994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
7994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith
8994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith#include "base/mac/scoped_nsobject.h"
9994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith#import "base/mac/sdk_forward_declarations.h"
10994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith#import "chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h"
11994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith#import "third_party/ocmock/OCMock/OCMock.h"
12994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith#import "third_party/ocmock/ocmock_extensions.h"
13994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith#include "third_party/WebKit/public/web/WebInputEvent.h"
14994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith
152d67097ad41f4c2fe82ebce3f587e06498f1bd71Richard Smith@interface HistorySwiper (MacHistorySwiperTest)
16994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith- (BOOL)systemSettingsAllowHistorySwiping:(NSEvent*)event;
17994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith- (BOOL)browserCanNavigateInDirection:
18994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith        (history_swiper::NavigationDirection)forward
19994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith                                event:(NSEvent*)event;
2050dc12ad05d4a3a57e83852756498afce4307a77Kaelyn Uhrain- (void)endHistorySwipe;
21994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith- (void)beginHistorySwipeInDirection:
22994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith        (history_swiper::NavigationDirection)goForward
23994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith                               event:(NSEvent*)event;
24994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith- (void)navigateBrowserInDirection:(history_swiper::NavigationDirection)forward;
25994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith- (void)initiateMagicMouseHistorySwipe:(BOOL)isRightScroll
2653aec2a2770afc242c70fd88975cd0ea389087c0Richard Smith                                 event:(NSEvent*)event;
2753aec2a2770afc242c70fd88975cd0ea389087c0Richard Smith@end
28994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith
29994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smithclass MacHistorySwiperTest : public CocoaTest {
30994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith public:
31994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith  virtual void SetUp() OVERRIDE {
32994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith    CocoaTest::SetUp();
3353aec2a2770afc242c70fd88975cd0ea389087c0Richard Smith
3453aec2a2770afc242c70fd88975cd0ea389087c0Richard Smith    [HistorySwiper resetMagicMouseState];
35994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith
36994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith    view_ = [[NSView alloc] init];
37994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith    id mockDelegate =
38b310439121c875937d78cc49cc969bc1197fc025Richard Smith        [OCMockObject mockForProtocol:@protocol(HistorySwiperDelegate)];
39b310439121c875937d78cc49cc969bc1197fc025Richard Smith    [[[mockDelegate stub] andReturn:view_] viewThatWantsHistoryOverlay];
40b310439121c875937d78cc49cc969bc1197fc025Richard Smith    [[[mockDelegate stub] andReturnBool:YES] shouldAllowHistorySwiping];
41b310439121c875937d78cc49cc969bc1197fc025Richard Smith
42b310439121c875937d78cc49cc969bc1197fc025Richard Smith    base::scoped_nsobject<HistorySwiper> historySwiper(
43b310439121c875937d78cc49cc969bc1197fc025Richard Smith        [[HistorySwiper alloc] initWithDelegate:mockDelegate]);
44b310439121c875937d78cc49cc969bc1197fc025Richard Smith    id mockHistorySwiper = [OCMockObject partialMockForObject:historySwiper];
45b310439121c875937d78cc49cc969bc1197fc025Richard Smith    [[[mockHistorySwiper stub] andReturnBool:YES]
46b310439121c875937d78cc49cc969bc1197fc025Richard Smith        systemSettingsAllowHistorySwiping:[OCMArg any]];
477faf81ff1dc8f8dc724e928ba90ccbfad0fdc2bcRichard Smith    [[[mockHistorySwiper stub] andReturnBool:YES]
487faf81ff1dc8f8dc724e928ba90ccbfad0fdc2bcRichard Smith        browserCanNavigateInDirection:history_swiper::kForwards
497faf81ff1dc8f8dc724e928ba90ccbfad0fdc2bcRichard Smith                                event:[OCMArg any]];
507faf81ff1dc8f8dc724e928ba90ccbfad0fdc2bcRichard Smith    [[[mockHistorySwiper stub] andReturnBool:YES]
517faf81ff1dc8f8dc724e928ba90ccbfad0fdc2bcRichard Smith        browserCanNavigateInDirection:history_swiper::kBackwards
52b310439121c875937d78cc49cc969bc1197fc025Richard Smith                                event:[OCMArg any]];
53b310439121c875937d78cc49cc969bc1197fc025Richard Smith    [[[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
54994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith      ++begin_count_;
55994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith      // beginHistorySwipeInDirection: calls endHistorySwipe internally.
56994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith      --end_count_;
57994d73f8473cb2cd3ce2f69c9575c95015be788aRichard Smith    }] andForwardToRealObject]
582d67097ad41f4c2fe82ebce3f587e06498f1bd71Richard Smith        beginHistorySwipeInDirection:history_swiper::kForwards
5950dc12ad05d4a3a57e83852756498afce4307a77Kaelyn Uhrain                               event:[OCMArg any]];
6050dc12ad05d4a3a57e83852756498afce4307a77Kaelyn Uhrain    [[[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
6150dc12ad05d4a3a57e83852756498afce4307a77Kaelyn Uhrain      ++begin_count_;
6237ec8d589c5de34d0e260f0599395519bd7498deRichard Smith      // beginHistorySwipeInDirection: calls endHistorySwipe internally.
6337ec8d589c5de34d0e260f0599395519bd7498deRichard Smith      --end_count_;
6437ec8d589c5de34d0e260f0599395519bd7498deRichard Smith    }] andForwardToRealObject]
6537ec8d589c5de34d0e260f0599395519bd7498deRichard Smith        beginHistorySwipeInDirection:history_swiper::kBackwards
6637ec8d589c5de34d0e260f0599395519bd7498deRichard Smith                               event:[OCMArg any]];
6737ec8d589c5de34d0e260f0599395519bd7498deRichard Smith    [[[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
6837ec8d589c5de34d0e260f0599395519bd7498deRichard Smith      ++end_count_;
69f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    }] andForwardToRealObject] endHistorySwipe];
70f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
71f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling        navigated_right_ = true;
72f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    }] navigateBrowserInDirection:history_swiper::kForwards];
73f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
74f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling        navigated_left_ = true;
75f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    }] navigateBrowserInDirection:history_swiper::kBackwards];
76f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling
77f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
78f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling        magic_mouse_history_swipe_ = true;
79f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    }] initiateMagicMouseHistorySwipe:YES event:[OCMArg any]];
80f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    [[[mockHistorySwiper stub] andDo:^(NSInvocation* invocation) {
81f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling        magic_mouse_history_swipe_ = true;
82f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    }] initiateMagicMouseHistorySwipe:NO event:[OCMArg any]];
83f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling
84f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    historySwiper_ = [mockHistorySwiper retain];
85f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling
86f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    begin_count_ = 0;
87f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    end_count_ = 0;
88f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    navigated_right_ = false;
89f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    navigated_left_ = false;
90f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    magic_mouse_history_swipe_ = false;
91f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  }
92f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling
93f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  virtual void TearDown() OVERRIDE {
94f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    [view_ release];
95f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    [historySwiper_ release];
96f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling    CocoaTest::TearDown();
97f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  }
98f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling
99f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  void startGestureInMiddle();
100f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  void moveGestureInMiddle();
101f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  void moveGestureAtPoint(NSPoint point);
102f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  void momentumMoveGestureAtPoint(NSPoint point);
103f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  void endGestureAtPoint(NSPoint point);
104f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  void rendererACKForBeganEvent();
105f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling
106f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  HistorySwiper* historySwiper_;
107f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  NSView* view_;
108f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  int begin_count_;
109f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  int end_count_;
110f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  bool navigated_right_;
111f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  bool navigated_left_;
112f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  bool magic_mouse_history_swipe_;
113f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling};
114f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling
115f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill WendlingNSPoint makePoint(CGFloat x, CGFloat y) {
116f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  NSPoint point;
117f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  point.x = x;
118f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  point.y = y;
119f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling  return point;
120f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling}
121f0cc19f43d5e05dbd22d00faca8c093b7005be3fBill Wendling
122e78e8fc27140309092fb56d77a72f31fa085f9daBill Wendlingid mockEventWithPoint(NSPoint point, NSEventType type) {
123651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  id mockEvent = [OCMockObject mockForClass:[NSEvent class]];
124651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  id mockTouch = [OCMockObject mockForClass:[NSTouch class]];
125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  [[[mockTouch stub] andReturnNSPoint:point] normalizedPosition];
126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  NSArray* touches = @[mockTouch];
127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  [[[mockEvent stub] andReturn:touches] touchesMatchingPhase:NSTouchPhaseAny
128651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    inView:[OCMArg any]];
129651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  [[[mockEvent stub] andReturnBool:NO] isDirectionInvertedFromDevice];
130651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  [(NSEvent*)[[mockEvent stub] andReturnValue:OCMOCK_VALUE(type)] type];
131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return mockEvent;
133e78e8fc27140309092fb56d77a72f31fa085f9daBill Wendling}
134e78e8fc27140309092fb56d77a72f31fa085f9daBill Wendling
135e78e8fc27140309092fb56d77a72f31fa085f9daBill Wendlingid scrollWheelEventWithPhase(NSEventPhase phase,
136e78e8fc27140309092fb56d77a72f31fa085f9daBill Wendling                             NSEventPhase momentumPhase,
137e78e8fc27140309092fb56d77a72f31fa085f9daBill Wendling                             CGFloat scrollingDeltaX,
1386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                             CGFloat scrollingDeltaY) {
1396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // The point isn't used, so we pass in bogus data.
1406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  id event = mockEventWithPoint(makePoint(0,0), NSScrollWheel);
1416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [(NSEvent*)[[event stub] andReturnValue:OCMOCK_VALUE(phase)] phase];
1426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [(NSEvent*)
1436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      [[event stub] andReturnValue:OCMOCK_VALUE(momentumPhase)] momentumPhase];
1446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [(NSEvent*)[[event stub]
1456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines       andReturnValue:OCMOCK_VALUE(scrollingDeltaX)] scrollingDeltaX];
1466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [(NSEvent*)[[event stub]
1476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines       andReturnValue:OCMOCK_VALUE(scrollingDeltaY)] scrollingDeltaY];
1486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return event;
1496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
1506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesid scrollWheelEventWithPhase(NSEventPhase phase,
1526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                             NSEventPhase momentumPhase) {
1536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return scrollWheelEventWithPhase(phase, momentumPhase, 0, 0);
1546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
1556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesid scrollWheelEventWithPhase(NSEventPhase phase) {
1576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return scrollWheelEventWithPhase(phase, NSEventPhaseNone);
1586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
1596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid MacHistorySwiperTest::startGestureInMiddle() {
1616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  NSEvent* event = mockEventWithPoint(makePoint(0.5, 0.5), NSEventTypeGesture);
1626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [historySwiper_ touchesBeganWithEvent:event];
1636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [historySwiper_ beginGestureWithEvent:event];
1646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseBegan);
1656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [historySwiper_ handleEvent:scrollEvent];
1666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
1676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid MacHistorySwiperTest::moveGestureInMiddle() {
1696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  moveGestureAtPoint(makePoint(0.5, 0.5));
1706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Callbacks from blink to set the relevant state for history swiping.
1726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  rendererACKForBeganEvent();
1736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
1746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid MacHistorySwiperTest::moveGestureAtPoint(NSPoint point) {
1766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  NSEvent* event = mockEventWithPoint(point, NSEventTypeGesture);
1776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [historySwiper_ touchesMovedWithEvent:event];
1786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseChanged);
1806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [historySwiper_ handleEvent:scrollEvent];
1816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
1826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid MacHistorySwiperTest::momentumMoveGestureAtPoint(NSPoint point) {
1846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  NSEvent* event = mockEventWithPoint(point, NSEventTypeGesture);
1856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [historySwiper_ touchesMovedWithEvent:event];
1866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  NSEvent* scrollEvent =
1886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      scrollWheelEventWithPhase(NSEventPhaseNone, NSEventPhaseChanged);
1896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [historySwiper_ handleEvent:scrollEvent];
1906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
1916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid MacHistorySwiperTest::endGestureAtPoint(NSPoint point) {
1936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  NSEvent* event = mockEventWithPoint(point, NSEventTypeGesture);
1946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [historySwiper_ touchesEndedWithEvent:event];
1956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseEnded);
1976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [historySwiper_ handleEvent:scrollEvent];
1986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
1996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid MacHistorySwiperTest::rendererACKForBeganEvent() {
2016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  blink::WebMouseWheelEvent event;
2026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  event.phase = blink::WebMouseWheelEvent::PhaseBegan;
2036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  [historySwiper_ rendererHandledWheelEvent:event consumed:NO];
2046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
205
206// Test that a simple left-swipe causes navigation.
207TEST_F(MacHistorySwiperTest, SwipeLeft) {
208  // These tests require 10.7+ APIs.
209  if (![NSEvent
210          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
211    return;
212
213  startGestureInMiddle();
214  moveGestureInMiddle();
215
216  EXPECT_EQ(begin_count_, 0);
217  EXPECT_EQ(end_count_, 0);
218
219  moveGestureAtPoint(makePoint(0.2, 0.5));
220  EXPECT_EQ(begin_count_, 1);
221  EXPECT_EQ(end_count_, 0);
222  EXPECT_FALSE(navigated_right_);
223  EXPECT_FALSE(navigated_left_);
224
225  endGestureAtPoint(makePoint(0.2, 0.5));
226  EXPECT_EQ(begin_count_, 1);
227  EXPECT_EQ(end_count_, 1);
228  EXPECT_FALSE(navigated_right_);
229  EXPECT_TRUE(navigated_left_);
230}
231
232// Test that a simple right-swipe causes navigation.
233TEST_F(MacHistorySwiperTest, SwipeRight) {
234  // These tests require 10.7+ APIs.
235  if (![NSEvent
236          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
237    return;
238
239  startGestureInMiddle();
240  moveGestureInMiddle();
241
242  EXPECT_EQ(begin_count_, 0);
243  EXPECT_EQ(end_count_, 0);
244
245  moveGestureAtPoint(makePoint(0.8, 0.5));
246  EXPECT_EQ(begin_count_, 1);
247  EXPECT_EQ(end_count_, 0);
248  EXPECT_FALSE(navigated_right_);
249  EXPECT_FALSE(navigated_left_);
250
251  endGestureAtPoint(makePoint(0.8, 0.5));
252  EXPECT_EQ(begin_count_, 1);
253  EXPECT_EQ(end_count_, 1);
254  EXPECT_TRUE(navigated_right_);
255  EXPECT_FALSE(navigated_left_);
256}
257
258// If the user doesn't swipe enough, the history swiper should begin, but the
259// browser should not navigate.
260TEST_F(MacHistorySwiperTest, SwipeLeftSmallAmount) {
261  // These tests require 10.7+ APIs.
262  if (![NSEvent
263          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
264    return;
265
266  startGestureInMiddle();
267  moveGestureInMiddle();
268  moveGestureAtPoint(makePoint(0.45, 0.5));
269  endGestureAtPoint(makePoint(0.45, 0.5));
270  EXPECT_EQ(begin_count_, 1);
271  EXPECT_EQ(end_count_, 1);
272  EXPECT_FALSE(navigated_right_);
273  EXPECT_FALSE(navigated_left_);
274}
275
276// Diagonal swipes with a slight horizontal bias should not start the history
277// swiper.
278TEST_F(MacHistorySwiperTest, SwipeDiagonal) {
279  // These tests require 10.7+ APIs.
280  if (![NSEvent
281          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
282    return;
283
284  startGestureInMiddle();
285  moveGestureInMiddle();
286  moveGestureInMiddle();
287  moveGestureAtPoint(makePoint(0.6, 0.59));
288  endGestureAtPoint(makePoint(0.6, 0.59));
289
290  EXPECT_EQ(begin_count_, 1);
291  EXPECT_EQ(end_count_, 1);
292  EXPECT_FALSE(navigated_right_);
293  EXPECT_FALSE(navigated_left_);
294}
295
296// Swiping left and then down should cancel the history swiper without
297// navigating.
298TEST_F(MacHistorySwiperTest, SwipeLeftThenDown) {
299  // These tests require 10.7+ APIs.
300  if (![NSEvent
301          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
302    return;
303
304  startGestureInMiddle();
305  moveGestureInMiddle();
306  moveGestureAtPoint(makePoint(0.4, 0.5));
307  moveGestureAtPoint(makePoint(0.4, 0.3));
308  endGestureAtPoint(makePoint(0.2, 0.2));
309  EXPECT_EQ(begin_count_, 1);
310  EXPECT_EQ(end_count_, 1);
311  EXPECT_FALSE(navigated_right_);
312  EXPECT_FALSE(navigated_left_);
313}
314
315// Sometimes Cocoa gets confused and sends us a momentum swipe event instead of
316// a swipe gesture event. Momentum events should not cause history swiping.
317TEST_F(MacHistorySwiperTest, MomentumSwipeLeft) {
318  // These tests require 10.7+ APIs.
319  if (![NSEvent
320          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
321    return;
322
323  startGestureInMiddle();
324
325  // Send a momentum move gesture.
326  momentumMoveGestureAtPoint(makePoint(0.5, 0.5));
327  EXPECT_EQ(begin_count_, 0);
328  EXPECT_EQ(end_count_, 0);
329
330  // Callbacks from blink to set the relevant state for history swiping.
331  rendererACKForBeganEvent();
332
333  momentumMoveGestureAtPoint(makePoint(0.2, 0.5));
334  EXPECT_EQ(begin_count_, 0);
335  EXPECT_EQ(end_count_, 0);
336
337  endGestureAtPoint(makePoint(0.2, 0.5));
338  EXPECT_EQ(begin_count_, 0);
339  EXPECT_EQ(end_count_, 0);
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  rendererACKForBeganEvent();
358
359  // Send a momentum move gesture.
360  scrollEvent =
361      scrollWheelEventWithPhase(NSEventPhaseNone, NSEventPhaseChanged, 5.0, 0);
362  [historySwiper_ handleEvent:scrollEvent];
363
364  EXPECT_FALSE(magic_mouse_history_swipe_);
365}
366
367// User starts a swipe but doesn't move.
368TEST_F(MacHistorySwiperTest, NoSwipe) {
369  // These tests require 10.7+ APIs.
370  if (![NSEvent
371          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
372    return;
373
374  startGestureInMiddle();
375  moveGestureInMiddle();
376
377  // Starts the gesture.
378  moveGestureAtPoint(makePoint(0.44, 0.44));
379
380  // No movement.
381  endGestureAtPoint(makePoint(0.44, 0.44));
382
383  EXPECT_EQ(begin_count_, 1);
384  EXPECT_EQ(end_count_, 1);
385  EXPECT_FALSE(navigated_right_);
386  EXPECT_FALSE(navigated_left_);
387}
388
389// After a gesture is successfully recognized, momentum events should be
390// swallowed, but new events should pass through.
391TEST_F(MacHistorySwiperTest, TouchEventAfterGestureFinishes) {
392  // These tests require 10.7+ APIs.
393  if (![NSEvent
394          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
395    return;
396
397  // Successfully pass through a gesture.
398  startGestureInMiddle();
399  moveGestureInMiddle();
400  moveGestureAtPoint(makePoint(0.8, 0.5));
401  endGestureAtPoint(makePoint(0.8, 0.5));
402  EXPECT_TRUE(navigated_right_);
403
404  // Momentum events should be swallowed.
405  NSEvent* momentumEvent = scrollWheelEventWithPhase(NSEventPhaseNone,
406                                                     NSEventPhaseChanged);
407  EXPECT_TRUE([historySwiper_ handleEvent:momentumEvent]);
408
409  // New events should not be swallowed.
410  NSEvent* beganEvent = scrollWheelEventWithPhase(NSEventPhaseBegan);
411  EXPECT_FALSE([historySwiper_ handleEvent:beganEvent]);
412}
413
414// The history swipe logic should be resilient against the timing of the
415// different callbacks that result from scrolling.
416TEST_F(MacHistorySwiperTest, SwipeRightEventOrdering) {
417  // These tests require 10.7+ APIs.
418  if (![NSEvent
419          respondsToSelector:@selector(isSwipeTrackingFromScrollEventsEnabled)])
420    return;
421
422  // Touches began.
423  NSEvent* scrollEvent = scrollWheelEventWithPhase(NSEventPhaseBegan);
424  NSEvent* event = mockEventWithPoint(makePoint(0.5, 0.5), NSEventTypeGesture);
425  [historySwiper_ touchesBeganWithEvent:event];
426  [historySwiper_ handleEvent:scrollEvent];
427  rendererACKForBeganEvent();
428
429  // Touches moved.
430  moveGestureAtPoint(makePoint(0.5, 0.5));
431  EXPECT_EQ(begin_count_, 0);
432  EXPECT_EQ(end_count_, 0);
433
434  // Touches moved.
435  moveGestureAtPoint(makePoint(0.52, 0.5));
436
437  // Begin gesture callback is delayed.
438  [historySwiper_ beginGestureWithEvent:event];
439
440  // Touches moved.
441  moveGestureAtPoint(makePoint(0.52, 0.5));
442
443  // Complete the rest of the gesture.
444  moveGestureAtPoint(makePoint(0.60, 0.5));
445  scrollEvent = scrollWheelEventWithPhase(NSEventPhaseChanged);
446  [historySwiper_ handleEvent:scrollEvent];
447  endGestureAtPoint(makePoint(0.70, 0.5));
448
449  EXPECT_EQ(begin_count_, 1);
450  EXPECT_EQ(end_count_, 1);
451  EXPECT_TRUE(navigated_right_);
452  EXPECT_FALSE(navigated_left_);
453}
454