Chromium Code Reviews| Index: chrome/browser/ui/cocoa/permission_bubble_controller_unittest.mm |
| diff --git a/chrome/browser/ui/cocoa/permission_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/permission_bubble_controller_unittest.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..792224b560ccd5f7159ba42869267cf6932cecdd |
| --- /dev/null |
| +++ b/chrome/browser/ui/cocoa/permission_bubble_controller_unittest.mm |
| @@ -0,0 +1,294 @@ |
| +// 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/permission_bubble_controller.h" |
| + |
| +#include "base/strings/sys_string_conversions.h" |
| +#include "base/strings/utf_string_conversions.h" |
| +#import "chrome/browser/ui/cocoa/cocoa_test_helper.h" |
| +#import "chrome/browser/ui/cocoa/permission_bubble_cocoa.h" |
| +#include "chrome/browser/ui/cocoa/run_loop_testing.h" |
| +#include "chrome/browser/ui/website_settings/mock_permission_bubble_delegate.h" |
| + |
| +@interface PermissionBubbleController (ExposedForTesting) |
| +- (void)ok; |
| +- (void)allow; |
| +- (void)block; |
| +- (void)customize; |
| +- (void)checkboxChanged:(id)sender; |
| +@end |
| + |
| +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()); |
| + |
| + virtual void SetUp() OVERRIDE { |
| + CocoaTest::SetUp(); |
| + bridge_.reset(new PermissionBubbleCocoa(nil)); |
| + controller_ = [[PermissionBubbleController alloc] |
| + initWithParentWindow:test_window() |
| + bridge:bridge_.get()]; |
| + } |
| + |
| + virtual void TearDown() OVERRIDE { |
| + [controller_ close]; |
| + chrome::testing::NSRunLoopRunAllPending(); |
| + CocoaTest::TearDown(); |
| + } |
| + |
| + NSButton* FindButtonWithTitle(NSView* parent, |
| + const base::string16& text) { |
| + NSString* title = base::SysUTF16ToNSString(text); |
| + for (NSView* child in [parent subviews]) { |
| + if ([child isKindOfClass:[NSButton class]]) { |
| + NSButton* button = (NSButton*)child; |
|
groby-ooo-7-16
2014/01/31 22:31:51
base::ObjCCast
leng
2014/02/03 22:38:04
Done.
|
| + if ([title isEqualToString:[button title]]) { |
| + return button; |
| + } |
| + } |
| + } |
| + return nil; |
| + } |
| + |
| + NSTextField* FindTextFieldWithString(NSView* parent, |
| + const base::string16& text, |
| + BOOL exactMatch) { |
| + NSString* title = base::SysUTF16ToNSString(text); |
| + for (NSView* child in [parent subviews]) { |
| + if ([child isKindOfClass:[NSTextField class]]) { |
| + NSTextField* textField = (NSTextField*)child; |
| + // When multiple requests are made, a bullet point will be inserted |
| + // at the beginning of every line. So in that case, only a partial |
| + // match is required. For a single request, expect an exact match. |
|
groby-ooo-7-16
2014/01/31 22:31:51
You can probably always test hasSuffix and skip th
leng
2014/02/03 22:38:04
You're right.
Done.
|
| + if ([title isEqualToString:[textField stringValue]]) { |
| + return textField; |
| + } else if (!exactMatch && [[textField stringValue] hasSuffix:title]) { |
| + return textField; |
| + } |
| + } |
| + } |
| + return nil; |
| + } |
| + |
| + protected: |
| + PermissionBubbleController* controller_; // Weak; it deletes itself. |
| + scoped_ptr<PermissionBubbleCocoa> bridge_; |
| +}; |
| + |
| +TEST_F(PermissionBubbleControllerTest, ShowAndClose) { |
| + EXPECT_FALSE([[controller_ window] isVisible]); |
| + [controller_ showWindow:nil]; |
| + EXPECT_TRUE([[controller_ window] isVisible]); |
| +} |
| + |
| +TEST_F(PermissionBubbleControllerTest, ShowSinglePermission) { |
| + MockPermissionBubbleDelegate delegate_a; |
| + base::string16 permission_a = base::UTF8ToUTF16("Permission A"); |
| + delegate_a.SetText(permission_a); |
| + EXPECT_CALL(delegate_a, GetMessageTextFragment()).Times(1); |
| + |
| + std::vector<PermissionBubbleDelegate*> requests; |
| + requests.push_back(&delegate_a); |
| + std::vector<bool> acceptStates; |
| + |
| + [controller_ showAtAnchor:NSMakePoint(0, 0) |
|
groby-ooo-7-16
2014/01/31 22:31:51
NSZeroPoint
leng
2014/02/03 22:38:04
Done.
|
| + withDelegate:this |
| + forRequests:requests |
| + acceptStates:acceptStates |
| + customizationMode:NO]; |
| + |
| + NSView* bubble = (NSView*)[controller_ bubble]; |
| + NSTextField* textField = FindTextFieldWithString(bubble, permission_a, true); |
|
groby-ooo-7-16
2014/01/31 22:31:51
Since the fixture has controller_, and you never s
leng
2014/02/03 22:38:04
Done. It's much simpler now, thanks!
|
| + EXPECT_TRUE(textField); |
| + NSButton* allowButton = |
| + FindButtonWithTitle(bubble, base::UTF8ToUTF16("Allow")); |
| + EXPECT_TRUE(allowButton); |
| + NSButton* blockButton = |
| + FindButtonWithTitle(bubble, base::UTF8ToUTF16("Block")); |
| + EXPECT_TRUE(blockButton); |
| + NSButton* okButton = FindButtonWithTitle(bubble, base::UTF8ToUTF16("OK")); |
| + EXPECT_FALSE(okButton); |
| +} |
| + |
| +TEST_F(PermissionBubbleControllerTest, ShowMultiplePermissions) { |
| + MockPermissionBubbleDelegate delegate_a; |
| + MockPermissionBubbleDelegate delegate_b; |
| + MockPermissionBubbleDelegate delegate_c; |
| + base::string16 permission_a = base::UTF8ToUTF16("Permission A"); |
| + base::string16 permission_b = base::UTF8ToUTF16("Permission B"); |
| + base::string16 permission_c = base::UTF8ToUTF16("Permission C"); |
| + delegate_a.SetText(permission_a); |
|
groby-ooo-7-16
2014/01/31 22:31:51
Is it possible to take the text in the ctor? And d
leng
2014/02/03 22:38:04
Done. Fewer lines of code is better, especially i
|
| + delegate_b.SetText(permission_b); |
| + delegate_c.SetText(permission_c); |
| + EXPECT_CALL(delegate_a, GetMessageTextFragment()).Times(1); |
| + EXPECT_CALL(delegate_b, GetMessageTextFragment()).Times(1); |
| + EXPECT_CALL(delegate_c, GetMessageTextFragment()).Times(1); |
| + |
| + std::vector<PermissionBubbleDelegate*> requests; |
| + requests.push_back(&delegate_a); |
| + requests.push_back(&delegate_b); |
| + requests.push_back(&delegate_c); |
| + std::vector<bool> acceptStates; |
| + |
| + [controller_ showAtAnchor:NSMakePoint(0, 0) |
| + withDelegate:this |
| + forRequests:requests |
| + acceptStates:acceptStates |
| + customizationMode:NO]; |
| + |
| + NSView* bubble = (NSView*)[controller_ bubble]; |
| + NSTextField* textField = FindTextFieldWithString(bubble, permission_a, false); |
| + EXPECT_TRUE(textField); |
| + textField = FindTextFieldWithString(bubble, permission_b, false); |
| + EXPECT_TRUE(textField); |
| + textField = FindTextFieldWithString(bubble, permission_c, false); |
| + EXPECT_TRUE(textField); |
| + |
| + NSButton* allowButton = FindButtonWithTitle(bubble, |
| + base::UTF8ToUTF16("Allow")); |
| + EXPECT_TRUE(allowButton); |
| + NSButton* blockButton = FindButtonWithTitle(bubble, |
| + base::UTF8ToUTF16("Block")); |
| + EXPECT_TRUE(blockButton); |
| + NSButton* okButton = FindButtonWithTitle(bubble, base::UTF8ToUTF16("OK")); |
| + EXPECT_FALSE(okButton); |
| +} |
| + |
| +TEST_F(PermissionBubbleControllerTest, ShowCustomizationMode) { |
| + MockPermissionBubbleDelegate delegate_a; |
| + MockPermissionBubbleDelegate delegate_b; |
| + base::string16 permission_a = base::UTF8ToUTF16("Permission A"); |
| + base::string16 permission_b = base::UTF8ToUTF16("Permission B"); |
| + delegate_a.SetText(permission_a); |
| + delegate_b.SetText(permission_b); |
| + EXPECT_CALL(delegate_a, GetMessageTextFragment()).Times(1); |
| + EXPECT_CALL(delegate_b, GetMessageTextFragment()).Times(1); |
| + |
| + std::vector<PermissionBubbleDelegate*> requests; |
| + requests.push_back(&delegate_a); |
| + requests.push_back(&delegate_b); |
| + |
| + std::vector<bool> acceptStates; |
| + acceptStates.push_back(true); |
| + acceptStates.push_back(false); |
| + |
| + [controller_ showAtAnchor:NSMakePoint(0, 0) |
| + withDelegate:this |
| + forRequests:requests |
| + acceptStates:acceptStates |
| + customizationMode:YES]; |
| + |
| + // Test that each checkbox is visible and only the first is checked. |
| + NSView* bubble = (NSView*)[controller_ bubble]; |
| + NSButton* checkbox_a = FindButtonWithTitle(bubble, permission_a); |
| + NSButton* checkbox_b = FindButtonWithTitle(bubble, permission_b); |
| + EXPECT_TRUE(checkbox_a); |
| + EXPECT_TRUE(checkbox_b); |
| + EXPECT_EQ(NSOnState, [checkbox_a state]); |
| + EXPECT_EQ(NSOffState, [checkbox_b state]); |
| + |
| + NSButton* okButton = FindButtonWithTitle(bubble, base::UTF8ToUTF16("OK")); |
| + EXPECT_TRUE(okButton); |
| + NSButton* allowButton = |
| + FindButtonWithTitle(bubble, base::UTF8ToUTF16("Allow")); |
| + EXPECT_FALSE(allowButton); |
| + NSButton* blockButton = |
| + FindButtonWithTitle(bubble, base::UTF8ToUTF16("Block")); |
| + EXPECT_FALSE(blockButton); |
| +} |
| + |
| +TEST_F(PermissionBubbleControllerTest, OK) { |
|
groby-ooo-7-16
2014/01/31 22:31:51
I'm not sure you need these tests - all of these f
leng
2014/02/03 22:38:04
I changed them all to push the button, so they're
|
| + std::vector<PermissionBubbleDelegate*> requests; |
| + std::vector<bool> acceptStates; |
| + [controller_ showAtAnchor:NSMakePoint(0, 0) |
| + withDelegate:this |
| + forRequests:requests |
| + acceptStates:acceptStates |
| + customizationMode:NO]; |
| + |
| + EXPECT_CALL(*this, Closing()).Times(1); |
| + [controller_ ok]; |
| +} |
| + |
| +TEST_F(PermissionBubbleControllerTest, Allow) { |
| + std::vector<PermissionBubbleDelegate*> requests; |
| + std::vector<bool> acceptStates; |
| + [controller_ showAtAnchor:NSMakePoint(0, 0) |
| + withDelegate:this |
| + forRequests:requests |
| + acceptStates:acceptStates |
| + customizationMode:NO]; |
| + |
| + EXPECT_CALL(*this, Accept()).Times(1); |
| + [controller_ allow]; |
| +} |
| + |
| +TEST_F(PermissionBubbleControllerTest, Deny) { |
| + std::vector<PermissionBubbleDelegate*> requests; |
| + std::vector<bool> acceptStates; |
| + [controller_ showAtAnchor:NSMakePoint(0, 0) |
| + withDelegate:this |
| + forRequests:requests |
| + acceptStates:acceptStates |
| + customizationMode:NO]; |
| + |
| + EXPECT_CALL(*this, Deny()).Times(1); |
| + [controller_ block]; |
| +} |
| + |
| +TEST_F(PermissionBubbleControllerTest, ToggleCheckbox) { |
| + MockPermissionBubbleDelegate delegate_a; |
| + MockPermissionBubbleDelegate delegate_b; |
| + base::string16 permission_a = base::UTF8ToUTF16("Permission A"); |
| + base::string16 permission_b = base::UTF8ToUTF16("Permission B"); |
| + delegate_a.SetText(permission_a); |
| + delegate_b.SetText(permission_b); |
| + EXPECT_CALL(delegate_a, GetMessageTextFragment()).Times(1); |
| + EXPECT_CALL(delegate_b, GetMessageTextFragment()).Times(1); |
| + |
| + std::vector<PermissionBubbleDelegate*> requests; |
| + requests.push_back(&delegate_a); |
| + requests.push_back(&delegate_b); |
| + |
| + std::vector<bool> acceptStates; |
| + acceptStates.push_back(true); |
| + acceptStates.push_back(false); |
| + |
| + [controller_ showAtAnchor:NSMakePoint(0, 0) |
| + withDelegate:this |
| + forRequests:requests |
| + acceptStates:acceptStates |
| + customizationMode:YES]; |
| + |
| + NSButton* checkbox_a = |
| + FindButtonWithTitle((NSView*)[controller_ bubble], permission_a); |
| + NSButton* checkbox_b = |
| + FindButtonWithTitle((NSView*)[controller_ bubble], permission_b); |
| + |
| + // Because calling -checkboxChanged: directly does not change the state of |
| + // the NSButton, expect the same toggle value as was set originally. |
|
groby-ooo-7-16
2014/01/31 22:31:51
You can simulate a button press by [button perform
leng
2014/02/03 22:38:04
Done - Thanks for the suggestion!
|
| + EXPECT_CALL(*this, ToggleAccept(0, true)).Times(1); |
| + EXPECT_CALL(*this, ToggleAccept(1, false)).Times(1); |
| + [controller_ checkboxChanged:checkbox_a]; |
| + [controller_ checkboxChanged:checkbox_b]; |
| +} |
| + |
| +TEST_F(PermissionBubbleControllerTest, ClickCustomize) { |
| + std::vector<PermissionBubbleDelegate*> requests; |
| + std::vector<bool> acceptStates; |
| + [controller_ showAtAnchor:NSMakePoint(0, 0) |
| + withDelegate:this |
| + forRequests:requests |
| + acceptStates:acceptStates |
| + customizationMode:NO]; |
| + |
| + EXPECT_CALL(*this, SetCustomizationMode()).Times(1); |
| + [controller_ customize]; |
| +} |