Index: chrome/test/data/webui/extensions/extension_navigation_helper_test.js |
diff --git a/chrome/test/data/webui/extensions/extension_navigation_helper_test.js b/chrome/test/data/webui/extensions/extension_navigation_helper_test.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d786733b15b8929d53274be2e9ca5a7abc8fc676 |
--- /dev/null |
+++ b/chrome/test/data/webui/extensions/extension_navigation_helper_test.js |
@@ -0,0 +1,158 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+cr.define('extension_navigation_helper_tests', function() { |
+ /** @enum {string} */ |
+ var TestNames = { |
+ Basic: 'basic', |
+ Conversions: 'conversions', |
+ PushAndReplaceState: 'push and replace state', |
+ }; |
+ |
+ /** |
+ * @return {!Promise<void>} A promise that resolves after the next popstate |
+ * event. |
+ */ |
+ function getOnPopState() { |
+ return new Promise(function(resolve, reject) { |
+ window.addEventListener('popstate', function listener() { |
+ window.removeEventListener('popstate', listener); |
+ // Resolve asynchronously to allow all other listeners to run. |
+ window.setTimeout(resolve, 0); |
+ }); |
+ }); |
+ } |
+ |
+ function registerTests() { |
+ suite('ExtensionNavigationHelperTest', function() { |
+ setup(function() { |
+ PolymerTest.clearBody(); |
+ Polymer.dom.flush(); |
+ }); |
+ |
+ test(assert(TestNames.Basic), function(done) { |
+ var id = 'a'.repeat(32); |
+ var mock = new MockMethod(); |
+ var changePage = function(state) { |
+ mock.recordCall([state]); |
+ }; |
+ var navigationHelper = new extensions.NavigationHelper(changePage); |
+ |
+ expectEquals('chrome://extensions/navigation_helper.html', |
+ location.href); |
+ expectDeepEquals({page: Page.LIST}, navigationHelper.getCurrentPage()); |
+ |
+ var currentLength = history.length; |
+ navigationHelper.updateHistory({page: Page.DETAILS, id: id}); |
+ expectEquals(++currentLength, history.length); |
+ |
+ navigationHelper.updateHistory({page: Page.ERRORS, id: id}); |
+ expectEquals(++currentLength, history.length); |
+ |
+ mock.addExpectation({page: Page.DETAILS, id: id}); |
+ var waitForPop = getOnPopState(); |
+ history.back(); |
+ waitForPop.then(() => { |
michaelpg
2017/05/01 23:41:26
I think returning this Promise will let you elimin
Devlin
2017/05/02 01:04:07
Done.
|
+ mock.verifyMock(); |
+ |
+ mock.addExpectation({page: Page.LIST}); |
+ waitForPop = getOnPopState(); |
michaelpg
2017/05/01 23:41:26
setting a variable in a function passed as an argu
Devlin
2017/05/02 01:04:07
waitFor*Next*Pop? :)
|
+ history.back(); |
+ return waitForPop; |
+ }).then(() => { |
+ mock.verifyMock(); |
+ done(); |
+ }).catch(done); |
+ }); |
+ |
+ test(assert(TestNames.Conversions), function() { |
+ var id = 'a'.repeat(32); |
+ var stateUrlPairs = { |
+ list: { |
+ url: 'chrome://extensions/', |
+ state: {page: Page.LIST}, |
+ }, |
+ details: { |
+ url: 'chrome://extensions/?id=' + id, |
+ state: {page: Page.DETAILS, id: id}, |
+ }, |
+ options: { |
+ url: 'chrome://extensions/?options=' + id, |
+ state: {page: Page.DETAILS, id: id, subpage: Dialog.OPTIONS}, |
+ }, |
+ errors: { |
+ url: 'chrome://extensions/?errors=' + id, |
+ state: {page: Page.ERRORS, id: id}, |
+ }, |
+ shortcuts: { |
+ url: 'chrome://extensions/shortcuts', |
+ state: {page: Page.SHORTCUTS}, |
+ }, |
+ }; |
+ |
+ var navigationHelper = new extensions.NavigationHelper(function() {}); |
+ |
+ // Test url -> state. |
+ for (let key in stateUrlPairs) { |
+ let entry = stateUrlPairs[key]; |
+ history.pushState({}, '', entry.url); |
+ var currentPage = navigationHelper.getCurrentPage(); |
michaelpg
2017/05/01 23:41:26
unused? also, mixing var/let?
Devlin
2017/05/02 01:04:07
Removed.
|
+ expectDeepEquals(entry.state, navigationHelper.getCurrentPage(), key); |
+ } |
+ |
+ // Test state -> url. |
+ for (let key in stateUrlPairs) { |
+ let entry = stateUrlPairs[key]; |
+ navigationHelper.updateHistory(entry.state); |
+ expectEquals(entry.url, location.href, key); |
+ } |
+ }); |
+ |
+ test(assert(TestNames.PushAndReplaceState), function() { |
+ var id1 = 'a'.repeat(32); |
+ var id2 = 'b'.repeat(32); |
+ var navigationHelper = new extensions.NavigationHelper(function() {}); |
+ |
+ history.pushState({}, '', 'chrome://extensions/'); |
+ expectDeepEquals({page: Page.LIST}, navigationHelper.getCurrentPage()); |
+ |
+ var expectedLength = history.length; |
+ |
+ // Navigating to a new page pushes new state. |
+ navigationHelper.updateHistory({page: Page.DETAILS, id: id1}); |
+ expectEquals(++expectedLength, history.length); |
+ |
+ // Navigating to a subpage (like the options page) just opens a dialog, |
+ // and shouldn't push new state. |
+ navigationHelper.updateHistory( |
+ {page: Page.DETAILS, id: id1, subpage: Dialog.OPTIONS}); |
+ expectEquals(expectedLength, history.length); |
+ |
+ // Navigating away from a subpage also shouldn't push state (it just |
+ // closes the dialog). |
+ navigationHelper.updateHistory({page: Page.DETAILS, id: id1}); |
+ expectEquals(expectedLength, history.length); |
+ |
+ // Navigating away should push new state. |
+ navigationHelper.updateHistory({page: Page.LIST}); |
+ expectEquals(++expectedLength, history.length); |
+ |
+ // Navigating to a subpage of a different page should push state. |
+ navigationHelper.updateHistory( |
+ {page: Page.DETAILS, id: id1, subpage: Dialog.OPTIONS}); |
+ expectEquals(++expectedLength, history.length); |
+ |
+ // Navigating away from a subpage to a page for a different item should |
+ // push state. |
+ navigationHelper.updateHistory({page: Page.DETAILS, id: id2}); |
+ expectEquals(++expectedLength, history.length); |
+ }); |
+ }); |
+ } |
+ |
+ return { |
+ registerTests: registerTests, |
+ TestNames: TestNames, |
+ }; |
+}); |