1 // Copyright 2015 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/logging.h"
6 #import "base/mac/foundation_util.h"
7 #import "base/mac/scoped_nsobject.h"
8 #include "base/strings/utf_string_conversions.h"
9 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
10 #import "chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac.h"
11 #include "chrome/browser/ui/cocoa/run_loop_testing.h"
12 #include "chrome/browser/ui/toolbar/test_toolbar_actions_bar_bubble_delegate.h"
13 #import "ui/events/test/cocoa_test_event_utils.h"
15 // A simple class to observe when a window is destructing.
16 @interface WindowObserver : NSObject {
17 BOOL windowIsClosing_;
20 - (id)initWithWindow:(NSWindow*)window;
24 - (void)onWindowClosing:(NSNotification*)notification;
26 @property(nonatomic, assign) BOOL windowIsClosing;
30 @implementation WindowObserver
32 - (id)initWithWindow:(NSWindow*)window {
33 if ((self = [super init])) {
34 [[NSNotificationCenter defaultCenter]
36 selector:@selector(onWindowClosing:)
37 name:NSWindowWillCloseNotification
44 [[NSNotificationCenter defaultCenter] removeObserver:self];
48 - (void)onWindowClosing:(NSNotification*)notification {
49 windowIsClosing_ = YES;
52 @synthesize windowIsClosing = windowIsClosing_;
56 class ToolbarActionsBarBubbleMacTest : public CocoaTest {
58 ToolbarActionsBarBubbleMacTest() {}
59 ~ToolbarActionsBarBubbleMacTest() override {}
61 void SetUp() override;
63 // Create and display a new bubble with the given |delegate|.
64 ToolbarActionsBarBubbleMac* CreateAndShowBubble(
65 TestToolbarActionsBarBubbleDelegate* delegate);
67 // Test that clicking on the corresponding button produces the
68 // |expected_action|, and closes the bubble.
69 void TestBubbleButton(
70 ToolbarActionsBarBubbleDelegate::CloseAction expected_action);
72 base::string16 HeadingString() { return base::ASCIIToUTF16("Heading"); }
73 base::string16 BodyString() { return base::ASCIIToUTF16("Body"); }
74 base::string16 ActionString() { return base::ASCIIToUTF16("Action"); }
75 base::string16 DismissString() { return base::ASCIIToUTF16("Dismiss"); }
76 base::string16 LearnMoreString() { return base::ASCIIToUTF16("LearnMore"); }
77 base::string16 ItemListString() { return base::ASCIIToUTF16("ItemList"); }
80 DISALLOW_COPY_AND_ASSIGN(ToolbarActionsBarBubbleMacTest);
83 void ToolbarActionsBarBubbleMacTest::SetUp() {
85 [ToolbarActionsBarBubbleMac setAnimationEnabledForTesting:NO];
88 ToolbarActionsBarBubbleMac* ToolbarActionsBarBubbleMacTest::CreateAndShowBubble(
89 TestToolbarActionsBarBubbleDelegate* delegate) {
90 ToolbarActionsBarBubbleMac* bubble =
91 [[ToolbarActionsBarBubbleMac alloc]
92 initWithParentWindow:test_window()
93 anchorPoint:NSZeroPoint
94 delegate:delegate->GetDelegate()];
95 EXPECT_FALSE(delegate->shown());
96 [bubble showWindow:nil];
97 chrome::testing::NSRunLoopRunAllPending();
98 EXPECT_FALSE(delegate->close_action());
99 EXPECT_TRUE(delegate->shown());
103 void ToolbarActionsBarBubbleMacTest::TestBubbleButton(
104 ToolbarActionsBarBubbleDelegate::CloseAction expected_action) {
105 TestToolbarActionsBarBubbleDelegate delegate(
106 HeadingString(), BodyString(), ActionString());
107 delegate.set_dismiss_button_text(DismissString());
108 delegate.set_learn_more_button_text(LearnMoreString());
109 ToolbarActionsBarBubbleMac* bubble = CreateAndShowBubble(&delegate);
110 base::scoped_nsobject<WindowObserver> windowObserver(
111 [[WindowObserver alloc] initWithWindow:[bubble window]]);
112 EXPECT_FALSE([windowObserver windowIsClosing]);
114 // Find the appropriate button to click.
115 NSButton* button = nil;
116 switch (expected_action) {
117 case ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE:
118 button = [bubble actionButton];
120 case ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS:
121 button = [bubble dismissButton];
123 case ToolbarActionsBarBubbleDelegate::CLOSE_LEARN_MORE:
124 button = [bubble learnMoreButton];
130 std::pair<NSEvent*, NSEvent*> events =
131 cocoa_test_event_utils::MouseClickInView(button, 1);
132 [NSApp postEvent:events.second atStart:YES];
133 [NSApp sendEvent:events.first];
134 chrome::testing::NSRunLoopRunAllPending();
136 // The bubble should be closed, and the delegate should be told that the
137 // button was clicked.
138 ASSERT_TRUE(delegate.close_action());
139 EXPECT_EQ(expected_action, *delegate.close_action());
140 EXPECT_TRUE([windowObserver windowIsClosing]);
143 // Test clicking on the action button and dismissing the bubble.
144 TEST_F(ToolbarActionsBarBubbleMacTest, CloseActionAndDismiss) {
145 // Test all the possible actions.
146 TestBubbleButton(ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE);
147 TestBubbleButton(ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS);
148 TestBubbleButton(ToolbarActionsBarBubbleDelegate::CLOSE_LEARN_MORE);
151 // Test dismissing the bubble without clicking the button.
152 TestToolbarActionsBarBubbleDelegate delegate(
153 HeadingString(), BodyString(), ActionString());
154 ToolbarActionsBarBubbleMac* bubble = CreateAndShowBubble(&delegate);
155 base::scoped_nsobject<WindowObserver> windowObserver(
156 [[WindowObserver alloc] initWithWindow:[bubble window]]);
157 EXPECT_FALSE([windowObserver windowIsClosing]);
159 // Close the bubble. The delegate should be told it was dismissed.
161 chrome::testing::NSRunLoopRunAllPending();
162 ASSERT_TRUE(delegate.close_action());
163 EXPECT_EQ(ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS,
164 *delegate.close_action());
165 EXPECT_TRUE([windowObserver windowIsClosing]);
169 // Test the basic layout of the bubble.
170 TEST_F(ToolbarActionsBarBubbleMacTest, ToolbarActionsBarBubbleLayout) {
171 // Test with no optional fields.
173 TestToolbarActionsBarBubbleDelegate delegate(
174 HeadingString(), BodyString(), ActionString());
175 ToolbarActionsBarBubbleMac* bubble = CreateAndShowBubble(&delegate);
176 EXPECT_TRUE([bubble actionButton]);
177 EXPECT_FALSE([bubble learnMoreButton]);
178 EXPECT_FALSE([bubble dismissButton]);
179 EXPECT_FALSE([bubble itemList]);
182 chrome::testing::NSRunLoopRunAllPending();
185 // Test with all possible buttons (action, learn more, dismiss).
187 TestToolbarActionsBarBubbleDelegate delegate(
188 HeadingString(), BodyString(), ActionString());
189 delegate.set_dismiss_button_text(DismissString());
190 delegate.set_learn_more_button_text(LearnMoreString());
191 ToolbarActionsBarBubbleMac* bubble = CreateAndShowBubble(&delegate);
192 EXPECT_TRUE([bubble actionButton]);
193 EXPECT_TRUE([bubble learnMoreButton]);
194 EXPECT_TRUE([bubble dismissButton]);
195 EXPECT_FALSE([bubble itemList]);
198 chrome::testing::NSRunLoopRunAllPending();
201 // Test with only a dismiss button (no action button).
203 TestToolbarActionsBarBubbleDelegate delegate(
204 HeadingString(), BodyString(), base::string16());
205 delegate.set_dismiss_button_text(DismissString());
206 ToolbarActionsBarBubbleMac* bubble = CreateAndShowBubble(&delegate);
207 EXPECT_FALSE([bubble actionButton]);
208 EXPECT_FALSE([bubble learnMoreButton]);
209 EXPECT_TRUE([bubble dismissButton]);
210 EXPECT_FALSE([bubble itemList]);
213 chrome::testing::NSRunLoopRunAllPending();
216 // Test with an action button and an item list.
218 TestToolbarActionsBarBubbleDelegate delegate(
219 HeadingString(), BodyString(), ActionString());
220 delegate.set_item_list_text(ItemListString());
221 ToolbarActionsBarBubbleMac* bubble = CreateAndShowBubble(&delegate);
222 EXPECT_TRUE([bubble actionButton]);
223 EXPECT_FALSE([bubble learnMoreButton]);
224 EXPECT_FALSE([bubble dismissButton]);
225 EXPECT_TRUE([bubble itemList]);
228 chrome::testing::NSRunLoopRunAllPending();
231 // Test with all possible fields.
233 TestToolbarActionsBarBubbleDelegate delegate(
234 HeadingString(), BodyString(), ActionString());
235 delegate.set_dismiss_button_text(DismissString());
236 delegate.set_learn_more_button_text(LearnMoreString());
237 delegate.set_item_list_text(ItemListString());
238 ToolbarActionsBarBubbleMac* bubble = CreateAndShowBubble(&delegate);
239 EXPECT_TRUE([bubble actionButton]);
240 EXPECT_TRUE([bubble learnMoreButton]);
241 EXPECT_TRUE([bubble dismissButton]);
242 EXPECT_TRUE([bubble itemList]);
245 chrome::testing::NSRunLoopRunAllPending();