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.
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"
10 @interface MenuButtonTestDelegate : NSObject<NSMenuDelegate> {
12 base::scoped_nsobject<NSMenu> menu_;
20 @implementation MenuButtonTestDelegate
21 - (id)initWithMenu:(NSMenu*)menu {
22 if ((self = [super init])) {
23 menu_.reset([menu retain]);
36 - (void)menuWillOpen:(NSMenu*)menu {
37 EXPECT_EQ(menu_.get(), menu);
41 NSArray* modes = [NSArray arrayWithObjects:NSEventTrackingRunLoopMode,
44 [menu performSelector:@selector(cancelTracking)
50 - (void)menuDidClose:(NSMenu*)menu {
51 EXPECT_EQ(menu_.get(), menu);
59 class MenuButtonTest : public CocoaTest {
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_];
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];
81 NSEvent* MouseDownEvent(NSEventType eventType) {
83 location.x = location.y = 0;
84 NSGraphicsContext* context = [NSGraphicsContext currentContext];
85 NSEvent* event = [NSEvent mouseEventWithType:eventType
101 TEST_VIEW(MenuButtonTest, button_);
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());
108 [button_ setAttachedMenu:menu];
109 EXPECT_TRUE([button_ attachedMenu]);
112 TEST_F(MenuButtonTest, OpenOnClick) {
113 base::scoped_nsobject<NSMenu> menu(CreateMenu());
114 ASSERT_TRUE(menu.get());
116 base::scoped_nsobject<MenuButtonTestDelegate> delegate(
117 [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
118 ASSERT_TRUE(delegate.get());
120 [menu setDelegate:delegate.get()];
121 [button_ setAttachedMenu:menu];
122 [button_ setOpenMenuOnClick:YES];
124 EXPECT_FALSE([delegate isOpen]);
125 EXPECT_FALSE([delegate didOpen]);
127 // Should open the menu.
128 [button_ performClick:nil];
130 EXPECT_TRUE([delegate didOpen]);
131 EXPECT_FALSE([delegate isOpen]);
134 TEST_F(MenuButtonTest, OpenOnRightClick) {
135 base::scoped_nsobject<NSMenu> menu(CreateMenu());
136 ASSERT_TRUE(menu.get());
138 base::scoped_nsobject<MenuButtonTestDelegate> delegate(
139 [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
140 ASSERT_TRUE(delegate.get());
142 [menu setDelegate:delegate.get()];
143 [button_ setAttachedMenu:menu];
144 [button_ setOpenMenuOnClick:YES];
145 // Right click is enabled.
146 [button_ setOpenMenuOnRightClick:YES];
148 EXPECT_FALSE([delegate isOpen]);
149 EXPECT_FALSE([delegate didOpen]);
151 // Should open the menu.
152 NSEvent* event = MouseDownEvent(NSRightMouseDown);
153 [button_ rightMouseDown:event];
155 EXPECT_TRUE([delegate didOpen]);
156 EXPECT_FALSE([delegate isOpen]);
159 TEST_F(MenuButtonTest, DontOpenOnRightClickWithoutSetRightClick) {
160 base::scoped_nsobject<NSMenu> menu(CreateMenu());
161 ASSERT_TRUE(menu.get());
163 base::scoped_nsobject<MenuButtonTestDelegate> delegate(
164 [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
165 ASSERT_TRUE(delegate.get());
167 [menu setDelegate:delegate.get()];
168 [button_ setAttachedMenu:menu];
169 [button_ setOpenMenuOnClick:YES];
171 EXPECT_FALSE([delegate isOpen]);
172 EXPECT_FALSE([delegate didOpen]);
174 // Should not open the menu.
175 NSEvent* event = MouseDownEvent(NSRightMouseDown);
176 [button_ rightMouseDown:event];
178 EXPECT_FALSE([delegate didOpen]);
179 EXPECT_FALSE([delegate isOpen]);
181 // Should open the menu in this case.
182 [button_ performClick:nil];
184 EXPECT_TRUE([delegate didOpen]);
185 EXPECT_FALSE([delegate isOpen]);
188 TEST_F(MenuButtonTest, OpenOnAccessibilityPerformAction) {
189 base::scoped_nsobject<NSMenu> menu(CreateMenu());
190 ASSERT_TRUE(menu.get());
192 base::scoped_nsobject<MenuButtonTestDelegate> delegate(
193 [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
194 ASSERT_TRUE(delegate.get());
196 [menu setDelegate:delegate.get()];
197 [button_ setAttachedMenu:menu];
198 NSCell* buttonCell = [button_ cell];
200 EXPECT_FALSE([delegate isOpen]);
201 EXPECT_FALSE([delegate didOpen]);
203 [button_ setOpenMenuOnClick:YES];
205 // NSAccessibilityShowMenuAction should not be available but
206 // NSAccessibilityPressAction should.
207 NSArray* actionNames = [buttonCell accessibilityActionNames];
208 EXPECT_FALSE([actionNames containsObject:NSAccessibilityShowMenuAction]);
209 EXPECT_TRUE([actionNames containsObject:NSAccessibilityPressAction]);
211 [button_ setOpenMenuOnClick:NO];
213 // NSAccessibilityPressAction should not be the one used to open the menu now.
214 actionNames = [buttonCell accessibilityActionNames];
215 EXPECT_TRUE([actionNames containsObject:NSAccessibilityShowMenuAction]);
216 EXPECT_TRUE([actionNames containsObject:NSAccessibilityPressAction]);
218 [buttonCell accessibilityPerformAction:NSAccessibilityShowMenuAction];
219 EXPECT_TRUE([delegate didOpen]);
220 EXPECT_FALSE([delegate isOpen]);
223 TEST_F(MenuButtonTest, OpenOnAccessibilityPerformActionWithSetRightClick) {
224 base::scoped_nsobject<NSMenu> menu(CreateMenu());
225 ASSERT_TRUE(menu.get());
227 base::scoped_nsobject<MenuButtonTestDelegate> delegate(
228 [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
229 ASSERT_TRUE(delegate.get());
231 [menu setDelegate:delegate.get()];
232 [button_ setAttachedMenu:menu];
233 NSCell* buttonCell = [button_ cell];
235 EXPECT_FALSE([delegate isOpen]);
236 EXPECT_FALSE([delegate didOpen]);
238 [button_ setOpenMenuOnClick:YES];
240 // Command to open the menu should not be available.
241 NSArray* actionNames = [buttonCell accessibilityActionNames];
242 EXPECT_FALSE([actionNames containsObject:NSAccessibilityShowMenuAction]);
244 [button_ setOpenMenuOnRightClick:YES];
246 // Command to open the menu should now become available.
247 actionNames = [buttonCell accessibilityActionNames];
248 EXPECT_TRUE([actionNames containsObject:NSAccessibilityShowMenuAction]);
250 [button_ setOpenMenuOnClick:NO];
252 // Command should still be available, even when both click + hold and right
253 // click are turned on.
254 actionNames = [buttonCell accessibilityActionNames];
255 EXPECT_TRUE([actionNames containsObject:NSAccessibilityShowMenuAction]);
257 [buttonCell accessibilityPerformAction:NSAccessibilityShowMenuAction];
258 EXPECT_TRUE([delegate didOpen]);
259 EXPECT_FALSE([delegate isOpen]);