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 // TODO(dbeam): test for loading upacked extensions?
7 GEN('#include "chrome/browser/ui/webui/extensions/' +
8 'extension_settings_browsertest.h"');
10 // The id of the extension from |InstallGoodExtension|.
11 var GOOD_EXTENSION_ID
= 'ldnnhddmnhbkjipkidpdiheffobcpfmf';
13 // The id of the extension from |InstallErrorsExtension|.
14 var ERROR_EXTENSION_ID
= 'pdlpifnclfacjobnmbpngemkalkjamnf';
17 * Test C++ fixture for settings WebUI testing.
19 * @extends {testing.Test}
21 function ExtensionSettingsUIBrowserTest() {}
24 * TestFixture for extension settings WebUI testing.
25 * @extends {testing.Test}
28 function ExtensionSettingsWebUITest() {}
30 ExtensionSettingsWebUITest
.prototype = {
31 __proto__
: testing
.Test
.prototype,
37 runAccessibilityChecks
: true,
40 accessibilityIssuesAreErrors
: true,
43 * A URL to load before starting each test.
47 browsePreload
: 'chrome://extensions-frame/',
50 typedefCppFixture
: 'ExtensionSettingsUIBrowserTest',
54 testing
.Test
.disableAnimationsAndTransitions();
58 * Holds an array of steps that should happen in order during a test.
59 * The last step should be |testDone|.
60 * @protected {Array<!Function>}
65 * Advances to the next step in the test. Every step should call this.
68 nextStep: function() {
69 assertTrue(this.steps
.length
> 0);
70 this.steps
.shift().call(this);
74 * Will wait for the page to load before calling the next step. This should be
75 * the first step in every test.
78 waitForPageLoad: function() {
79 assertEquals(this.browsePreload
, document
.location
.href
);
80 var extensionList
= getRequiredElement('extension-settings-list');
81 extensionList
.loadFinished
.then(this.nextStep
.bind(this));
85 enableDeveloperMode: function() {
86 // Toggling developer mode triggers a page update, so we need to be able to
87 // wait for the update to finish.
88 $('extension-settings-list').resetLoadFinished();
89 var waitForPage
= this.waitForPageLoad
.bind(this);
90 document
.addEventListener('devControlsVisibilityUpdated',
91 function devCallback() {
92 // Callback should only be handled once.
93 document
.removeEventListener('devControlsVisibilityUpdated', devCallback
);
95 chrome
.developerPrivate
.getProfileConfiguration(function(profileInfo
) {
96 assertTrue(extensionSettings
.classList
.contains('dev-mode'));
97 assertTrue(profileInfo
.inDeveloperMode
);
99 // This event isn't thrown because transitions are disabled.
100 // Ensure transition here so that any dependent code does not break.
101 ensureTransitionEndEvent($('dev-controls'), 0);
107 var extensionSettings
= getRequiredElement('extension-settings');
108 assertFalse(extensionSettings
.classList
.contains('dev-mode'));
109 $('toggle-dev-on').click();
113 testDeveloperMode: function() {
114 var next
= this.nextStep
.bind(this);
115 var checkDevModeIsOff = function() {
116 chrome
.developerPrivate
.getProfileConfiguration(function(profileInfo
) {
117 assertFalse(profileInfo
.inDeveloperMode
);
121 this.steps
= [this.waitForPageLoad
,
123 this.enableDeveloperMode
,
129 // Flaky: http://crbug.com/505506.
130 // Verify that developer mode doesn't change behavior when the number of
131 // extensions changes.
132 TEST_F('ExtensionSettingsWebUITest', 'DISABLED_testDeveloperModeNoExtensions',
134 this.testDeveloperMode();
137 TEST_F('ExtensionSettingsWebUITest', 'testEmptyExtensionList', function() {
138 var verifyListIsHiddenAndEmpty = function() {
139 assertTrue($('extension-list-wrapper').hidden
);
140 assertFalse($('no-extensions').hidden
);
141 assertEquals(0, $('extension-settings-list').childNodes
.length
);
145 this.steps
= [this.waitForPageLoad
, verifyListIsHiddenAndEmpty
, testDone
];
149 TEST_F('ExtensionSettingsWebUITest', 'testChromeSendHandled', function() {
150 var testPackExtenion = function() {
151 // This dialog should be hidden at first.
152 assertFalse($('pack-extension-overlay').classList
.contains('showing'));
154 // Show the dialog, which triggers a chrome.send() for metrics purposes.
155 cr
.dispatchSimpleEvent($('pack-extension'), 'click');
156 assertTrue($('pack-extension-overlay').classList
.contains('showing'));
160 this.steps
= [this.waitForPageLoad
, testPackExtenion
, testDone
];
165 * @param {chrome.developerPrivate.EventType} eventType
166 * @param {function():void} callback
169 function UpdateListener(eventType
, callback
) {
170 this.callback_
= callback
;
171 this.eventType_
= eventType
;
172 this.onItemStateChangedListener_
= this.onItemStateChanged_
.bind(this);
173 chrome
.developerPrivate
.onItemStateChanged
.addListener(
174 this.onItemStateChangedListener_
);
177 UpdateListener
.prototype = {
179 onItemStateChanged_: function(data
) {
180 if (this.eventType_
== data
.event_type
) {
181 window
.setTimeout(function() {
182 chrome
.developerPrivate
.onItemStateChanged
.removeListener(
183 this.onItemStateChangedListener_
);
190 function BasicExtensionSettingsWebUITest() {}
192 BasicExtensionSettingsWebUITest
.prototype = {
193 __proto__
: ExtensionSettingsWebUITest
.prototype,
196 testGenPreamble: function() {
197 // Install multiple types of extensions to ensure we handle each type.
198 // TODO(devlin): There are more types to add here.
199 GEN(' InstallGoodExtension();');
200 GEN(' InstallErrorsExtension();');
201 GEN(' InstallSharedModule();');
202 GEN(' InstallPackagedApp();');
204 GEN(' SetAutoConfirmUninstall();');
208 verifyDisabledWorks: function() {
209 var listener
= new UpdateListener(
210 chrome
.developerPrivate
.EventType
.UNLOADED
,
212 var node
= getRequiredElement(GOOD_EXTENSION_ID
);
213 assertTrue(node
.classList
.contains('inactive-extension'));
216 chrome
.management
.setEnabled(GOOD_EXTENSION_ID
, false);
220 verifyEnabledWorks: function() {
221 var listener
= new UpdateListener(
222 chrome
.developerPrivate
.EventType
.LOADED
,
224 var node
= getRequiredElement(GOOD_EXTENSION_ID
);
225 assertFalse(node
.classList
.contains('inactive-extension'));
228 chrome
.management
.setEnabled(GOOD_EXTENSION_ID
, true);
232 verifyUninstallWorks: function() {
233 var listener
= new UpdateListener(
234 chrome
.developerPrivate
.EventType
.UNINSTALLED
,
236 assertEquals(null, $(GOOD_EXTENSION_ID
));
239 chrome
.test
.runWithUserGesture(function() {
240 chrome
.management
.uninstall(GOOD_EXTENSION_ID
);
245 // Verify that developer mode doesn't change behavior when the number of
246 // extensions changes.
247 TEST_F('BasicExtensionSettingsWebUITest', 'testDeveloperModeManyExtensions',
249 this.testDeveloperMode();
252 TEST_F('BasicExtensionSettingsWebUITest', 'testDisable', function() {
253 this.steps
= [this.waitForPageLoad
, this.verifyDisabledWorks
, testDone
];
257 TEST_F('BasicExtensionSettingsWebUITest', 'testEnable', function() {
258 this.steps
= [this.waitForPageLoad
,
259 this.verifyDisabledWorks
,
260 this.verifyEnabledWorks
,
265 TEST_F('BasicExtensionSettingsWebUITest', 'testUninstall', function() {
266 this.steps
= [this.waitForPageLoad
, this.verifyUninstallWorks
, testDone
];
270 TEST_F('BasicExtensionSettingsWebUITest', 'testNonEmptyExtensionList',
272 var verifyListIsNotHiddenAndEmpty = function() {
273 assertFalse($('extension-list-wrapper').hidden
);
274 assertTrue($('no-extensions').hidden
);
275 assertGT($('extension-settings-list').childNodes
.length
, 0);
279 this.steps
= [this.waitForPageLoad
, verifyListIsNotHiddenAndEmpty
, testDone
];
283 function AutoScrollExtensionSettingsWebUITest() {}
286 * A variation for testing auto-scroll when an id query param is passed in the
289 * @extends {BasicExtensionSettingsWebUITest}
291 AutoScrollExtensionSettingsWebUITest
.prototype = {
292 __proto__
: BasicExtensionSettingsWebUITest
.prototype,
295 browsePreload
: 'chrome://extensions-frame/?id=' + GOOD_EXTENSION_ID
,
298 testGenPreamble: function() {
299 BasicExtensionSettingsWebUITest
.prototype.testGenPreamble
.call(this);
300 // The window needs to be sufficiently small in order to ensure a scroll bar
302 GEN(' ShrinkWebContentsView();');
306 TEST_F('AutoScrollExtensionSettingsWebUITest', 'testAutoScroll', function() {
307 var checkHasScrollbar = function() {
308 assertGT(document
.body
.scrollHeight
, document
.body
.clientHeight
);
311 var checkIsScrolled = function() {
312 assertGT(document
.body
.scrollTop
, 0);
315 var checkScrolledToTop = function() {
316 assertEquals(0, document
.body
.scrollTop
);
319 var scrollToTop = function() {
320 document
.body
.scrollTop
= 0;
323 // Test that a) autoscroll works on first page load and b) updating the
324 // page doesn't result in autoscroll triggering again.
325 this.steps
= [this.waitForPageLoad
,
329 this.enableDeveloperMode
,
335 function ErrorConsoleExtensionSettingsWebUITest() {}
337 ErrorConsoleExtensionSettingsWebUITest
.prototype = {
338 __proto__
: ExtensionSettingsWebUITest
.prototype,
341 testGenPreamble: function() {
342 GEN(' EnableErrorConsole();');
343 GEN(' InstallGoodExtension();');
344 GEN(' InstallErrorsExtension();');
348 // Flaky on all platforms: http://crbug.com/499884, http://crbug.com/463245.
349 TEST_F('ErrorConsoleExtensionSettingsWebUITest',
350 'DISABLED_testErrorListButtonVisibility', function() {
351 var testButtonVisibility = function() {
352 var extensionList
= $('extension-list-wrapper');
354 var visibleButtons
= extensionList
.querySelectorAll(
355 '.errors-link:not([hidden])');
356 expectEquals(1, visibleButtons
.length
);
358 if (visibleButtons
.length
> 0) {
359 var errorLink
= $(ERROR_EXTENSION_ID
).querySelector('.errors-link');
360 expectEquals(visibleButtons
[0], errorLink
);
362 var errorIcon
= errorLink
.querySelector('img');
363 expectTrue(errorIcon
.classList
.contains('extension-error-warning-icon'));
366 var hiddenButtons
= extensionList
.querySelectorAll('.errors-link[hidden]');
367 expectEquals(1, hiddenButtons
.length
);
372 this.steps
= [this.waitForPageLoad
,
373 this.enableDeveloperMode
,
374 testButtonVisibility
,
380 * TestFixture for extension settings WebUI testing (commands config edition).
381 * @extends {testing.Test}
384 function SettingsCommandsExtensionSettingsWebUITest() {}
386 SettingsCommandsExtensionSettingsWebUITest
.prototype = {
387 __proto__
: ExtensionSettingsWebUITest
.prototype,
390 * A URL to load before starting each test.
394 browsePreload
: 'chrome://extensions-frame/configureCommands',
397 TEST_F('SettingsCommandsExtensionSettingsWebUITest', 'testChromeSendHandler',
399 // Just navigating to the page should trigger the chrome.send().
400 var assertOverlayVisible = function() {
401 assertTrue($('extension-commands-overlay').classList
.contains('showing'));
405 this.steps
= [this.waitForPageLoad
, assertOverlayVisible
, testDone
];
409 TEST_F('SettingsCommandsExtensionSettingsWebUITest', 'extensionSettingsUri',
411 var closeCommandOverlay = function() {
412 assertTrue($('extension-commands-overlay').classList
.contains('showing'));
413 assertEquals(window
.location
.href
,
414 'chrome://extensions-frame/configureCommands');
416 // Close command overlay.
417 $('extension-commands-dismiss').click();
419 assertFalse($('extension-commands-overlay').classList
.contains('showing'));
423 var checkExtensionsUrl = function() {
424 // After closing the overlay, the URL shouldn't include commands overlay
426 assertEquals(window
.location
.href
, 'chrome://extensions-frame/');
430 this.steps
= [this.waitForPageLoad
,
439 * @extends {ExtensionSettingsWebUITest}
441 function InstallGoodExtensionSettingsWebUITest() {}
443 InstallGoodExtensionSettingsWebUITest
.prototype = {
444 __proto__
: ExtensionSettingsWebUITest
.prototype,
447 testGenPreamble: function() {
448 GEN(' InstallGoodExtension();');
451 emptyTestForAccessibility() {
452 this.steps
= [this.waitForPageLoad
, testDone
];
457 TEST_F('InstallGoodExtensionSettingsWebUITest', 'testAccessibility',
459 this.emptyTestForAccessibility();
462 TEST_F('InstallGoodExtensionSettingsWebUITest', 'showOptions', function() {
463 var showExtensionOptions = function() {
464 var optionsOverlay
= extensions
.ExtensionOptionsOverlay
.getInstance();
465 optionsOverlay
.setExtensionAndShow(GOOD_EXTENSION_ID
, 'GOOD!', '',
466 this.nextStep
.bind(this));
468 // Preferred size changes don't happen in browser tests. Just fake it.
469 document
.querySelector('extensionoptions').onpreferredsizechanged(
470 {width
: 500, height
: 500});
473 this.steps
= [this.waitForPageLoad
, showExtensionOptions
, testDone
];
479 * @extends {InstallGoodExtensionSettingsWebUITest}
481 function ManagedExtensionSettingsWebUITest() {}
483 ManagedExtensionSettingsWebUITest
.prototype = {
484 __proto__
: InstallGoodExtensionSettingsWebUITest
.prototype,
487 testGenPreamble: function() {
488 GEN(' AddManagedPolicyProvider();');
489 InstallGoodExtensionSettingsWebUITest
.prototype.testGenPreamble
.call(this);
493 TEST_F('ManagedExtensionSettingsWebUITest', 'testAccessibility', function() {
494 this.emptyTestForAccessibility();
499 * @extends {InstallGoodExtensionSettingsWebUITest}
501 function OptionsDialogExtensionSettingsWebUITest() {}
503 OptionsDialogExtensionSettingsWebUITest
.prototype = {
504 __proto__
: InstallGoodExtensionSettingsWebUITest
.prototype,
507 browsePreload
: ExtensionSettingsWebUITest
.prototype.browsePreload
+
508 '?options=' + GOOD_EXTENSION_ID
,
511 TEST_F('OptionsDialogExtensionSettingsWebUITest', 'testAccessibility',
513 this.emptyTestForAccessibility();