1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <Carbon/Carbon.h>
6
7#include "base/debug/debugger.h"
8#include "chrome/app/chrome_command_ids.h"
9#import "chrome/browser/ui/cocoa/browser_window_controller.h"
10#import "chrome/browser/ui/cocoa/chrome_event_processing_window.h"
11#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
12#import "third_party/ocmock/OCMock/OCMock.h"
13#include "third_party/ocmock/gtest_support.h"
14#import "third_party/ocmock/ocmock_extensions.h"
15
16namespace {
17
18NSEvent* KeyEvent(const NSUInteger flags, const NSUInteger keyCode) {
19  return [NSEvent keyEventWithType:NSKeyDown
20                          location:NSZeroPoint
21                     modifierFlags:flags
22                         timestamp:0.0
23                      windowNumber:0
24                           context:nil
25                        characters:@""
26       charactersIgnoringModifiers:@""
27                         isARepeat:NO
28                          keyCode:keyCode];
29}
30
31class ChromeEventProcessingWindowTest : public CocoaTest {
32 public:
33  virtual void SetUp() {
34    CocoaTest::SetUp();
35    // Create a window.
36    const NSUInteger mask = NSTitledWindowMask | NSClosableWindowMask |
37        NSMiniaturizableWindowMask | NSResizableWindowMask;
38    window_ = [[ChromeEventProcessingWindow alloc]
39               initWithContentRect:NSMakeRect(0, 0, 800, 600)
40                         styleMask:mask
41                           backing:NSBackingStoreBuffered
42                             defer:NO];
43    if (base::debug::BeingDebugged()) {
44      [window_ orderFront:nil];
45    } else {
46      [window_ orderBack:nil];
47    }
48  }
49
50  virtual void TearDown() {
51    [window_ close];
52    CocoaTest::TearDown();
53  }
54
55  ChromeEventProcessingWindow* window_;
56};
57
58id CreateBrowserWindowControllerMock() {
59  id delegate = [OCMockObject mockForClass:[BrowserWindowController class]];
60  // Make conformsToProtocol return YES for @protocol(BrowserCommandExecutor)
61  // to satisfy the DCHECK() in handleExtraKeyboardShortcut.
62  [[[delegate stub] andReturnBool:YES]
63    conformsToProtocol:[OCMArg conformsToProtocol:
64                        @protocol(BrowserCommandExecutor)]];
65  return delegate;
66}
67
68// Verify that the window intercepts a particular key event and
69// forwards it to [delegate executeCommand:].  Assume that other
70// CommandForKeyboardShortcut() will work the same for the rest.
71TEST_F(ChromeEventProcessingWindowTest,
72       PerformKeyEquivalentForwardToExecuteCommand) {
73  NSEvent* event = KeyEvent(NSCommandKeyMask, kVK_ANSI_1);
74
75  id delegate = CreateBrowserWindowControllerMock();
76  [[delegate expect] executeCommand:IDC_SELECT_TAB_0];
77
78  [window_ setDelegate:delegate];
79  [window_ performKeyEquivalent:event];
80
81  // Don't wish to mock all the way down...
82  [window_ setDelegate:nil];
83  EXPECT_OCMOCK_VERIFY(delegate);
84}
85
86// Verify that an unhandled shortcut does not get forwarded via
87// -executeCommand:.
88// TODO(shess) Think of a way to test that it is sent to the
89// superclass.
90TEST_F(ChromeEventProcessingWindowTest, PerformKeyEquivalentNoForward) {
91  NSEvent* event = KeyEvent(0, 0);
92
93  id delegate = CreateBrowserWindowControllerMock();
94
95  [window_ setDelegate:delegate];
96  [window_ performKeyEquivalent:event];
97
98  // Don't wish to mock all the way down...
99  [window_ setDelegate:nil];
100  EXPECT_OCMOCK_VERIFY(delegate);
101}
102
103}  // namespace
104