| // Copyright 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 "chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.h" |
| |
| #include <Carbon/Carbon.h> |
| |
| #include "base/mac/foundation_util.h" |
| #include "base/stl_util.h" |
| #include "base/strings/sys_string_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #import "chrome/browser/ui/cocoa/cocoa_test_helper.h" |
| #include "chrome/browser/ui/cocoa/run_loop_testing.h" |
| #import "chrome/browser/ui/cocoa/website_settings/permission_bubble_cocoa.h" |
| #import "chrome/browser/ui/cocoa/website_settings/split_block_button.h" |
| #include "chrome/browser/ui/website_settings/mock_permission_bubble_request.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/l10n/l10n_util_mac.h" |
| #import "ui/events/test/cocoa_test_event_utils.h" |
| |
| @class ConstrainedWindowButton; |
| |
| @interface PermissionBubbleController (ExposedForTesting) |
| - (void)ok:(id)sender; |
| - (void)onAllow:(id)sender; |
| - (void)onBlock:(id)sender; |
| - (void)onCustomize:(id)sender; |
| - (void)onCheckboxChanged:(id)sender; |
| @end |
| |
| @interface SplitBlockButton (ExposedForTesting) |
| - (NSMenu*)menu; |
| @end |
| |
| namespace { |
| const char* const kPermissionA = "Permission A"; |
| const char* const kPermissionB = "Permission B"; |
| const char* const kPermissionC = "Permission C"; |
| } |
| |
| class PermissionBubbleControllerTest : public CocoaTest, |
| public PermissionBubbleView::Delegate { |
| public: |
| |
| MOCK_METHOD2(ToggleAccept, void(int, bool)); |
| MOCK_METHOD0(SetCustomizationMode, void()); |
| MOCK_METHOD0(Accept, void()); |
| MOCK_METHOD0(Deny, void()); |
| MOCK_METHOD0(Closing, void()); |
| MOCK_METHOD1(SetView, void(PermissionBubbleView*)); |
| |
| void SetUp() override { |
| CocoaTest::SetUp(); |
| bridge_.reset(new PermissionBubbleCocoa(nil)); |
| AddRequest(kPermissionA); |
| controller_ = [[PermissionBubbleController alloc] |
| initWithParentWindow:test_window() |
| bridge:bridge_.get()]; |
| } |
| |
| void TearDown() override { |
| [controller_ close]; |
| chrome::testing::NSRunLoopRunAllPending(); |
| STLDeleteElements(&requests_); |
| CocoaTest::TearDown(); |
| } |
| |
| void AddRequest(const std::string& title) { |
| MockPermissionBubbleRequest* request = new MockPermissionBubbleRequest( |
| title, |
| l10n_util::GetStringUTF8(IDS_PERMISSION_ALLOW), |
| l10n_util::GetStringUTF8(IDS_PERMISSION_DENY)); |
| requests_.push_back(request); |
| } |
| |
| NSButton* FindButtonWithTitle(const std::string& title) { |
| return FindButtonWithTitle(base::SysUTF8ToNSString(title), |
| [ConstrainedWindowButton class]); |
| } |
| |
| NSButton* FindButtonWithTitle(int title_id) { |
| return FindButtonWithTitle(l10n_util::GetNSString(title_id), |
| [ConstrainedWindowButton class]); |
| } |
| |
| NSButton* FindMenuButtonWithTitle(int title_id) { |
| return FindButtonWithTitle(l10n_util::GetNSString(title_id), |
| [NSPopUpButton class]); |
| } |
| |
| // IDS_PERMISSION_ALLOW and IDS_PERMISSION_DENY are used for two distinct |
| // UI elements, both of which derive from NSButton. So check the expected |
| // class, not just NSButton, as well as the title. |
| NSButton* FindButtonWithTitle(NSString* title, Class button_class) { |
| for (NSButton* view in [[controller_ bubble] subviews]) { |
| if ([view isKindOfClass:button_class] && |
| [title isEqualToString:[view title]]) { |
| return view; |
| } |
| } |
| return nil; |
| } |
| |
| NSTextField* FindTextFieldWithString(const std::string& text) { |
| NSView* parent = base::mac::ObjCCastStrict<NSView>([controller_ bubble]); |
| return FindTextFieldWithString(parent, base::SysUTF8ToNSString(text)); |
| } |
| |
| NSTextField* FindTextFieldWithString(NSView* view, NSString* text) { |
| NSTextField* textField = nil; |
| for (NSView* child in [view subviews]) { |
| textField = base::mac::ObjCCast<NSTextField>(child); |
| if (![[textField stringValue] hasSuffix:text]) { |
| textField = FindTextFieldWithString(child, text); |
| if (textField) |
| break; |
| } |
| } |
| return textField; |
| } |
| |
| void ChangePermissionMenuSelection(NSButton* menu_button, int next_title_id) { |
| NSMenu* menu = [base::mac::ObjCCastStrict<NSPopUpButton>(menu_button) menu]; |
| NSString* next_title = l10n_util::GetNSString(next_title_id); |
| EXPECT_EQ([[menu itemWithTitle:[menu_button title]] state], NSOnState); |
| NSMenuItem* next_item = [menu itemWithTitle:next_title]; |
| EXPECT_EQ([next_item state], NSOffState); |
| [menu performActionForItemAtIndex:[menu indexOfItem:next_item]]; |
| } |
| |
| protected: |
| PermissionBubbleController* controller_; // Weak; it deletes itself. |
| scoped_ptr<PermissionBubbleCocoa> bridge_; |
| std::vector<PermissionBubbleRequest*> requests_; |
| std::vector<bool> accept_states_; |
| }; |
| |
| TEST_F(PermissionBubbleControllerTest, ShowAndClose) { |
| EXPECT_FALSE([[controller_ window] isVisible]); |
| [controller_ showWindow:nil]; |
| EXPECT_TRUE([[controller_ window] isVisible]); |
| } |
| |
| TEST_F(PermissionBubbleControllerTest, ShowSinglePermission) { |
| [controller_ showAtAnchor:NSZeroPoint |
| withDelegate:this |
| forRequests:requests_ |
| acceptStates:accept_states_]; |
| |
| EXPECT_TRUE(FindTextFieldWithString(kPermissionA)); |
| EXPECT_TRUE(FindButtonWithTitle(IDS_PERMISSION_ALLOW)); |
| EXPECT_TRUE(FindButtonWithTitle(IDS_PERMISSION_DENY)); |
| EXPECT_FALSE(FindButtonWithTitle(IDS_OK)); |
| } |
| |
| TEST_F(PermissionBubbleControllerTest, ShowMultiplePermissions) { |
| AddRequest(kPermissionB); |
| AddRequest(kPermissionC); |
| |
| accept_states_.push_back(true); // A |
| accept_states_.push_back(true); // B |
| accept_states_.push_back(true); // C |
| |
| [controller_ showAtAnchor:NSZeroPoint |
| withDelegate:this |
| forRequests:requests_ |
| acceptStates:accept_states_]; |
| |
| EXPECT_TRUE(FindTextFieldWithString(kPermissionA)); |
| EXPECT_TRUE(FindTextFieldWithString(kPermissionB)); |
| EXPECT_TRUE(FindTextFieldWithString(kPermissionC)); |
| |
| EXPECT_FALSE(FindButtonWithTitle(IDS_PERMISSION_ALLOW)); |
| EXPECT_FALSE(FindButtonWithTitle(IDS_PERMISSION_DENY)); |
| EXPECT_TRUE(FindButtonWithTitle(IDS_OK)); |
| } |
| |
| TEST_F(PermissionBubbleControllerTest, ShowMultiplePermissionsAllow) { |
| AddRequest(kPermissionB); |
| |
| accept_states_.push_back(true); // A |
| accept_states_.push_back(true); // B |
| |
| [controller_ showAtAnchor:NSZeroPoint |
| withDelegate:this |
| forRequests:requests_ |
| acceptStates:accept_states_]; |
| |
| // Test that all menus have 'Allow' visible. |
| EXPECT_TRUE(FindMenuButtonWithTitle(IDS_PERMISSION_ALLOW)); |
| EXPECT_FALSE(FindMenuButtonWithTitle(IDS_PERMISSION_DENY)); |
| |
| EXPECT_TRUE(FindButtonWithTitle(IDS_OK)); |
| EXPECT_FALSE(FindButtonWithTitle(IDS_PERMISSION_ALLOW)); |
| EXPECT_FALSE(FindButtonWithTitle(IDS_PERMISSION_DENY)); |
| } |
| |
| TEST_F(PermissionBubbleControllerTest, ShowMultiplePermissionsBlock) { |
| AddRequest(kPermissionB); |
| |
| accept_states_.push_back(false); // A |
| accept_states_.push_back(false); // B |
| |
| [controller_ showAtAnchor:NSZeroPoint |
| withDelegate:this |
| forRequests:requests_ |
| acceptStates:accept_states_]; |
| |
| // Test that all menus have 'Block' visible. |
| EXPECT_TRUE(FindMenuButtonWithTitle(IDS_PERMISSION_DENY)); |
| EXPECT_FALSE(FindMenuButtonWithTitle(IDS_PERMISSION_ALLOW)); |
| |
| EXPECT_TRUE(FindButtonWithTitle(IDS_OK)); |
| EXPECT_FALSE(FindButtonWithTitle(IDS_PERMISSION_ALLOW)); |
| EXPECT_FALSE(FindButtonWithTitle(IDS_PERMISSION_DENY)); |
| } |
| |
| TEST_F(PermissionBubbleControllerTest, ShowMultiplePermissionsMixed) { |
| AddRequest(kPermissionB); |
| AddRequest(kPermissionC); |
| |
| accept_states_.push_back(false); // A |
| accept_states_.push_back(false); // B |
| accept_states_.push_back(true); // C |
| |
| [controller_ showAtAnchor:NSZeroPoint |
| withDelegate:this |
| forRequests:requests_ |
| acceptStates:accept_states_]; |
| |
| // Test that both 'allow' and 'deny' are visible. |
| EXPECT_TRUE(FindMenuButtonWithTitle(IDS_PERMISSION_DENY)); |
| EXPECT_TRUE(FindMenuButtonWithTitle(IDS_PERMISSION_ALLOW)); |
| |
| EXPECT_TRUE(FindButtonWithTitle(IDS_OK)); |
| EXPECT_FALSE(FindButtonWithTitle(IDS_PERMISSION_ALLOW)); |
| EXPECT_FALSE(FindButtonWithTitle(IDS_PERMISSION_DENY)); |
| } |
| |
| TEST_F(PermissionBubbleControllerTest, OK) { |
| AddRequest(kPermissionB); |
| |
| accept_states_.push_back(true); // A |
| accept_states_.push_back(true); // B |
| |
| [controller_ showAtAnchor:NSZeroPoint |
| withDelegate:this |
| forRequests:requests_ |
| acceptStates:accept_states_]; |
| |
| EXPECT_CALL(*this, Accept()).Times(1); |
| [FindButtonWithTitle(IDS_OK) performClick:nil]; |
| } |
| |
| TEST_F(PermissionBubbleControllerTest, Allow) { |
| [controller_ showAtAnchor:NSZeroPoint |
| withDelegate:this |
| forRequests:requests_ |
| acceptStates:accept_states_]; |
| |
| EXPECT_CALL(*this, Accept()).Times(1); |
| [FindButtonWithTitle(IDS_PERMISSION_ALLOW) performClick:nil]; |
| } |
| |
| TEST_F(PermissionBubbleControllerTest, Deny) { |
| [controller_ showAtAnchor:NSZeroPoint |
| withDelegate:this |
| forRequests:requests_ |
| acceptStates:accept_states_]; |
| |
| EXPECT_CALL(*this, Deny()).Times(1); |
| [FindButtonWithTitle(IDS_PERMISSION_DENY) performClick:nil]; |
| } |
| |
| TEST_F(PermissionBubbleControllerTest, ChangePermissionSelection) { |
| AddRequest(kPermissionB); |
| |
| accept_states_.push_back(true); // A |
| accept_states_.push_back(false); // B |
| |
| [controller_ showAtAnchor:NSZeroPoint |
| withDelegate:this |
| forRequests:requests_ |
| acceptStates:accept_states_]; |
| |
| EXPECT_CALL(*this, ToggleAccept(0, false)).Times(1); |
| EXPECT_CALL(*this, ToggleAccept(1, true)).Times(1); |
| NSButton* menu_a = FindMenuButtonWithTitle(IDS_PERMISSION_ALLOW); |
| NSButton* menu_b = FindMenuButtonWithTitle(IDS_PERMISSION_DENY); |
| ChangePermissionMenuSelection(menu_a, IDS_PERMISSION_DENY); |
| ChangePermissionMenuSelection(menu_b, IDS_PERMISSION_ALLOW); |
| } |
| |
| TEST_F(PermissionBubbleControllerTest, EscapeCloses) { |
| [controller_ showAtAnchor:NSZeroPoint |
| withDelegate:this |
| forRequests:requests_ |
| acceptStates:accept_states_]; |
| |
| EXPECT_TRUE([[controller_ window] isVisible]); |
| [[controller_ window] |
| performKeyEquivalent:cocoa_test_event_utils::KeyEventWithKeyCode( |
| kVK_Escape, '\e', NSKeyDown, 0)]; |
| EXPECT_FALSE([[controller_ window] isVisible]); |
| } |