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 ExtensionInstallPrompt::Prompt prompt =
38 chrome::BuildExtensionInstallPrompt(extension_.get());
40 std::vector<base::string16> permissions;
41 permissions.push_back(base::UTF8ToUTF16("warning 1"));
42 prompt.SetPermissions(permissions);
43 // No details provided with this permission.
44 std::vector<base::string16> details;
45 details.push_back(base::string16());
46 prompt.SetPermissionsDetails(details);
48 base::scoped_nsobject<ExtensionInstallViewController> controller(
49 [[ExtensionInstallViewController alloc] initWithNavigator:browser()
53 [controller view]; // Force nib load.
55 // Test the right nib loaded.
56 EXPECT_NSEQ(@"ExtensionInstallPrompt", [controller nibName]);
58 // Check all the controls.
59 // Make sure everything is non-nil, and that the fields that are
60 // auto-translated don't start with a caret (that would indicate that they
61 // were not translated).
62 EXPECT_TRUE([controller iconView]);
63 EXPECT_TRUE([[controller iconView] image]);
65 EXPECT_TRUE([controller titleField]);
66 EXPECT_NE(0u, [[[controller titleField] stringValue] length]);
68 NSOutlineView* outlineView = [controller outlineView];
69 EXPECT_TRUE(outlineView);
70 EXPECT_EQ(2, [outlineView numberOfRows]);
71 EXPECT_NSEQ(base::SysUTF16ToNSString(prompt.GetPermission(0)),
72 [[outlineView dataSource] outlineView:outlineView
73 objectValueForTableColumn:nil
74 byItem:[outlineView itemAtRow:1]]);
76 EXPECT_TRUE([controller cancelButton]);
77 EXPECT_NE(0u, [[[controller cancelButton] stringValue] length]);
78 EXPECT_NE('^', [[[controller cancelButton] stringValue] characterAtIndex:0]);
80 EXPECT_TRUE([controller okButton]);
81 EXPECT_NE(0u, [[[controller okButton] stringValue] length]);
82 EXPECT_NE('^', [[[controller okButton] stringValue] characterAtIndex:0]);
84 // Test that cancel calls our delegate.
85 [controller cancel:nil];
86 EXPECT_EQ(1, delegate.abort_count());
87 EXPECT_EQ(0, delegate.proceed_count());
90 TEST_F(ExtensionInstallViewControllerTest, BasicsNormalOK) {
91 chrome::MockExtensionInstallPromptDelegate delegate;
93 ExtensionInstallPrompt::Prompt prompt =
94 chrome::BuildExtensionInstallPrompt(extension_.get());
95 std::vector<base::string16> permissions;
96 permissions.push_back(base::UTF8ToUTF16("warning 1"));
97 prompt.SetPermissions(permissions);
98 // No details provided with this permission.
99 std::vector<base::string16> details;
100 details.push_back(base::string16());
101 prompt.SetPermissionsDetails(details);
103 base::scoped_nsobject<ExtensionInstallViewController> controller(
104 [[ExtensionInstallViewController alloc] initWithNavigator:browser()
108 [controller view]; // Force nib load.
111 EXPECT_EQ(0, delegate.abort_count());
112 EXPECT_EQ(1, delegate.proceed_count());
115 // Test that controls get repositioned when there are two warnings vs one
117 TEST_F(ExtensionInstallViewControllerTest, MultipleWarnings) {
118 chrome::MockExtensionInstallPromptDelegate delegate1;
119 chrome::MockExtensionInstallPromptDelegate delegate2;
121 ExtensionInstallPrompt::Prompt one_warning_prompt =
122 chrome::BuildExtensionInstallPrompt(extension_.get());
123 std::vector<base::string16> permissions;
124 permissions.push_back(base::UTF8ToUTF16("warning 1"));
125 one_warning_prompt.SetPermissions(permissions);
126 // No details provided with this permission.
127 std::vector<base::string16> details;
128 details.push_back(base::string16());
129 one_warning_prompt.SetPermissionsDetails(details);
131 ExtensionInstallPrompt::Prompt two_warnings_prompt =
132 chrome::BuildExtensionInstallPrompt(extension_.get());
133 permissions.push_back(base::UTF8ToUTF16("warning 2"));
134 two_warnings_prompt.SetPermissions(permissions);
135 // No details provided with this permission.
136 details.push_back(base::string16());
137 two_warnings_prompt.SetPermissionsDetails(details);
139 base::scoped_nsobject<ExtensionInstallViewController> controller1(
140 [[ExtensionInstallViewController alloc]
141 initWithNavigator:browser()
143 prompt:one_warning_prompt]);
145 [controller1 view]; // Force nib load.
147 base::scoped_nsobject<ExtensionInstallViewController> controller2(
148 [[ExtensionInstallViewController alloc]
149 initWithNavigator:browser()
151 prompt:two_warnings_prompt]);
153 [controller2 view]; // Force nib load.
155 // Test control positioning. We don't test exact positioning because we don't
156 // want this to depend on string details and localization. But we do know the
157 // relative effect that adding a second warning should have on the layout.
158 ASSERT_LT([[controller1 view] frame].size.height,
159 [[controller2 view] frame].size.height);
161 ASSERT_LT([[controller1 view] frame].size.height,
162 [[controller2 view] frame].size.height);
165 // Test that we can load the skinny prompt correctly, and that the outlets are
167 TEST_F(ExtensionInstallViewControllerTest, BasicsSkinny) {
168 chrome::MockExtensionInstallPromptDelegate delegate;
170 // No warnings should trigger skinny prompt.
171 ExtensionInstallPrompt::Prompt no_warnings_prompt =
172 chrome::BuildExtensionInstallPrompt(extension_.get());
174 base::scoped_nsobject<ExtensionInstallViewController> controller(
175 [[ExtensionInstallViewController alloc]
176 initWithNavigator:browser()
178 prompt:no_warnings_prompt]);
180 [controller view]; // Force nib load.
182 // Test the right nib loaded.
183 EXPECT_NSEQ(@"ExtensionInstallPromptNoWarnings", [controller nibName]);
185 // Check all the controls.
186 // In the skinny prompt, only the icon, title and buttons are non-nill.
187 // Everything else is nil.
188 EXPECT_TRUE([controller iconView]);
189 EXPECT_TRUE([[controller iconView] image]);
191 EXPECT_TRUE([controller titleField]);
192 EXPECT_NE(0u, [[[controller titleField] stringValue] length]);
194 EXPECT_TRUE([controller cancelButton]);
195 EXPECT_NE(0u, [[[controller cancelButton] stringValue] length]);
196 EXPECT_NE('^', [[[controller cancelButton] stringValue] characterAtIndex:0]);
198 EXPECT_TRUE([controller okButton]);
199 EXPECT_NE(0u, [[[controller okButton] stringValue] length]);
200 EXPECT_NE('^', [[[controller okButton] stringValue] characterAtIndex:0]);
202 EXPECT_FALSE([controller outlineView]);
206 // Test that we can load the inline prompt correctly, and that the outlets are
208 TEST_F(ExtensionInstallViewControllerTest, BasicsInline) {
209 chrome::MockExtensionInstallPromptDelegate delegate;
211 // No warnings should trigger skinny prompt.
212 ExtensionInstallPrompt::Prompt inline_prompt(
213 ExtensionInstallPrompt::INLINE_INSTALL_PROMPT);
214 inline_prompt.SetInlineInstallWebstoreData("1,000", true, 3.5, 200);
215 inline_prompt.set_extension(extension_.get());
216 inline_prompt.set_icon(chrome::LoadInstallPromptIcon());
218 base::scoped_nsobject<ExtensionInstallViewController> controller(
219 [[ExtensionInstallViewController alloc] initWithNavigator:browser()
221 prompt:inline_prompt]);
223 [controller view]; // Force nib load.
225 // Test the right nib loaded.
226 EXPECT_NSEQ(@"ExtensionInstallPromptInline", [controller nibName]);
228 // Check all the controls.
229 EXPECT_TRUE([controller iconView]);
230 EXPECT_TRUE([[controller iconView] image]);
232 EXPECT_TRUE([controller titleField]);
233 EXPECT_NE(0u, [[[controller titleField] stringValue] length]);
235 EXPECT_TRUE([controller cancelButton]);
236 EXPECT_NE(0u, [[[controller cancelButton] stringValue] length]);
237 EXPECT_NE('^', [[[controller cancelButton] stringValue] characterAtIndex:0]);
239 EXPECT_TRUE([controller okButton]);
240 EXPECT_NE(0u, [[[controller okButton] stringValue] length]);
241 EXPECT_NE('^', [[[controller okButton] stringValue] characterAtIndex:0]);
243 EXPECT_TRUE([controller ratingStars]);
244 EXPECT_EQ(5u, [[[controller ratingStars] subviews] count]);
246 EXPECT_TRUE([controller ratingCountField]);
247 EXPECT_NE(0u, [[[controller ratingCountField] stringValue] length]);
249 EXPECT_TRUE([controller userCountField]);
250 EXPECT_NE(0u, [[[controller userCountField] stringValue] length]);
252 EXPECT_TRUE([controller storeLinkButton]);
253 EXPECT_NE(0u, [[[controller storeLinkButton] stringValue] length]);
255 [[[controller storeLinkButton] stringValue] characterAtIndex:0]);
257 // Though we have no permissions warnings, these should still be hooked up,
259 EXPECT_TRUE([controller outlineView]);
260 EXPECT_TRUE([[[controller outlineView] enclosingScrollView] isHidden]);
261 EXPECT_TRUE([controller warningsSeparator]);
262 EXPECT_TRUE([[controller warningsSeparator] isHidden]);
265 TEST_F(ExtensionInstallViewControllerTest, OAuthIssues) {
266 chrome::MockExtensionInstallPromptDelegate delegate;
268 ExtensionInstallPrompt::Prompt prompt =
269 chrome::BuildExtensionInstallPrompt(extension_.get());
270 std::vector<base::string16> permissions;
271 permissions.push_back(base::UTF8ToUTF16("warning 1"));
272 prompt.SetPermissions(permissions);
273 // No details provided with this permission.
274 std::vector<base::string16> details;
275 details.push_back(base::string16());
276 prompt.SetPermissionsDetails(details);
278 IssueAdviceInfoEntry issue;
279 issue.description = base::UTF8ToUTF16("issue description 1");
280 issue.details.push_back(base::UTF8ToUTF16("issue detail 1"));
281 IssueAdviceInfo issues;
282 issues.push_back(issue);
283 prompt.SetOAuthIssueAdvice(issues);
284 prompt.SetIsShowingDetails(
285 ExtensionInstallPrompt::OAUTH_DETAILS, 0, true);
287 base::scoped_nsobject<ExtensionInstallViewController> controller(
288 [[ExtensionInstallViewController alloc] initWithNavigator:browser()
292 [controller view]; // Force nib load.
293 NSOutlineView* outlineView = [controller outlineView];
294 EXPECT_TRUE(outlineView);
295 EXPECT_EQ(6, [outlineView numberOfRows]);
296 EXPECT_NSEQ(base::SysUTF16ToNSString(prompt.GetOAuthIssue(0).description),
297 [[outlineView dataSource] outlineView:outlineView
298 objectValueForTableColumn:nil
299 byItem:[outlineView itemAtRow:3]]);
301 EXPECT_NSEQ(base::SysUTF16ToNSString(prompt.GetOAuthIssue(0).details[0]),
302 [[outlineView dataSource] outlineView:outlineView
303 objectValueForTableColumn:nil
304 byItem:[outlineView itemAtRow:4]]);
307 TEST_F(ExtensionInstallViewControllerTest, PostInstallPermissionsPrompt) {
308 chrome::MockExtensionInstallPromptDelegate delegate;
310 ExtensionInstallPrompt::Prompt prompt =
311 chrome::BuildExtensionPostInstallPermissionsPrompt(extension_.get());
312 std::vector<base::string16> permissions;
313 permissions.push_back(base::UTF8ToUTF16("warning 1"));
314 prompt.SetPermissions(permissions);
315 // No details provided with this permission.
316 std::vector<base::string16> details;
317 details.push_back(base::string16());
318 prompt.SetPermissionsDetails(details);
320 base::scoped_nsobject<ExtensionInstallViewController> controller(
321 [[ExtensionInstallViewController alloc] initWithNavigator:browser()
325 [controller view]; // Force nib load.
327 EXPECT_TRUE([controller cancelButton]);
328 EXPECT_FALSE([controller okButton]);
330 [controller cancel:nil];
331 EXPECT_EQ(1, delegate.abort_count());
334 // Test that permission details show up.
335 TEST_F(ExtensionInstallViewControllerTest, PermissionsDetails) {
336 chrome::MockExtensionInstallPromptDelegate delegate;
338 ExtensionInstallPrompt::Prompt prompt =
339 chrome::BuildExtensionInstallPrompt(extension_.get());
341 std::vector<base::string16> permissions;
342 permissions.push_back(base::UTF8ToUTF16("warning 1"));
343 std::vector<base::string16> permissions_details;
344 permissions_details.push_back(base::UTF8ToUTF16("Detail 1"));
345 prompt.SetPermissions(permissions);
346 prompt.SetPermissionsDetails(permissions_details);
347 prompt.SetIsShowingDetails(
348 ExtensionInstallPrompt::PERMISSIONS_DETAILS, 0, true);
350 base::scoped_nsobject<ExtensionInstallViewController> controller(
351 [[ExtensionInstallViewController alloc] initWithNavigator:browser()
355 [controller view]; // Force nib load.
357 NSOutlineView* outlineView = [controller outlineView];
358 EXPECT_TRUE(outlineView);
359 EXPECT_EQ(4, [outlineView numberOfRows]);
360 EXPECT_NSEQ(base::SysUTF16ToNSString(prompt.GetPermissionsDetails(0)),
361 [[outlineView dataSource] outlineView:outlineView
362 objectValueForTableColumn:nil
363 byItem:[outlineView itemAtRow:2]]);