Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / extensions / extension_installed_bubble_controller_unittest.mm
blob906edd06c74d3ffd18e07c2f510fdb827f263263
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 #import <Cocoa/Cocoa.h>
7 #include "base/basictypes.h"
8 #include "base/command_line.h"
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/path_service.h"
13 #include "base/values.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/test_extension_system.h"
16 #import "chrome/browser/ui/browser_window.h"
17 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
18 #import "chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h"
19 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "extensions/common/extension.h"
23 #include "extensions/common/manifest_constants.h"
24 #import "third_party/ocmock/OCMock/OCMock.h"
25 #include "third_party/ocmock/gtest_support.h"
26 #include "ui/gfx/codec/png_codec.h"
28 using extensions::Extension;
30 // ExtensionInstalledBubbleController with removePageActionPreview overridden
31 // to a no-op, because pageActions are not yet hooked up in the test browser.
32 @interface ExtensionInstalledBubbleControllerForTest :
33     ExtensionInstalledBubbleController {
36 // Do nothing, because browser window is not set up with page actions
37 // for unit testing.
38 - (void)removePageActionPreview;
40 @end
42 @implementation ExtensionInstalledBubbleControllerForTest
44 - (void)removePageActionPreview { }
46 @end
48 namespace keys = extensions::manifest_keys;
50 class ExtensionInstalledBubbleControllerTest : public CocoaProfileTest {
52  public:
53   void SetUp() override {
54     CocoaProfileTest::SetUp();
55     ASSERT_TRUE(browser());
56     window_ = browser()->window()->GetNativeWindow();
57     icon_ = LoadTestIcon();
58     base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
59     extension_service_ = static_cast<extensions::TestExtensionSystem*>(
60         extensions::ExtensionSystem::Get(profile()))->CreateExtensionService(
61             &command_line, base::FilePath(), false);
62   }
64   // Load test icon from extension test directory.
65   SkBitmap LoadTestIcon() {
66     base::FilePath path;
67     PathService::Get(chrome::DIR_TEST_DATA, &path);
68     path = path.AppendASCII("extensions").AppendASCII("icon1.png");
70     std::string file_contents;
71     base::ReadFileToString(path, &file_contents);
72     const unsigned char* data =
73         reinterpret_cast<const unsigned char*>(file_contents.data());
75     SkBitmap bitmap;
76     gfx::PNGCodec::Decode(data, file_contents.length(), &bitmap);
77     return bitmap;
78   }
80   // Create a skeletal framework of either page action or browser action
81   // type.  This extension only needs to have a type and a name to initialize
82   // the ExtensionInstalledBubble for unit testing.
83   scoped_refptr<Extension> CreateExtension(
84         extension_installed_bubble::ExtensionType type) {
85     base::FilePath path;
86     PathService::Get(chrome::DIR_TEST_DATA, &path);
87     path = path.AppendASCII("extensions").AppendASCII("dummy");
89     base::DictionaryValue extension_input_value;
90     extension_input_value.SetString(keys::kVersion, "1.0.0.0");
91     if (type == extension_installed_bubble::kPageAction) {
92       extension_input_value.SetString(keys::kName, "page action extension");
93       base::DictionaryValue* action = new base::DictionaryValue;
94       action->SetString(keys::kPageActionId, "ExtensionActionId");
95       action->SetString(keys::kPageActionDefaultTitle, "ExtensionActionTitle");
96       action->SetString(keys::kPageActionDefaultIcon, "image1.png");
97       extension_input_value.Set(keys::kPageAction, action);
98     } else if (type == extension_installed_bubble::kBrowserAction) {
99       extension_input_value.SetString(keys::kName, "browser action extension");
100       base::DictionaryValue* browser_action = new base::DictionaryValue;
101       // An empty dictionary is enough to create a Browser Action.
102       extension_input_value.Set(keys::kBrowserAction, browser_action);
103     } else if (type == extension_installed_bubble::kApp) {
104       extension_input_value.SetString(keys::kName, "test app");
105       extension_input_value.SetString(keys::kLaunchWebURL,
106                                       "http://www.example.com");
107     }
109     std::string error;
110     scoped_refptr<Extension> extension =
111         Extension::Create(path, extensions::Manifest::INVALID_LOCATION,
112                           extension_input_value, Extension::NO_FLAGS, &error);
113     extension_service_->AddExtension(extension.get());
114     return extension;
115   }
117   // Required to initialize the extension installed bubble.
118   NSWindow* window_;  // weak, owned by CocoaProfileTest.
120   ExtensionService* extension_service_;
122   // Skeleton extension to be tested; reinitialized for each test.
123   scoped_refptr<Extension> extension_;
125   // The icon_ to be loaded into the bubble window.
126   SkBitmap icon_;
129 // Confirm that window sizes are set correctly for a page action extension.
130 TEST_F(ExtensionInstalledBubbleControllerTest, PageActionTest) {
131   extension_ = CreateExtension(extension_installed_bubble::kPageAction);
132   ExtensionInstalledBubbleControllerForTest* controller =
133       [[ExtensionInstalledBubbleControllerForTest alloc]
134           initWithParentWindow:window_
135                      extension:extension_.get()
136                         bundle:NULL
137                        browser:browser()
138                           icon:icon_];
139   EXPECT_TRUE(controller);
141   // Initialize window without having to calculate tabstrip locations.
142   [controller initializeWindow];
143   EXPECT_TRUE([controller window]);
145   int height = [controller calculateWindowHeight];
146   // Height should equal the vertical padding + height of all messages.
147   int correctHeight = 2 * extension_installed_bubble::kOuterVerticalMargin +
148       2 * extension_installed_bubble::kInnerVerticalMargin +
149       NSHeight([controller headingFrame]) +
150       NSHeight([controller frameOfHowToUse]) +
151       NSHeight([controller frameOfHowToManage]);
152   if ([controller showSyncPromo]) {
153     correctHeight += NSHeight([controller frameOfSigninPromo]) +
154                      extension_installed_bubble::kInnerVerticalMargin;
155   }
156   EXPECT_EQ(height, correctHeight);
157   [controller setMessageFrames:height];
159   NSRect msg1Frame = [controller headingFrame];
160   NSRect msg2Frame = [controller frameOfHowToUse];
161   NSRect msg3Frame = [controller frameOfHowToManage];
162   NSRect msg4Frame = [controller frameOfSigninPromo];
164   int next_y = extension_installed_bubble::kOuterVerticalMargin;
165   if ([controller showSyncPromo]) {
166     // Bottom message should be kOuterVerticalMargin pixels above window edge.
167     EXPECT_EQ(next_y, NSMinY(msg4Frame));
168     next_y = NSMinY(msg4Frame) + NSHeight(msg4Frame) +
169             extension_installed_bubble::kInnerVerticalMargin;
170   }
172   // HowToManage frame should be kInnerVerticalMargin pixels above sync promo,
173   // unless sync promo is hidden, then kOuterVerticalMargin pixels above.
174   EXPECT_EQ(next_y, NSMinY(msg3Frame));
176   // Page action message should be kInnerVerticalMargin pixels above bottom msg.
177   EXPECT_EQ(NSMinY(msg3Frame) + NSHeight(msg3Frame) +
178                 extension_installed_bubble::kInnerVerticalMargin,
179             NSMinY(msg2Frame));
181   // Top message should be kInnerVerticalMargin pixels above Page action msg.
182   EXPECT_EQ(NSMinY(msg2Frame) + NSHeight(msg2Frame) +
183                 extension_installed_bubble::kInnerVerticalMargin,
184             NSMinY(msg1Frame));
186   [controller setPageActionPreviewShowing:NO];
187   [controller close];
190 TEST_F(ExtensionInstalledBubbleControllerTest, BrowserActionTest) {
191   extension_ = CreateExtension(extension_installed_bubble::kBrowserAction);
192   ExtensionInstalledBubbleControllerForTest* controller =
193       [[ExtensionInstalledBubbleControllerForTest alloc]
194           initWithParentWindow:window_
195                      extension:extension_.get()
196                         bundle:NULL
197                        browser:browser()
198                           icon:icon_];
199   EXPECT_TRUE(controller);
201   // Initialize window without having to calculate tabstrip locations.
202   [controller initializeWindow];
203   EXPECT_TRUE([controller window]);
205   int height = [controller calculateWindowHeight];
206   // Height should equal the vertical padding + height of all messages.
207   int correctHeight = 2 * extension_installed_bubble::kOuterVerticalMargin +
208       2 * extension_installed_bubble::kInnerVerticalMargin +
209       NSHeight([controller headingFrame]) +
210       NSHeight([controller frameOfHowToUse]) +
211       NSHeight([controller frameOfHowToManage]);
212   if ([controller showSyncPromo]) {
213     correctHeight += NSHeight([controller frameOfSigninPromo]) +
214                      extension_installed_bubble::kInnerVerticalMargin;
215   }
216   EXPECT_EQ(height, correctHeight);
217   [controller setMessageFrames:height];
219   NSRect msg1Frame = [controller headingFrame];
220   NSRect msg2Frame = [controller frameOfHowToUse];
221   NSRect msg3Frame = [controller frameOfHowToManage];
222   NSRect msg4Frame = [controller frameOfSigninPromo];
224   int next_y = extension_installed_bubble::kOuterVerticalMargin;
225   if ([controller showSyncPromo]) {
226     // Bottom message should be kOuterVerticalMargin pixels above window edge.
227     EXPECT_EQ(next_y, NSMinY(msg4Frame));
228     next_y = NSMinY(msg4Frame) + NSHeight(msg4Frame) +
229             extension_installed_bubble::kInnerVerticalMargin;
230   }
232   // HowToManage frame should be kInnerVerticalMargin pixels above sync promo,
233   // unless sync promo is hidden, then kOuterVerticalMargin pixels above.
234   EXPECT_EQ(next_y, NSMinY(msg3Frame));
236   // Browser action message should be kInnerVerticalMargin pixels above bottom
237   // msg.
238   EXPECT_EQ(NSMinY(msg3Frame) + NSHeight(msg3Frame) +
239                 extension_installed_bubble::kInnerVerticalMargin,
240             NSMinY(msg2Frame));
242   // Top message should be kInnerVerticalMargin pixels above Browser action msg.
243   EXPECT_EQ(NSMinY(msg2Frame) + NSHeight(msg2Frame) +
244                 extension_installed_bubble::kInnerVerticalMargin,
245             NSMinY(msg1Frame));
247   [controller close];
250 TEST_F(ExtensionInstalledBubbleControllerTest, ParentClose) {
251   extension_ = CreateExtension(extension_installed_bubble::kBrowserAction);
252   ExtensionInstalledBubbleControllerForTest* controller =
253       [[ExtensionInstalledBubbleControllerForTest alloc]
254           initWithParentWindow:window_
255                      extension:extension_.get()
256                         bundle:NULL
257                        browser:browser()
258                           icon:icon_];
259   EXPECT_TRUE(controller);
261   // Bring up the window and disable close animation.
262   [controller showWindow:nil];
263   NSWindow* bubbleWindow = [controller window];
264   ASSERT_TRUE([bubbleWindow isKindOfClass:[InfoBubbleWindow class]]);
265   [static_cast<InfoBubbleWindow*>(bubbleWindow)
266       setAllowedAnimations:info_bubble::kAnimateNone];
268   // Observe whether the bubble window closes.
269   NSString* notification = NSWindowWillCloseNotification;
270   id observer = [OCMockObject observerMock];
271   [[observer expect] notificationWithName:notification object:bubbleWindow];
272   [[NSNotificationCenter defaultCenter]
273     addMockObserver:observer name:notification object:bubbleWindow];
275   // The bubble window goes from visible to not-visible.
276   EXPECT_TRUE([bubbleWindow isVisible]);
277   [window_ close];
278   EXPECT_FALSE([bubbleWindow isVisible]);
280   [[NSNotificationCenter defaultCenter] removeObserver:observer];
282   // Check that the appropriate notification was received.
283   EXPECT_OCMOCK_VERIFY(observer);
286 TEST_F(ExtensionInstalledBubbleControllerTest, AppTest) {
287   extension_ = CreateExtension(extension_installed_bubble::kApp);
288   ExtensionInstalledBubbleControllerForTest* controller =
289       [[ExtensionInstalledBubbleControllerForTest alloc]
290           initWithParentWindow:window_
291                      extension:extension_.get()
292                         bundle:NULL
293                        browser:browser()
294                           icon:icon_];
295   EXPECT_TRUE(controller);
296   [controller initializeWindow];
297   EXPECT_TRUE([controller window]);
299   int height = [controller calculateWindowHeight];
301   // Make sure there is always enough room for the icon and margin.
302   int minHeight = extension_installed_bubble::kIconSize +
303     (2 * extension_installed_bubble::kOuterVerticalMargin);
304   EXPECT_GT(height, minHeight);
306   // Make sure the "show me" link is visible.
307   EXPECT_FALSE([[controller appInstalledShortcutLink] isHidden]);
309   [controller close];