Index: chrome/browser/ui/cocoa/accelerators_cocoa_browsertest.mm |
diff --git a/chrome/browser/ui/cocoa/accelerators_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/accelerators_cocoa_browsertest.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..eda644e479d0632f312527ec9753f1d8aded4569 |
--- /dev/null |
+++ b/chrome/browser/ui/cocoa/accelerators_cocoa_browsertest.mm |
@@ -0,0 +1,133 @@ |
+// Copyright (c) 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import <Cocoa/Cocoa.h> |
+ |
+#include "base/logging.h" |
+#import "chrome/browser/ui/cocoa/accelerators_cocoa.h" |
+#include "chrome/test/base/in_process_browser_test.h" |
+#include "ui/base/accelerators/platform_accelerator_cocoa.h" |
+#import "ui/events/keycodes/keyboard_code_conversion_mac.h" |
+#include "testing/gtest_mac.h" |
+ |
+typedef InProcessBrowserTest AcceleratorsCocoaBrowserTest; |
+ |
+namespace { |
+ |
+// Adds all NSMenuItems with an accelerator to the array. |
+void AddAcceleratorItemsToArray(NSMenu* menu, NSMutableArray* array) { |
+ for (NSMenuItem* item in [menu itemArray]) { |
+ NSMenu* submenu = item.submenu; |
+ if (submenu) |
+ AddAcceleratorItemsToArray(submenu, array); |
+ |
+ if (item.keyEquivalent.length > 0) |
+ [array addObject:item]; |
+ } |
+} |
+ |
+// Returns the NSMenuItem that has the given keyEquivalent and modifiers, or |
+// nil. |
+NSMenuItem* MenuContainsAccelerator(NSMenu* menu, |
+ NSString* key_equivalent, |
+ NSUInteger modifiers) { |
+ for (NSMenuItem* item in [menu itemArray]) { |
+ NSMenu* submenu = item.submenu; |
+ if (submenu) { |
+ NSMenuItem* result = |
+ MenuContainsAccelerator(submenu, key_equivalent, modifiers); |
+ if (result) |
+ return result; |
+ } |
+ |
+ if ([item.keyEquivalent isEqual:key_equivalent]) { |
+ BOOL maskEqual = |
+ (modifiers == item.keyEquivalentModifierMask) || |
+ ((modifiers & (~NSShiftKeyMask)) == item.keyEquivalentModifierMask); |
+ if (maskEqual) |
+ return item; |
+ } |
+ } |
+ return nil; |
+} |
+ |
+} // namespace |
+ |
+// Checks that each NSMenuItem in the main menu has a corresponding accelerator, |
+// and the keyEquivalent/modifiers match. |
+IN_PROC_BROWSER_TEST_F(AcceleratorsCocoaBrowserTest, |
+ MainMenuAcceleratorsInMapping) { |
+ NSMenu* menu = [NSApp mainMenu]; |
+ NSMutableArray* array = [NSMutableArray array]; |
+ AddAcceleratorItemsToArray(menu, array); |
+ |
+ for (NSMenuItem* item in array) { |
+ NSInteger command_id = item.tag; |
+ AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance(); |
+ const ui::Accelerator* accelerator; |
+ |
+ // If the tag is zero, then the NSMenuItem must use a custom selector. |
+ // Check that the accelerator is present as an un-mapped accelerator. |
+ if (command_id == 0) { |
+ accelerator = keymap->GetAcceleratorForHotKey( |
+ item.keyEquivalent, item.keyEquivalentModifierMask); |
+ |
+ EXPECT_TRUE(accelerator); |
+ return; |
+ } |
+ |
+ // If the tag isn't zero, then it must correspond to an IDC_* command. |
+ accelerator = keymap->GetAcceleratorForCommand(command_id); |
+ EXPECT_TRUE(accelerator); |
+ if (!accelerator) |
+ continue; |
+ |
+ // Get the Cocoa key_equivalent associated with the accelerator. |
+ const ui::PlatformAcceleratorCocoa* platform_accelerator = |
+ static_cast<const ui::PlatformAcceleratorCocoa*>( |
+ accelerator->platform_accelerator()); |
+ NSString* key_equivalent = platform_accelerator->characters(); |
+ |
+ // Check that the menu item's keyEquivalent matches the one from the |
+ // Cocoa accelerator map. |
+ EXPECT_NSEQ(key_equivalent, item.keyEquivalent); |
+ |
+ // Check that the menu item's modifier mask matches the one stored in the |
+ // accelerator. A mask that include NSShiftKeyMask may not include the |
+ // relevant bit (the information is reflected in the keyEquivalent of the |
+ // NSMenuItem). |
+ NSUInteger mask = platform_accelerator->modifier_mask(); |
+ BOOL maskEqual = |
+ (mask == item.keyEquivalentModifierMask) || |
+ ((mask & (~NSShiftKeyMask)) == item.keyEquivalentModifierMask); |
+ EXPECT_TRUE(maskEqual); |
+ } |
+} |
+ |
+// Check that each accelerator with a command_id has an associated NSMenuItem |
+// in the main menu. If the selector is commandDispatch:, then the tag must |
+// match the command_id. |
+IN_PROC_BROWSER_TEST_F(AcceleratorsCocoaBrowserTest, |
+ MappingAcceleratorsInMainMenu) { |
+ AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance(); |
+ for (AcceleratorsCocoa::AcceleratorMap::iterator it = |
+ keymap->accelerators_.begin(); |
+ it != keymap->accelerators_.end(); |
+ ++it) { |
+ const ui::PlatformAcceleratorCocoa* platform_accelerator = |
+ static_cast<const ui::PlatformAcceleratorCocoa*>( |
+ it->second.platform_accelerator()); |
+ |
+ // Check that there exists a corresponding NSMenuItem. |
+ NSMenuItem* item = |
+ MenuContainsAccelerator([NSApp mainMenu], |
+ platform_accelerator->characters(), |
+ platform_accelerator->modifier_mask()); |
+ EXPECT_TRUE(item); |
+ |
+ // If the menu uses a commandDispatch:, the tag must match the command id! |
+ if (item.action == @selector(commandDispatch:)) |
+ EXPECT_EQ(item.tag, it->first); |
+ } |
+} |