Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / ui / webui / extensions / extension_settings_browsertest.js
blobd7847efc3d2fa46bda9b724ea0ca502c02a7c703
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';
16 /**
17  * Test C++ fixture for settings WebUI testing.
18  * @constructor
19  * @extends {testing.Test}
20  */
21 function ExtensionSettingsUIBrowserTest() {}
23 /**
24  * TestFixture for extension settings WebUI testing.
25  * @extends {testing.Test}
26  * @constructor
27  */
28 function ExtensionSettingsWebUITest() {}
30 ExtensionSettingsWebUITest.prototype = {
31   __proto__: testing.Test.prototype,
33   /** @override */
34   isAsync: true,
36   /** @override */
37   runAccessibilityChecks: true,
39   /** @override */
40   accessibilityIssuesAreErrors: true,
42   /**
43    * A URL to load before starting each test.
44    * @type {string}
45    * @const
46    */
47   browsePreload: 'chrome://extensions-frame/',
49   /** @override */
50   typedefCppFixture: 'ExtensionSettingsUIBrowserTest',
52   /** @override */
53   setUp: function() {
54     testing.Test.disableAnimationsAndTransitions();
55   },
57   /**
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>}
61    * */
62   steps: [],
64   /**
65    * Advances to the next step in the test. Every step should call this.
66    * @protected
67    * */
68   nextStep: function() {
69     assertTrue(this.steps.length > 0);
70     this.steps.shift().call(this);
71   },
73   /**
74    * Will wait for the page to load before calling the next step. This should be
75    * the first step in every test.
76    * @protected
77    * */
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));
82   },
84   /** @protected */
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);
103         waitForPage();
104       });
105     });
107     var extensionSettings = getRequiredElement('extension-settings');
108     assertFalse(extensionSettings.classList.contains('dev-mode'));
109     $('toggle-dev-on').click();
110   },
112   /** @protected */
113   testDeveloperMode: function() {
114     var next = this.nextStep.bind(this);
115     var checkDevModeIsOff = function() {
116       chrome.developerPrivate.getProfileConfiguration(function(profileInfo) {
117         assertFalse(profileInfo.inDeveloperMode);
118         next();
119       });
120     };
121     this.steps = [this.waitForPageLoad,
122                   checkDevModeIsOff,
123                   this.enableDeveloperMode,
124                   testDone];
125     this.nextStep();
126   },
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',
133        function() {
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);
142     this.nextStep();
143   };
145   this.steps = [this.waitForPageLoad, verifyListIsHiddenAndEmpty, testDone];
146   this.nextStep();
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'));
157     this.nextStep();
158   };
160   this.steps = [this.waitForPageLoad, testPackExtenion, testDone];
161   this.nextStep();
165  * @param {chrome.developerPrivate.EventType} eventType
166  * @param {function():void} callback
167  * @constructor
168  */
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 = {
178   /** @private */
179   onItemStateChanged_: function(data) {
180     if (this.eventType_ == data.event_type) {
181       window.setTimeout(function() {
182         chrome.developerPrivate.onItemStateChanged.removeListener(
183             this.onItemStateChangedListener_);
184         this.callback_();
185       }.bind(this), 0);
186     }
187   }
190 function BasicExtensionSettingsWebUITest() {}
192 BasicExtensionSettingsWebUITest.prototype = {
193   __proto__: ExtensionSettingsWebUITest.prototype,
195   /** @override */
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();');
205   },
207   /** @protected */
208   verifyDisabledWorks: function() {
209     var listener = new UpdateListener(
210         chrome.developerPrivate.EventType.UNLOADED,
211         function() {
212       var node = getRequiredElement(GOOD_EXTENSION_ID);
213       assertTrue(node.classList.contains('inactive-extension'));
214       this.nextStep();
215     }.bind(this));
216     chrome.management.setEnabled(GOOD_EXTENSION_ID, false);
217   },
219   /** @protected */
220   verifyEnabledWorks: function() {
221     var listener = new UpdateListener(
222         chrome.developerPrivate.EventType.LOADED,
223         function() {
224       var node = getRequiredElement(GOOD_EXTENSION_ID);
225       assertFalse(node.classList.contains('inactive-extension'));
226       this.nextStep();
227     }.bind(this));
228     chrome.management.setEnabled(GOOD_EXTENSION_ID, true);
229   },
231   /** @protected */
232   verifyUninstallWorks: function() {
233     var listener = new UpdateListener(
234         chrome.developerPrivate.EventType.UNINSTALLED,
235         function() {
236       assertEquals(null, $(GOOD_EXTENSION_ID));
237       this.nextStep();
238     }.bind(this));
239     chrome.test.runWithUserGesture(function() {
240       chrome.management.uninstall(GOOD_EXTENSION_ID);
241     });
242   },
245 // Verify that developer mode doesn't change behavior when the number of
246 // extensions changes.
247 TEST_F('BasicExtensionSettingsWebUITest', 'testDeveloperModeManyExtensions',
248        function() {
249   this.testDeveloperMode();
252 TEST_F('BasicExtensionSettingsWebUITest', 'testDisable', function() {
253   this.steps = [this.waitForPageLoad, this.verifyDisabledWorks, testDone];
254   this.nextStep();
257 TEST_F('BasicExtensionSettingsWebUITest', 'testEnable', function() {
258   this.steps = [this.waitForPageLoad,
259                 this.verifyDisabledWorks,
260                 this.verifyEnabledWorks,
261                 testDone];
262   this.nextStep();
265 TEST_F('BasicExtensionSettingsWebUITest', 'testUninstall', function() {
266   this.steps = [this.waitForPageLoad, this.verifyUninstallWorks, testDone];
267   this.nextStep();
270 TEST_F('BasicExtensionSettingsWebUITest', 'testNonEmptyExtensionList',
271        function() {
272   var verifyListIsNotHiddenAndEmpty = function() {
273     assertFalse($('extension-list-wrapper').hidden);
274     assertTrue($('no-extensions').hidden);
275     assertGT($('extension-settings-list').childNodes.length, 0);
276     this.nextStep();
277   };
279   this.steps = [this.waitForPageLoad, verifyListIsNotHiddenAndEmpty, testDone];
280   this.nextStep();
283 function AutoScrollExtensionSettingsWebUITest() {}
286  * A variation for testing auto-scroll when an id query param is passed in the
287  * url.
288  * @constructor
289  * @extends {BasicExtensionSettingsWebUITest}
290  */
291 AutoScrollExtensionSettingsWebUITest.prototype = {
292   __proto__: BasicExtensionSettingsWebUITest.prototype,
294   /** @override */
295   browsePreload: 'chrome://extensions-frame/?id=' + GOOD_EXTENSION_ID,
297   /** @override */
298   testGenPreamble: function() {
299     BasicExtensionSettingsWebUITest.prototype.testGenPreamble.call(this);
300     // The window needs to be sufficiently small in order to ensure a scroll bar
301     // is available.
302     GEN('  ShrinkWebContentsView();');
303   },
306 TEST_F('AutoScrollExtensionSettingsWebUITest', 'testAutoScroll', function() {
307   var checkHasScrollbar = function() {
308     assertGT(document.body.scrollHeight, document.body.clientHeight);
309     this.nextStep();
310   };
311   var checkIsScrolled = function() {
312     assertGT(document.body.scrollTop, 0);
313     this.nextStep();
314   };
315   var checkScrolledToTop = function() {
316     assertEquals(0, document.body.scrollTop);
317     this.nextStep();
318   };
319   var scrollToTop = function() {
320     document.body.scrollTop = 0;
321     this.nextStep();
322   };
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,
326                 checkHasScrollbar,
327                 checkIsScrolled,
328                 scrollToTop,
329                 this.enableDeveloperMode,
330                 checkScrolledToTop,
331                 testDone];
332   this.nextStep();
335 function ErrorConsoleExtensionSettingsWebUITest() {}
337 ErrorConsoleExtensionSettingsWebUITest.prototype = {
338   __proto__: ExtensionSettingsWebUITest.prototype,
340   /** @override */
341   testGenPreamble: function() {
342     GEN('  EnableErrorConsole();');
343     GEN('  InstallGoodExtension();');
344     GEN('  InstallErrorsExtension();');
345   },
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'));
364     }
366     var hiddenButtons = extensionList.querySelectorAll('.errors-link[hidden]');
367     expectEquals(1, hiddenButtons.length);
369     this.nextStep();
370   };
372   this.steps = [this.waitForPageLoad,
373                 this.enableDeveloperMode,
374                 testButtonVisibility,
375                 testDone];
376   this.nextStep();
380  * TestFixture for extension settings WebUI testing (commands config edition).
381  * @extends {testing.Test}
382  * @constructor
383  */
384 function SettingsCommandsExtensionSettingsWebUITest() {}
386 SettingsCommandsExtensionSettingsWebUITest.prototype = {
387   __proto__: ExtensionSettingsWebUITest.prototype,
389   /**
390    * A URL to load before starting each test.
391    * @type {string}
392    * @const
393    */
394   browsePreload: 'chrome://extensions-frame/configureCommands',
397 TEST_F('SettingsCommandsExtensionSettingsWebUITest', 'testChromeSendHandler',
398     function() {
399   // Just navigating to the page should trigger the chrome.send().
400   var assertOverlayVisible = function() {
401     assertTrue($('extension-commands-overlay').classList.contains('showing'));
402     this.nextStep();
403   };
405   this.steps = [this.waitForPageLoad, assertOverlayVisible, testDone];
406   this.nextStep();
409 TEST_F('SettingsCommandsExtensionSettingsWebUITest', 'extensionSettingsUri',
410     function() {
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'));
420     this.nextStep();
421   };
423   var checkExtensionsUrl = function() {
424     // After closing the overlay, the URL shouldn't include commands overlay
425     // reference.
426     assertEquals(window.location.href, 'chrome://extensions-frame/');
427     this.nextStep();
428   };
430   this.steps = [this.waitForPageLoad,
431                 closeCommandOverlay,
432                 checkExtensionsUrl,
433                 testDone];
434   this.nextStep();
438  * @constructor
439  * @extends {ExtensionSettingsWebUITest}
440  */
441 function InstallGoodExtensionSettingsWebUITest() {}
443 InstallGoodExtensionSettingsWebUITest.prototype = {
444   __proto__: ExtensionSettingsWebUITest.prototype,
446   /** @override */
447   testGenPreamble: function() {
448     GEN('  InstallGoodExtension();');
449   },
451   emptyTestForAccessibility() {
452     this.steps = [this.waitForPageLoad, testDone];
453     this.nextStep();
454   },
457 TEST_F('InstallGoodExtensionSettingsWebUITest', 'testAccessibility',
458        function() {
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});
471   };
473   this.steps = [this.waitForPageLoad, showExtensionOptions, testDone];
474   this.nextStep();
478  * @constructor
479  * @extends {InstallGoodExtensionSettingsWebUITest}
480  */
481 function ManagedExtensionSettingsWebUITest() {}
483 ManagedExtensionSettingsWebUITest.prototype = {
484   __proto__: InstallGoodExtensionSettingsWebUITest.prototype,
486   /** @override */
487   testGenPreamble: function() {
488     GEN('  AddManagedPolicyProvider();');
489     InstallGoodExtensionSettingsWebUITest.prototype.testGenPreamble.call(this);
490   },
493 TEST_F('ManagedExtensionSettingsWebUITest', 'testAccessibility', function() {
494   this.emptyTestForAccessibility();
498  * @constructor
499  * @extends {InstallGoodExtensionSettingsWebUITest}
500  */
501 function OptionsDialogExtensionSettingsWebUITest() {}
503 OptionsDialogExtensionSettingsWebUITest.prototype = {
504   __proto__: InstallGoodExtensionSettingsWebUITest.prototype,
506   /** @override */
507   browsePreload: ExtensionSettingsWebUITest.prototype.browsePreload +
508       '?options=' + GOOD_EXTENSION_ID,
511 TEST_F('OptionsDialogExtensionSettingsWebUITest', 'testAccessibility',
512        function() {
513   this.emptyTestForAccessibility();