Home | History | Annotate | Download | only in cocoa
      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 "base/mac/scoped_nsobject.h"
      6 #import "chrome/browser/ui/cocoa/clickhold_button_cell.h"
      7 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
      8 #import "chrome/browser/ui/cocoa/menu_button.h"
      9 
     10 @interface MenuButtonTestDelegate : NSObject<NSMenuDelegate> {
     11  @private
     12   base::scoped_nsobject<NSMenu> menu_;
     13   BOOL open_;
     14   BOOL didOpen_;
     15 }
     16 - (BOOL)isOpen;
     17 - (BOOL)didOpen;
     18 @end
     19 
     20 @implementation MenuButtonTestDelegate
     21 - (id)initWithMenu:(NSMenu*)menu {
     22   if ((self = [super init])) {
     23     menu_.reset([menu retain]);
     24   }
     25   return self;
     26 }
     27 
     28 - (BOOL)isOpen {
     29   return open_;
     30 }
     31 
     32 - (BOOL)didOpen {
     33   return didOpen_;
     34 }
     35 
     36 - (void)menuWillOpen:(NSMenu*)menu {
     37   EXPECT_EQ(menu_.get(), menu);
     38   EXPECT_FALSE(open_);
     39   open_ = YES;
     40   didOpen_ = YES;
     41   NSArray* modes = [NSArray arrayWithObjects:NSEventTrackingRunLoopMode,
     42                                              NSDefaultRunLoopMode,
     43                                              nil];
     44   [menu performSelector:@selector(cancelTracking)
     45              withObject:nil
     46              afterDelay:0.1
     47                 inModes:modes];
     48 }
     49 
     50 - (void)menuDidClose:(NSMenu*)menu {
     51   EXPECT_EQ(menu_.get(), menu);
     52   EXPECT_TRUE(open_);
     53   open_ = NO;
     54 }
     55 @end
     56 
     57 namespace {
     58 
     59 class MenuButtonTest : public CocoaTest {
     60  public:
     61   MenuButtonTest() {
     62     NSRect frame = NSMakeRect(0, 0, 50, 30);
     63     base::scoped_nsobject<MenuButton> button(
     64         [[MenuButton alloc] initWithFrame:frame]);
     65     button_ = button.get();
     66     base::scoped_nsobject<ClickHoldButtonCell> cell(
     67         [[ClickHoldButtonCell alloc] initTextCell:@"Testing"]);
     68     [button_ setCell:cell.get()];
     69     [[test_window() contentView] addSubview:button_];
     70   }
     71 
     72   NSMenu* CreateMenu() {
     73     NSMenu* menu = [[NSMenu alloc] initWithTitle:@""];
     74     [menu insertItemWithTitle:@"" action:nil keyEquivalent:@"" atIndex:0];
     75     [menu insertItemWithTitle:@"foo" action:nil keyEquivalent:@"" atIndex:1];
     76     [menu insertItemWithTitle:@"bar" action:nil keyEquivalent:@"" atIndex:2];
     77     [menu insertItemWithTitle:@"baz" action:nil keyEquivalent:@"" atIndex:3];
     78     return menu;
     79   }
     80 
     81   NSEvent* MouseDownEvent(NSEventType eventType) {
     82     NSPoint location;
     83     location.x = location.y = 0;
     84     NSGraphicsContext* context = [NSGraphicsContext currentContext];
     85     NSEvent* event = [NSEvent mouseEventWithType:eventType
     86                                         location:location
     87                                    modifierFlags:0
     88                                        timestamp:0
     89                                     windowNumber:0
     90                                          context:context
     91                                      eventNumber:0
     92                                       clickCount:1
     93                                         pressure:0.0F];
     94 
     95     return event;
     96   }
     97 
     98   MenuButton* button_;
     99 };
    100 
    101 TEST_VIEW(MenuButtonTest, button_);
    102 
    103 // Test assigning a menu, again mostly to ensure nothing leaks or crashes.
    104 TEST_F(MenuButtonTest, MenuAssign) {
    105   base::scoped_nsobject<NSMenu> menu(CreateMenu());
    106   ASSERT_TRUE(menu.get());
    107 
    108   [button_ setAttachedMenu:menu];
    109   EXPECT_TRUE([button_ attachedMenu]);
    110 }
    111 
    112 TEST_F(MenuButtonTest, OpenOnClick) {
    113   base::scoped_nsobject<NSMenu> menu(CreateMenu());
    114   ASSERT_TRUE(menu.get());
    115 
    116   base::scoped_nsobject<MenuButtonTestDelegate> delegate(
    117       [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
    118   ASSERT_TRUE(delegate.get());
    119 
    120   [menu setDelegate:delegate.get()];
    121   [button_ setAttachedMenu:menu];
    122   [button_ setOpenMenuOnClick:YES];
    123 
    124   EXPECT_FALSE([delegate isOpen]);
    125   EXPECT_FALSE([delegate didOpen]);
    126 
    127   // Should open the menu.
    128   [button_ performClick:nil];
    129 
    130   EXPECT_TRUE([delegate didOpen]);
    131   EXPECT_FALSE([delegate isOpen]);
    132 }
    133 
    134 TEST_F(MenuButtonTest, OpenOnRightClick) {
    135   base::scoped_nsobject<NSMenu> menu(CreateMenu());
    136   ASSERT_TRUE(menu.get());
    137 
    138   base::scoped_nsobject<MenuButtonTestDelegate> delegate(
    139       [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
    140   ASSERT_TRUE(delegate.get());
    141 
    142   [menu setDelegate:delegate.get()];
    143   [button_ setAttachedMenu:menu];
    144   [button_ setOpenMenuOnClick:YES];
    145   // Right click is enabled.
    146   [button_ setOpenMenuOnRightClick:YES];
    147 
    148   EXPECT_FALSE([delegate isOpen]);
    149   EXPECT_FALSE([delegate didOpen]);
    150 
    151   // Should open the menu.
    152   NSEvent* event = MouseDownEvent(NSRightMouseDown);
    153   [button_ rightMouseDown:event];
    154 
    155   EXPECT_TRUE([delegate didOpen]);
    156   EXPECT_FALSE([delegate isOpen]);
    157 }
    158 
    159 TEST_F(MenuButtonTest, DontOpenOnRightClickWithoutSetRightClick) {
    160   base::scoped_nsobject<NSMenu> menu(CreateMenu());
    161   ASSERT_TRUE(menu.get());
    162 
    163   base::scoped_nsobject<MenuButtonTestDelegate> delegate(
    164       [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
    165   ASSERT_TRUE(delegate.get());
    166 
    167   [menu setDelegate:delegate.get()];
    168   [button_ setAttachedMenu:menu];
    169   [button_ setOpenMenuOnClick:YES];
    170 
    171   EXPECT_FALSE([delegate isOpen]);
    172   EXPECT_FALSE([delegate didOpen]);
    173 
    174   // Should not open the menu.
    175   NSEvent* event = MouseDownEvent(NSRightMouseDown);
    176   [button_ rightMouseDown:event];
    177 
    178   EXPECT_FALSE([delegate didOpen]);
    179   EXPECT_FALSE([delegate isOpen]);
    180 
    181   // Should open the menu in this case.
    182   [button_ performClick:nil];
    183 
    184   EXPECT_TRUE([delegate didOpen]);
    185   EXPECT_FALSE([delegate isOpen]);
    186 }
    187 
    188 }  // namespace
    189