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 #import "base/mac/scoped_nsobject.h"
8 #include "base/strings/sys_string_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #import "chrome/browser/extensions/extension_install_prompt.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
13 #import "chrome/browser/ui/cocoa/extensions/extension_install_prompt_test_utils.h"
14 #import "chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h"
15 #include "extensions/common/extension.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #import "testing/gtest_mac.h"
19 using extensions::Extension;
21 // Base class for our tests.
22 class ExtensionInstallViewControllerTest : public CocoaProfileTest {
24 ExtensionInstallViewControllerTest() {
25 extension_ = chrome::LoadInstallPromptExtension();
29 scoped_refptr<extensions::Extension> extension_;
32 // Test that we can load the two kinds of prompts correctly, that the outlets
33 // are hooked up, and that the dialog calls cancel when cancel is pressed.
34 TEST_F(ExtensionInstallViewControllerTest, BasicsNormalCancel) {
35 chrome::MockExtensionInstallPromptDelegate delegate;
37 scoped_refptr<ExtensionInstallPrompt::Prompt> prompt =
38 chrome::BuildExtensionInstallPrompt(extension_.get());
39 ExtensionInstallPrompt::PermissionsType type =
40 ExtensionInstallPrompt::PermissionsType::REGULAR_PERMISSIONS;
42 std::vector<base::string16> permissions;
43 permissions.push_back(base::UTF8ToUTF16("warning 1"));
44 prompt->SetPermissions(permissions, type);
45 // No details provided with this permission.
46 std::vector<base::string16> details;
47 details.push_back(base::string16());
48 prompt->SetPermissionsDetails(details, type);
50 base::scoped_nsobject<ExtensionInstallViewController> controller(
51 [[ExtensionInstallViewController alloc] initWithProfile:profile()
56 [controller view]; // Force nib load.
58 // Test the right nib loaded.
59 EXPECT_NSEQ(@"ExtensionInstallPrompt", [controller nibName]);
61 // Check all the controls.
62 // Make sure everything is non-nil, and that the fields that are
63 // auto-translated don't start with a caret (that would indicate that they
64 // were not translated).
65 EXPECT_TRUE([controller iconView]);
66 EXPECT_TRUE([[controller iconView] image]);
68 EXPECT_TRUE([controller titleField]);
69 EXPECT_NE(0u, [[[controller titleField] stringValue] length]);
71 NSOutlineView* outlineView = [controller outlineView];
72 EXPECT_TRUE(outlineView);
73 EXPECT_EQ(2, [outlineView numberOfRows]);
74 EXPECT_NSEQ(base::SysUTF16ToNSString(prompt->GetPermission(0, type)),
75 [[outlineView dataSource] outlineView:outlineView
76 objectValueForTableColumn:nil
77 byItem:[outlineView itemAtRow:1]]);
79 EXPECT_TRUE([controller cancelButton]);
80 EXPECT_NE(0u, [[[controller cancelButton] stringValue] length]);
81 EXPECT_NE('^', [[[controller cancelButton] stringValue] characterAtIndex:0]);
83 EXPECT_TRUE([controller okButton]);
84 EXPECT_NE(0u, [[[controller okButton] stringValue] length]);
85 EXPECT_NE('^', [[[controller okButton] stringValue] characterAtIndex:0]);
87 // Test that cancel calls our delegate.
88 [controller cancel:nil];
89 EXPECT_EQ(1, delegate.abort_count());
90 EXPECT_EQ(0, delegate.proceed_count());
93 TEST_F(ExtensionInstallViewControllerTest, BasicsNormalOK) {
94 chrome::MockExtensionInstallPromptDelegate delegate;
96 scoped_refptr<ExtensionInstallPrompt::Prompt> prompt =
97 chrome::BuildExtensionInstallPrompt(extension_.get());
98 ExtensionInstallPrompt::PermissionsType type =
99 ExtensionInstallPrompt::PermissionsType::REGULAR_PERMISSIONS;
101 std::vector<base::string16> permissions;
102 permissions.push_back(base::UTF8ToUTF16("warning 1"));
103 prompt->SetPermissions(permissions, type);
104 // No details provided with this permission.
105 std::vector<base::string16> details;
106 details.push_back(base::string16());
107 prompt->SetPermissionsDetails(details, type);
109 base::scoped_nsobject<ExtensionInstallViewController> controller(
110 [[ExtensionInstallViewController alloc] initWithProfile:profile()
115 [controller view]; // Force nib load.
118 EXPECT_EQ(0, delegate.abort_count());
119 EXPECT_EQ(1, delegate.proceed_count());
122 // Test that controls get repositioned when there are two warnings vs one
124 TEST_F(ExtensionInstallViewControllerTest, MultipleWarnings) {
125 chrome::MockExtensionInstallPromptDelegate delegate1;
126 chrome::MockExtensionInstallPromptDelegate delegate2;
128 scoped_refptr<ExtensionInstallPrompt::Prompt> one_warning_prompt =
129 chrome::BuildExtensionInstallPrompt(extension_.get());
130 ExtensionInstallPrompt::PermissionsType type =
131 ExtensionInstallPrompt::PermissionsType::REGULAR_PERMISSIONS;
133 std::vector<base::string16> permissions;
134 permissions.push_back(base::UTF8ToUTF16("warning 1"));
135 one_warning_prompt->SetPermissions(permissions, type);
136 // No details provided with this permission.
137 std::vector<base::string16> details;
138 details.push_back(base::string16());
139 one_warning_prompt->SetPermissionsDetails(details, type);
141 scoped_refptr<ExtensionInstallPrompt::Prompt> two_warnings_prompt =
142 chrome::BuildExtensionInstallPrompt(extension_.get());
143 permissions.push_back(base::UTF8ToUTF16("warning 2"));
144 two_warnings_prompt->SetPermissions(permissions, type);
145 // No details provided with this permission.
146 details.push_back(base::string16());
147 two_warnings_prompt->SetPermissionsDetails(details, type);
149 base::scoped_nsobject<ExtensionInstallViewController> controller1(
150 [[ExtensionInstallViewController alloc]
151 initWithProfile:profile()
154 prompt:one_warning_prompt]);
156 [controller1 view]; // Force nib load.
158 base::scoped_nsobject<ExtensionInstallViewController> controller2(
159 [[ExtensionInstallViewController alloc]
160 initWithProfile:profile()
163 prompt:two_warnings_prompt]);
165 [controller2 view]; // Force nib load.
167 // Test control positioning. We don't test exact positioning because we don't
168 // want this to depend on string details and localization. But we do know the
169 // relative effect that adding a second warning should have on the layout.
170 ASSERT_LT([[controller1 view] frame].size.height,
171 [[controller2 view] frame].size.height);
173 ASSERT_LT([[controller1 view] frame].size.height,
174 [[controller2 view] frame].size.height);
177 // Test that we can load the skinny prompt correctly, and that the outlets are
179 TEST_F(ExtensionInstallViewControllerTest, BasicsSkinny) {
180 chrome::MockExtensionInstallPromptDelegate delegate;
182 // No warnings should trigger skinny prompt.
183 scoped_refptr<ExtensionInstallPrompt::Prompt> no_warnings_prompt =
184 chrome::BuildExtensionInstallPrompt(extension_.get());
186 base::scoped_nsobject<ExtensionInstallViewController> controller(
187 [[ExtensionInstallViewController alloc]
188 initWithProfile:profile()
191 prompt:no_warnings_prompt]);
193 [controller view]; // Force nib load.
195 // Test the right nib loaded.
196 EXPECT_NSEQ(@"ExtensionInstallPromptNoWarnings", [controller nibName]);
198 // Check all the controls.
199 // In the skinny prompt, only the icon, title and buttons are non-nill.
200 // Everything else is nil.
201 EXPECT_TRUE([controller iconView]);
202 EXPECT_TRUE([[controller iconView] image]);
204 EXPECT_TRUE([controller titleField]);
205 EXPECT_NE(0u, [[[controller titleField] stringValue] length]);
207 EXPECT_TRUE([controller cancelButton]);
208 EXPECT_NE(0u, [[[controller cancelButton] stringValue] length]);
209 EXPECT_NE('^', [[[controller cancelButton] stringValue] characterAtIndex:0]);
211 EXPECT_TRUE([controller okButton]);
212 EXPECT_NE(0u, [[[controller okButton] stringValue] length]);
213 EXPECT_NE('^', [[[controller okButton] stringValue] characterAtIndex:0]);
215 EXPECT_FALSE([controller outlineView]);
219 // Test that we can load the inline prompt correctly, and that the outlets are
221 TEST_F(ExtensionInstallViewControllerTest, BasicsInline) {
222 chrome::MockExtensionInstallPromptDelegate delegate;
224 // No warnings should trigger skinny prompt.
225 scoped_refptr<ExtensionInstallPrompt::Prompt> inline_prompt =
226 new ExtensionInstallPrompt::Prompt(
227 ExtensionInstallPrompt::INLINE_INSTALL_PROMPT);
228 inline_prompt->SetWebstoreData("1,000", true, 3.5, 200);
229 inline_prompt->set_extension(extension_.get());
230 inline_prompt->set_icon(chrome::LoadInstallPromptIcon());
232 base::scoped_nsobject<ExtensionInstallViewController> controller(
233 [[ExtensionInstallViewController alloc] initWithProfile:profile()
236 prompt:inline_prompt]);
238 [controller view]; // Force nib load.
240 // Test the right nib loaded.
241 EXPECT_NSEQ(@"ExtensionInstallPromptWebstoreData", [controller nibName]);
243 // Check all the controls.
244 EXPECT_TRUE([controller iconView]);
245 EXPECT_TRUE([[controller iconView] image]);
247 EXPECT_TRUE([controller titleField]);
248 EXPECT_NE(0u, [[[controller titleField] stringValue] length]);
250 EXPECT_TRUE([controller cancelButton]);
251 EXPECT_NE(0u, [[[controller cancelButton] stringValue] length]);
252 EXPECT_NE('^', [[[controller cancelButton] stringValue] characterAtIndex:0]);
254 EXPECT_TRUE([controller okButton]);
255 EXPECT_NE(0u, [[[controller okButton] stringValue] length]);
256 EXPECT_NE('^', [[[controller okButton] stringValue] characterAtIndex:0]);
258 EXPECT_TRUE([controller ratingStars]);
259 EXPECT_EQ(5u, [[[controller ratingStars] subviews] count]);
261 EXPECT_TRUE([controller ratingCountField]);
262 EXPECT_NE(0u, [[[controller ratingCountField] stringValue] length]);
264 EXPECT_TRUE([controller userCountField]);
265 EXPECT_NE(0u, [[[controller userCountField] stringValue] length]);
267 EXPECT_TRUE([controller storeLinkButton]);
268 EXPECT_NE(0u, [[[controller storeLinkButton] stringValue] length]);
270 [[[controller storeLinkButton] stringValue] characterAtIndex:0]);
272 // Though we have no permissions warnings, these should still be hooked up,
274 EXPECT_TRUE([controller outlineView]);
275 EXPECT_TRUE([[[controller outlineView] enclosingScrollView] isHidden]);
276 EXPECT_TRUE([controller warningsSeparator]);
277 EXPECT_TRUE([[controller warningsSeparator] isHidden]);
280 TEST_F(ExtensionInstallViewControllerTest, PostInstallPermissionsPrompt) {
281 chrome::MockExtensionInstallPromptDelegate delegate;
283 scoped_refptr<ExtensionInstallPrompt::Prompt> prompt =
284 chrome::BuildExtensionPostInstallPermissionsPrompt(extension_.get());
285 ExtensionInstallPrompt::PermissionsType type =
286 ExtensionInstallPrompt::PermissionsType::REGULAR_PERMISSIONS;
288 std::vector<base::string16> permissions;
289 permissions.push_back(base::UTF8ToUTF16("warning 1"));
290 prompt->SetPermissions(permissions, type);
291 // No details provided with this permission.
292 std::vector<base::string16> details;
293 details.push_back(base::string16());
294 prompt->SetPermissionsDetails(details, type);
296 base::scoped_nsobject<ExtensionInstallViewController> controller(
297 [[ExtensionInstallViewController alloc] initWithProfile:profile()
302 [controller view]; // Force nib load.
304 EXPECT_TRUE([controller cancelButton]);
305 EXPECT_FALSE([controller okButton]);
307 [controller cancel:nil];
308 EXPECT_EQ(1, delegate.abort_count());
311 // Test that permission details show up.
312 TEST_F(ExtensionInstallViewControllerTest, PermissionsDetails) {
313 chrome::MockExtensionInstallPromptDelegate delegate;
315 scoped_refptr<ExtensionInstallPrompt::Prompt> prompt =
316 chrome::BuildExtensionInstallPrompt(extension_.get());
317 ExtensionInstallPrompt::PermissionsType type =
318 ExtensionInstallPrompt::PermissionsType::REGULAR_PERMISSIONS;
320 std::vector<base::string16> permissions;
321 permissions.push_back(base::UTF8ToUTF16("warning 1"));
322 std::vector<base::string16> permissions_details;
323 permissions_details.push_back(base::UTF8ToUTF16("Detail 1"));
324 prompt->SetPermissions(permissions, type);
325 prompt->SetPermissionsDetails(permissions_details, type);
326 prompt->SetIsShowingDetails(
327 ExtensionInstallPrompt::PERMISSIONS_DETAILS, 0, true);
329 base::scoped_nsobject<ExtensionInstallViewController> controller(
330 [[ExtensionInstallViewController alloc] initWithProfile:profile()
335 [controller view]; // Force nib load.
337 NSOutlineView* outlineView = [controller outlineView];
338 EXPECT_TRUE(outlineView);
339 EXPECT_EQ(4, [outlineView numberOfRows]);
340 EXPECT_NSEQ(base::SysUTF16ToNSString(prompt->GetPermissionsDetails(0, type)),
341 [[outlineView dataSource] outlineView:outlineView
342 objectValueForTableColumn:nil
343 byItem:[outlineView itemAtRow:2]]);