NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / ui / webui / options / options_browsertest.js
blob36fb74799879a17870b16655dc6a78a3f1cd0106
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 GEN('#include "chrome/browser/ui/webui/options/options_browsertest.h"');
7 /** @const */ var MANAGED_USERS_PREF = 'profile.managed_users';
9 /**
10 * Wait for the method specified by |methodName|, on the |object| object, to be
11 * called, then execute |afterFunction|.
13 function waitForResponse(object, methodName, afterFunction) {
14 var originalCallback = object[methodName];
16 // Install a wrapper that temporarily replaces the original function.
17 object[methodName] = function() {
18 object[methodName] = originalCallback;
19 originalCallback.apply(this, arguments);
20 afterFunction();
24 /**
25 * Wait for the global window.onpopstate callback to be called (after a tab
26 * history navigation), then execute |afterFunction|.
28 function waitForPopstate(afterFunction) {
29 waitForResponse(window, 'onpopstate', afterFunction);
32 /**
33 * TestFixture for OptionsPage WebUI testing.
34 * @extends {testing.Test}
35 * @constructor
37 function OptionsWebUITest() {}
39 OptionsWebUITest.prototype = {
40 __proto__: testing.Test.prototype,
42 /** @override */
43 accessibilityIssuesAreErrors: true,
45 /** @override */
46 setUp: function() {
47 // user-image-stream is a streaming video element used for capturing a
48 // user image during OOBE.
49 this.accessibilityAuditConfig.ignoreSelectors('videoWithoutCaptions',
50 '.user-image-stream');
53 /**
54 * Browse to the options page & call our preLoad().
56 browsePreload: 'chrome://settings-frame',
58 isAsync: true,
60 /**
61 * Register a mock handler to ensure expectations are met and options pages
62 * behave correctly.
64 preLoad: function() {
65 this.makeAndRegisterMockHandler(
66 ['defaultZoomFactorAction',
67 'fetchPrefs',
68 'observePrefs',
69 'setBooleanPref',
70 'setIntegerPref',
71 'setDoublePref',
72 'setStringPref',
73 'setObjectPref',
74 'clearPref',
75 'coreOptionsUserMetricsAction',
76 ]);
78 // Register stubs for methods expected to be called before/during tests.
79 // Specific expectations can be made in the tests themselves.
80 this.mockHandler.stubs().fetchPrefs(ANYTHING);
81 this.mockHandler.stubs().observePrefs(ANYTHING);
82 this.mockHandler.stubs().coreOptionsUserMetricsAction(ANYTHING);
86 // Crashes on Mac only. See http://crbug.com/79181
87 GEN('#if defined(OS_MACOSX)');
88 GEN('#define MAYBE_testSetBooleanPrefTriggers ' +
89 'DISABLED_testSetBooleanPrefTriggers');
90 GEN('#else');
91 GEN('#define MAYBE_testSetBooleanPrefTriggers testSetBooleanPrefTriggers');
92 GEN('#endif // defined(OS_MACOSX)');
94 TEST_F('OptionsWebUITest', 'MAYBE_testSetBooleanPrefTriggers', function() {
95 // TODO(dtseng): make generic to click all buttons.
96 var showHomeButton = $('show-home-button');
97 var trueListValue = [
98 'browser.show_home_button',
99 true,
100 'Options_Homepage_HomeButton',
102 // Note: this expectation is checked in testing::Test::tearDown.
103 this.mockHandler.expects(once()).setBooleanPref(trueListValue);
105 // Cause the handler to be called.
106 showHomeButton.click();
107 showHomeButton.blur();
108 testDone();
111 // Not meant to run on ChromeOS at this time.
112 // Not finishing in windows. http://crbug.com/81723
113 TEST_F('OptionsWebUITest', 'DISABLED_testRefreshStaysOnCurrentPage',
114 function() {
115 assertTrue($('search-engine-manager-page').hidden);
116 var item = $('manage-default-search-engines');
117 item.click();
119 assertFalse($('search-engine-manager-page').hidden);
121 window.location.reload();
123 assertEquals('chrome://settings-frame/searchEngines', document.location.href);
124 assertFalse($('search-engine-manager-page').hidden);
125 testDone();
129 * Test the default zoom factor select element.
131 TEST_F('OptionsWebUITest', 'testDefaultZoomFactor', function() {
132 // The expected minimum length of the |defaultZoomFactor| element.
133 var defaultZoomFactorMinimumLength = 10;
134 // Verify that the zoom factor element exists.
135 var defaultZoomFactor = $('defaultZoomFactor');
136 assertNotEquals(defaultZoomFactor, null);
138 // Verify that the zoom factor element has a reasonable number of choices.
139 expectGE(defaultZoomFactor.options.length, defaultZoomFactorMinimumLength);
141 // Simulate a change event, selecting the highest zoom value. Verify that
142 // the javascript handler was invoked once.
143 this.mockHandler.expects(once()).defaultZoomFactorAction(NOT_NULL).
144 will(callFunction(function() { }));
145 defaultZoomFactor.selectedIndex = defaultZoomFactor.options.length - 1;
146 var event = { target: defaultZoomFactor };
147 if (defaultZoomFactor.onchange) defaultZoomFactor.onchange(event);
148 testDone();
151 // If |confirmInterstitial| is true, the OK button of the Do Not Track
152 // interstitial is pressed, otherwise the abort button is pressed.
153 OptionsWebUITest.prototype.testDoNotTrackInterstitial =
154 function(confirmInterstitial) {
155 Preferences.prefsFetchedCallback({'enable_do_not_track': {'value': false } });
156 var buttonToClick = confirmInterstitial ? $('do-not-track-confirm-ok')
157 : $('do-not-track-confirm-cancel');
158 var dntCheckbox = $('do-not-track-enabled');
159 var dntOverlay = OptionsPage.registeredOverlayPages['donottrackconfirm'];
160 assertFalse(dntCheckbox.checked);
162 var visibleChangeCounter = 0;
163 var visibleChangeHandler = function() {
164 ++visibleChangeCounter;
165 switch (visibleChangeCounter) {
166 case 1:
167 window.setTimeout(function() {
168 assertTrue(dntOverlay.visible);
169 buttonToClick.click();
170 }, 0);
171 break;
172 case 2:
173 window.setTimeout(function() {
174 assertFalse(dntOverlay.visible);
175 assertEquals(confirmInterstitial, dntCheckbox.checked);
176 dntOverlay.removeEventListener(visibleChangeHandler);
177 testDone();
178 }, 0);
179 break;
180 default:
181 assertTrue(false);
184 dntOverlay.addEventListener('visibleChange', visibleChangeHandler);
186 if (confirmInterstitial) {
187 this.mockHandler.expects(once()).setBooleanPref(
188 ['enable_do_not_track', true, 'Options_DoNotTrackCheckbox']);
189 } else {
190 // The mock handler complains if setBooleanPref is called even though
191 // it should not be.
194 dntCheckbox.click();
197 TEST_F('OptionsWebUITest', 'EnableDoNotTrackAndConfirmInterstitial',
198 function() {
199 this.testDoNotTrackInterstitial(true);
202 TEST_F('OptionsWebUITest', 'EnableDoNotTrackAndCancelInterstitial',
203 function() {
204 this.testDoNotTrackInterstitial(false);
207 // Check that the "Do not Track" preference can be correctly disabled.
208 // In order to do that, we need to enable it first.
209 TEST_F('OptionsWebUITest', 'EnableAndDisableDoNotTrack', function() {
210 Preferences.prefsFetchedCallback({'enable_do_not_track': {'value': false } });
211 var dntCheckbox = $('do-not-track-enabled');
212 var dntOverlay = OptionsPage.registeredOverlayPages['donottrackconfirm'];
213 assertFalse(dntCheckbox.checked);
215 var visibleChangeCounter = 0;
216 var visibleChangeHandler = function() {
217 ++visibleChangeCounter;
218 switch (visibleChangeCounter) {
219 case 1:
220 window.setTimeout(function() {
221 assertTrue(dntOverlay.visible);
222 $('do-not-track-confirm-ok').click();
223 }, 0);
224 break;
225 case 2:
226 window.setTimeout(function() {
227 assertFalse(dntOverlay.visible);
228 assertTrue(dntCheckbox.checked);
229 dntOverlay.removeEventListener(visibleChangeHandler);
230 dntCheckbox.click();
231 }, 0);
232 break;
233 default:
234 assertNotReached();
237 dntOverlay.addEventListener('visibleChange', visibleChangeHandler);
239 this.mockHandler.expects(once()).setBooleanPref(
240 eq(["enable_do_not_track", true, 'Options_DoNotTrackCheckbox']));
242 var verifyCorrectEndState = function() {
243 window.setTimeout(function() {
244 assertFalse(dntOverlay.visible);
245 assertFalse(dntCheckbox.checked);
246 testDone();
247 }, 0)
249 this.mockHandler.expects(once()).setBooleanPref(
250 eq(["enable_do_not_track", false, 'Options_DoNotTrackCheckbox'])).will(
251 callFunction(verifyCorrectEndState));
253 dntCheckbox.click();
256 // Verify that preventDefault() is called on 'Enter' keydown events that trigger
257 // the default button. If this doesn't happen, other elements that may get
258 // focus (by the overlay closing for instance), will execute in addition to the
259 // default button. See crbug.com/268336.
260 TEST_F('OptionsWebUITest', 'EnterPreventsDefault', function() {
261 var page = HomePageOverlay.getInstance();
262 OptionsPage.showPageByName(page.name);
263 var event = new KeyboardEvent('keydown', {
264 'bubbles': true,
265 'cancelable': true,
266 'keyIdentifier': 'Enter'
268 assertFalse(event.defaultPrevented);
269 page.pageDiv.dispatchEvent(event);
270 assertTrue(event.defaultPrevented);
271 testDone();
274 // Verifies that sending an empty list of indexes to move doesn't crash chrome.
275 TEST_F('OptionsWebUITest', 'emptySelectedIndexesDoesntCrash', function() {
276 chrome.send('dragDropStartupPage', [0, []]);
277 setTimeout(testDone);
280 // Flaky on win. See http://crbug.com/315250
281 GEN('#if defined(OS_WIN)');
282 GEN('#define MAYBE_OverlayShowDoesntShift DISABLED_OverlayShowDoesntShift');
283 GEN('#else');
284 GEN('#define MAYBE_OverlayShowDoesntShift OverlayShowDoesntShift');
285 GEN('#endif // defined(OS_WIN)');
287 // An overlay's position should remain the same as it shows.
288 TEST_F('OptionsWebUITest', 'MAYBE_OverlayShowDoesntShift', function() {
289 var overlayName = 'startup';
290 var overlay = $('startup-overlay');
291 var frozenPages = document.getElementsByClassName('frozen'); // Gets updated.
292 expectEquals(0, frozenPages.length);
294 document.addEventListener('webkitTransitionEnd', function(e) {
295 if (e.target != overlay)
296 return;
298 assertFalse(overlay.classList.contains('transparent'));
299 expectEquals(numFrozenPages, frozenPages.length);
300 testDone();
303 OptionsPage.navigateToPage(overlayName);
304 var numFrozenPages = frozenPages.length;
305 expectGT(numFrozenPages, 0);
309 * TestFixture for OptionsPage WebUI testing including tab history and support
310 * for preference manipulation. If you don't need the features in the C++
311 * fixture, use the simpler OptionsWebUITest (above) instead.
312 * @extends {testing.Test}
313 * @constructor
315 function OptionsWebUIExtendedTest() {}
317 OptionsWebUIExtendedTest.prototype = {
318 __proto__: testing.Test.prototype,
320 /** @override */
321 browsePreload: 'chrome://settings-frame',
323 /** @override */
324 typedefCppFixture: 'OptionsBrowserTest',
326 testGenPreamble: function() {
327 // Start with no supervised users managed by this profile.
328 GEN(' ClearPref("' + MANAGED_USERS_PREF + '");');
331 /** @override */
332 isAsync: true,
334 /** @override */
335 setUp: function () {
336 // user-image-stream is a streaming video element used for capturing a
337 // user image during OOBE.
338 this.accessibilityAuditConfig.ignoreSelectors('videoWithoutCaptions',
339 '.user-image-stream');
343 * Asserts that two non-nested arrays are equal. The arrays must contain only
344 * plain data types, no nested arrays or other objects.
345 * @param {Array} expected An array of expected values.
346 * @param {Array} result An array of actual values.
347 * @param {boolean} doSort If true, the arrays will be sorted before being
348 * compared.
349 * @param {string} description A brief description for the array of actual
350 * values, to use in an error message if the arrays differ.
351 * @private
353 compareArrays_: function(expected, result, doSort, description) {
354 var errorMessage = '\n' + description + ': ' + result +
355 '\nExpected: ' + expected;
356 assertEquals(expected.length, result.length, errorMessage);
358 var expectedSorted = expected.slice();
359 var resultSorted = result.slice();
360 if (doSort) {
361 expectedSorted.sort();
362 resultSorted.sort();
365 for (var i = 0; i < expectedSorted.length; ++i) {
366 assertEquals(expectedSorted[i], resultSorted[i], errorMessage);
371 * Verifies that the correct pages are currently open/visible.
372 * @param {!Array.<string>} expectedPages An array of page names expected to
373 * be open, with the topmost listed last.
374 * @param {string=} expectedUrl The URL path, including hash, expected to be
375 * open. If undefined, the topmost (last) page name in |expectedPages|
376 * will be used. In either case, 'chrome://settings-frame/' will be
377 * prepended.
378 * @private
380 verifyOpenPages_: function(expectedPages, expectedUrl) {
381 // Check the topmost page.
382 assertEquals(null, OptionsPage.getVisibleBubble());
383 var currentPage = OptionsPage.getTopmostVisiblePage();
385 var lastExpected = expectedPages[expectedPages.length - 1];
386 assertEquals(lastExpected, currentPage.name);
387 // We'd like to check the title too, but we have to load the settings-frame
388 // instead of the outer settings page in order to have access to
389 // OptionsPage, and setting the title from within the settings-frame fails
390 // because of cross-origin access restrictions.
391 // TODO(pamg): Add a test fixture that loads chrome://settings and uses
392 // UI elements to access sub-pages, so we can test the titles and
393 // search-page URLs.
394 var fullExpectedUrl = 'chrome://settings-frame/' +
395 (expectedUrl ? expectedUrl : lastExpected);
396 assertEquals(fullExpectedUrl, window.location.href);
398 // Collect open pages.
399 var allPageNames = Object.keys(OptionsPage.registeredPages).concat(
400 Object.keys(OptionsPage.registeredOverlayPages));
401 var openPages = [];
402 for (var i = 0; i < allPageNames.length; ++i) {
403 var name = allPageNames[i];
404 var page = OptionsPage.registeredPages[name] ||
405 OptionsPage.registeredOverlayPages[name];
406 if (page.visible)
407 openPages.push(page.name);
410 this.compareArrays_(expectedPages, openPages, true, 'Open pages');
414 * Verifies that the correct URLs are listed in the history. Asynchronous.
415 * @param {!Array.<string>} expectedHistory An array of URL paths expected to
416 * be in the tab navigation history, sorted by visit time, including the
417 * current page as the last entry. The base URL (chrome://settings-frame/)
418 * will be prepended to each. An initial 'about:blank' history entry is
419 * assumed and should not be included in this list.
420 * @param {Function=} callback A function to be called after the history has
421 * been verified successfully. May be undefined.
422 * @private
424 verifyHistory_: function(expectedHistory, callback) {
425 var self = this;
426 OptionsWebUIExtendedTest.verifyHistoryCallback = function(results) {
427 // The history always starts with a blank page.
428 assertEquals('about:blank', results.shift());
429 var fullExpectedHistory = [];
430 for (var i = 0; i < expectedHistory.length; ++i) {
431 fullExpectedHistory.push(
432 'chrome://settings-frame/' + expectedHistory[i]);
434 self.compareArrays_(fullExpectedHistory, results, false, 'History');
435 callback();
438 // The C++ fixture will call verifyHistoryCallback with the results.
439 chrome.send('optionsTestReportHistory');
443 * Overrides the page callbacks for the given OptionsPage overlay to verify
444 * that they are not called.
445 * @param {Object} overlay The singleton instance of the overlay.
446 * @private
448 prohibitChangesToOverlay_: function(overlay) {
449 overlay.initializePage =
450 overlay.didShowPage =
451 overlay.didClosePage = function() {
452 assertTrue(false,
453 'Overlay was affected when changes were prohibited.');
459 * Set by verifyHistory_ to incorporate a followup callback, then called by the
460 * C++ fixture with the navigation history to be verified.
461 * @type {Function}
463 OptionsWebUIExtendedTest.verifyHistoryCallback = null;
465 // Show the search page with no query string, to fall back to the settings page.
466 // Test disabled because it's flaky. crbug.com/303841
467 TEST_F('OptionsWebUIExtendedTest', 'DISABLED_ShowSearchPageNoQuery',
468 function() {
469 OptionsPage.showPageByName('search');
470 this.verifyOpenPages_(['settings']);
471 this.verifyHistory_(['settings'], testDone);
474 // Show a page without updating history.
475 TEST_F('OptionsWebUIExtendedTest', 'ShowPageNoHistory', function() {
476 this.verifyOpenPages_(['settings']);
477 // There are only two main pages, 'settings' and 'search'. It's not possible
478 // to show the search page using OptionsPage.showPageByName, because it
479 // reverts to the settings page if it has no search text set. So we show the
480 // search page by performing a search, then test showPageByName.
481 $('search-field').onsearch({currentTarget: {value: 'query'}});
483 // The settings page is also still "open" (i.e., visible), in order to show
484 // the search results. Furthermore, the URL hasn't been updated in the parent
485 // page, because we've loaded the chrome-settings frame instead of the whole
486 // settings page, so the cross-origin call to set the URL fails.
487 this.verifyOpenPages_(['settings', 'search'], 'settings#query');
488 var self = this;
489 this.verifyHistory_(['settings', 'settings#query'], function() {
490 OptionsPage.showPageByName('settings', false);
491 self.verifyOpenPages_(['settings'], 'settings#query');
492 self.verifyHistory_(['settings', 'settings#query'], testDone);
496 TEST_F('OptionsWebUIExtendedTest', 'ShowPageWithHistory', function() {
497 // See comments for ShowPageNoHistory.
498 $('search-field').onsearch({currentTarget: {value: 'query'}});
499 var self = this;
500 this.verifyHistory_(['settings', 'settings#query'], function() {
501 OptionsPage.showPageByName('settings', true);
502 self.verifyOpenPages_(['settings'], 'settings#query');
503 self.verifyHistory_(['settings', 'settings#query', 'settings#query'],
504 testDone);
508 TEST_F('OptionsWebUIExtendedTest', 'ShowPageReplaceHistory', function() {
509 // See comments for ShowPageNoHistory.
510 $('search-field').onsearch({currentTarget: {value: 'query'}});
511 var self = this;
512 this.verifyHistory_(['settings', 'settings#query'], function() {
513 OptionsPage.showPageByName('settings', true, {'replaceState': true});
514 self.verifyOpenPages_(['settings'], 'settings#query');
515 self.verifyHistory_(['settings', 'settings#query'], testDone);
519 // This should be identical to ShowPageWithHisory.
520 TEST_F('OptionsWebUIExtendedTest', 'NavigateToPage', function() {
521 // See comments for ShowPageNoHistory.
522 $('search-field').onsearch({currentTarget: {value: 'query'}});
523 var self = this;
524 this.verifyHistory_(['settings', 'settings#query'], function() {
525 OptionsPage.navigateToPage('settings');
526 self.verifyOpenPages_(['settings'], 'settings#query');
527 self.verifyHistory_(['settings', 'settings#query', 'settings#query'],
528 testDone);
532 // Settings overlays are much more straightforward than settings pages, opening
533 // normally with none of the latter's quirks in the expected history or URL.
534 TEST_F('OptionsWebUIExtendedTest', 'ShowOverlayNoHistory', function() {
535 // Open a layer-1 overlay, not updating history.
536 OptionsPage.showPageByName('languages', false);
537 this.verifyOpenPages_(['settings', 'languages'], 'settings');
539 var self = this;
540 this.verifyHistory_(['settings'], function() {
541 // Open a layer-2 overlay for which the layer-1 is a parent, not updating
542 // history.
543 OptionsPage.showPageByName('addLanguage', false);
544 self.verifyOpenPages_(['settings', 'languages', 'addLanguage'],
545 'settings');
546 self.verifyHistory_(['settings'], testDone);
550 TEST_F('OptionsWebUIExtendedTest', 'ShowOverlayWithHistory', function() {
551 // Open a layer-1 overlay, updating history.
552 OptionsPage.showPageByName('languages', true);
553 this.verifyOpenPages_(['settings', 'languages']);
555 var self = this;
556 this.verifyHistory_(['settings', 'languages'], function() {
557 // Open a layer-2 overlay, updating history.
558 OptionsPage.showPageByName('addLanguage', true);
559 self.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
560 self.verifyHistory_(['settings', 'languages', 'addLanguage'], testDone);
564 TEST_F('OptionsWebUIExtendedTest', 'ShowOverlayReplaceHistory', function() {
565 // Open a layer-1 overlay, updating history.
566 OptionsPage.showPageByName('languages', true);
567 var self = this;
568 this.verifyHistory_(['settings', 'languages'], function() {
569 // Open a layer-2 overlay, replacing history.
570 OptionsPage.showPageByName('addLanguage', true, {'replaceState': true});
571 self.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
572 self.verifyHistory_(['settings', 'addLanguage'], testDone);
576 // Directly show an overlay further above this page, i.e. one for which the
577 // current page is an ancestor but not a parent.
578 TEST_F('OptionsWebUIExtendedTest', 'ShowOverlayFurtherAbove', function() {
579 // Open a layer-2 overlay directly.
580 OptionsPage.showPageByName('addLanguage', true);
581 this.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
582 var self = this;
583 this.verifyHistory_(['settings', 'addLanguage'], testDone);
586 // Directly show a layer-2 overlay for which the layer-1 overlay is not a
587 // parent.
588 TEST_F('OptionsWebUIExtendedTest', 'ShowUnrelatedOverlay', function() {
589 // Open a layer-1 overlay.
590 OptionsPage.showPageByName('languages', true);
591 this.verifyOpenPages_(['settings', 'languages']);
593 var self = this;
594 this.verifyHistory_(['settings', 'languages'], function() {
595 // Open an unrelated layer-2 overlay.
596 OptionsPage.showPageByName('cookies', true);
597 self.verifyOpenPages_(['settings', 'content', 'cookies']);
598 self.verifyHistory_(['settings', 'languages', 'cookies'], testDone);
602 // Close an overlay.
603 TEST_F('OptionsWebUIExtendedTest', 'CloseOverlay', function() {
604 // Open a layer-1 overlay, then a layer-2 overlay on top of it.
605 OptionsPage.showPageByName('languages', true);
606 this.verifyOpenPages_(['settings', 'languages']);
607 OptionsPage.showPageByName('addLanguage', true);
608 this.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
610 var self = this;
611 this.verifyHistory_(['settings', 'languages', 'addLanguage'], function() {
612 // Close the layer-2 overlay.
613 OptionsPage.closeOverlay();
614 self.verifyOpenPages_(['settings', 'languages']);
615 self.verifyHistory_(
616 ['settings', 'languages', 'addLanguage', 'languages'],
617 function() {
618 // Close the layer-1 overlay.
619 OptionsPage.closeOverlay();
620 self.verifyOpenPages_(['settings']);
621 self.verifyHistory_(
622 ['settings', 'languages', 'addLanguage', 'languages', 'settings'],
623 testDone);
628 // Make sure an overlay isn't closed (even temporarily) when another overlay is
629 // opened on top.
630 TEST_F('OptionsWebUIExtendedTest', 'OverlayAboveNoReset', function() {
631 // Open a layer-1 overlay.
632 OptionsPage.showPageByName('languages', true);
633 this.verifyOpenPages_(['settings', 'languages']);
635 // Open a layer-2 overlay on top. This should not close 'languages'.
636 this.prohibitChangesToOverlay_(options.LanguageOptions.getInstance());
637 OptionsPage.showPageByName('addLanguage', true);
638 this.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
639 testDone();
642 TEST_F('OptionsWebUIExtendedTest', 'OverlayTabNavigation', function() {
643 // Open a layer-1 overlay, then a layer-2 overlay on top of it.
644 OptionsPage.showPageByName('languages', true);
645 OptionsPage.showPageByName('addLanguage', true);
646 var self = this;
648 // Go back twice, then forward twice.
649 self.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
650 self.verifyHistory_(['settings', 'languages', 'addLanguage'], function() {
651 window.history.back();
652 waitForPopstate(function() {
653 self.verifyOpenPages_(['settings', 'languages']);
654 self.verifyHistory_(['settings', 'languages'], function() {
655 window.history.back();
656 waitForPopstate(function() {
657 self.verifyOpenPages_(['settings']);
658 self.verifyHistory_(['settings'], function() {
659 window.history.forward();
660 waitForPopstate(function() {
661 self.verifyOpenPages_(['settings', 'languages']);
662 self.verifyHistory_(['settings', 'languages'], function() {
663 window.history.forward();
664 waitForPopstate(function() {
665 self.verifyOpenPages_(
666 ['settings', 'languages', 'addLanguage']);
667 self.verifyHistory_(
668 ['settings', 'languages', 'addLanguage'], testDone);
679 // Going "back" to an overlay that's a child of the current overlay shouldn't
680 // close the current one.
681 TEST_F('OptionsWebUIExtendedTest', 'OverlayBackToChild', function() {
682 // Open a layer-1 overlay, then a layer-2 overlay on top of it.
683 OptionsPage.showPageByName('languages', true);
684 OptionsPage.showPageByName('addLanguage', true);
685 var self = this;
687 self.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
688 self.verifyHistory_(['settings', 'languages', 'addLanguage'], function() {
689 // Close the top overlay, then go back to it.
690 OptionsPage.closeOverlay();
691 self.verifyOpenPages_(['settings', 'languages']);
692 self.verifyHistory_(
693 ['settings', 'languages', 'addLanguage', 'languages'],
694 function() {
695 // Going back to the 'addLanguage' page should not close 'languages'.
696 self.prohibitChangesToOverlay_(options.LanguageOptions.getInstance());
697 window.history.back();
698 waitForPopstate(function() {
699 self.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
700 self.verifyHistory_(['settings', 'languages', 'addLanguage'],
701 testDone);
707 // Going back to an unrelated overlay should close the overlay and its parent.
708 TEST_F('OptionsWebUIExtendedTest', 'OverlayBackToUnrelated', function() {
709 // Open a layer-1 overlay, then an unrelated layer-2 overlay.
710 OptionsPage.showPageByName('languages', true);
711 OptionsPage.showPageByName('cookies', true);
712 var self = this;
713 self.verifyOpenPages_(['settings', 'content', 'cookies']);
714 self.verifyHistory_(['settings', 'languages', 'cookies'], function() {
715 window.history.back();
716 waitForPopstate(function() {
717 self.verifyOpenPages_(['settings', 'languages']);
718 testDone();
723 // Verify history changes properly while the page is loading.
724 TEST_F('OptionsWebUIExtendedTest', 'HistoryUpdatedAfterLoading', function() {
725 var loc = location.href;
727 document.documentElement.classList.add('loading');
728 assertTrue(OptionsPage.isLoading());
729 OptionsPage.navigateToPage('searchEngines');
730 expectNotEquals(loc, location.href);
732 document.documentElement.classList.remove('loading');
733 assertFalse(OptionsPage.isLoading());
734 OptionsPage.showDefaultPage();
735 expectEquals(loc, location.href);
737 testDone();
740 // A tip should be shown or hidden depending on whether this profile manages any
741 // supervised users.
742 TEST_F('OptionsWebUIExtendedTest', 'SupervisingUsers', function() {
743 // We start managing no supervised users.
744 assertTrue($('profiles-supervised-dashboard-tip').hidden);
746 // Remove all supervised users, then add some, watching for the pref change
747 // notifications and UI updates in each case. Any non-empty pref dictionary
748 // is interpreted as having supervised users.
749 chrome.send('optionsTestSetPref', [MANAGED_USERS_PREF, {key: 'value'}]);
750 waitForResponse(BrowserOptions, 'updateManagesSupervisedUsers', function() {
751 assertFalse($('profiles-supervised-dashboard-tip').hidden);
752 chrome.send('optionsTestSetPref', [MANAGED_USERS_PREF, {}]);
753 waitForResponse(BrowserOptions, 'updateManagesSupervisedUsers', function() {
754 assertTrue($('profiles-supervised-dashboard-tip').hidden);
755 testDone();