diff --git a/test-utils/pushStateMock.js b/test-utils/pushStateMock.js index ebd963fd4..c727f3930 100644 --- a/test-utils/pushStateMock.js +++ b/test-utils/pushStateMock.js @@ -1,6 +1,18 @@ "use strict" var parseURL = require("../test-utils/parseURL") +var callAsync = require("../test-utils/callAsync.js") + +function debouncedAsync(f) { + var ref + return function() { + if (ref != null) return + ref = callAsync(function(){ + ref = null + f() + }) + } +} module.exports = function(options) { if (options == null) options = {} @@ -29,7 +41,9 @@ module.exports = function(options) { if (data.search != null && data.search !== search) search = data.search, isNew = true if (data.hash != null && data.hash !== hash) { hash = data.hash - if (!isNew) hashchange() + if (!isNew) { + hashchange() + } } return isNew } @@ -38,9 +52,10 @@ module.exports = function(options) { if (value === "") return "" return (value.charAt(0) !== prefix ? prefix : "") + value } - function hashchange() { + function _hashchange() { if (typeof $window.onhashchange === "function") $window.onhashchange({type: "hashchange"}) } + var hashchange = debouncedAsync(_hashchange) function popstate() { if (typeof $window.onpopstate === "function") $window.onpopstate({type: "popstate", state: $window.history.state}) } diff --git a/test-utils/tests/test-pushStateMock.js b/test-utils/tests/test-pushStateMock.js index 41efacab1..b07ee1b4c 100644 --- a/test-utils/tests/test-pushStateMock.js +++ b/test-utils/tests/test-pushStateMock.js @@ -2,7 +2,7 @@ var o = require("../../ospec/ospec") var pushStateMock = require("../../test-utils/pushStateMock") - +var callAsync = require("../../test-utils/callAsync") o.spec("pushStateMock", function() { var $window @@ -478,93 +478,160 @@ o.spec("pushStateMock", function() { }) }) o.spec("onhashchance", function() { - o("onhashchange triggers on location.href change", function() { + o("onhashchange triggers on location.href change", function(done) { $window.onhashchange = o.spy() $window.location.href = "http://localhost/#a" - o($window.onhashchange.callCount).equals(1) - o($window.onhashchange.args[0].type).equals("hashchange") + callAsync(function(){ + o($window.onhashchange.callCount).equals(1) + o($window.onhashchange.args[0].type).equals("hashchange") + done() + }) }) - o("onhashchange triggers on relative location.href change", function() { + o("onhashchange triggers on relative location.href change", function(done) { $window.onhashchange = o.spy() $window.location.href = "#a" - o($window.onhashchange.callCount).equals(1) + callAsync(function(){ + o($window.onhashchange.callCount).equals(1) + done() + }) }) - o("onhashchange triggers on location.hash change", function() { + o("onhashchange triggers on location.hash change", function(done) { $window.onhashchange = o.spy() $window.location.hash = "#a" - o($window.onhashchange.callCount).equals(1) + callAsync(function(){ + o($window.onhashchange.callCount).equals(1) + done() + }) }) - o("onhashchange does not trigger on page change", function() { + o("onhashchange does not trigger on page change", function(done) { $window.onhashchange = o.spy() $window.location.href = "http://localhost/a" - o($window.onhashchange.callCount).equals(0) + callAsync(function(){ + o($window.onhashchange.callCount).equals(0) + done() + }) }) - o("onhashchange does not trigger on page change with different hash", function() { + o("onhashchange does not trigger on page change with different hash", function(done) { $window.location.href = "http://localhost/#a" - $window.onhashchange = o.spy() - $window.location.href = "http://localhost/a#b" + callAsync(function(){ + $window.onhashchange = o.spy() + $window.location.href = "http://localhost/a#b" - o($window.onhashchange.callCount).equals(0) + callAsync(function(){ + o($window.onhashchange.callCount).equals(0) + done() + }) + }) }) - o("onhashchange does not trigger on page change with same hash", function() { + o("onhashchange does not trigger on page change with same hash", function(done) { $window.location.href = "http://localhost/#b" - $window.onhashchange = o.spy() - $window.location.href = "http://localhost/a#b" + callAsync(function(){ + $window.onhashchange = o.spy() + $window.location.href = "http://localhost/a#b" - o($window.onhashchange.callCount).equals(0) + callAsync(function(){ + o($window.onhashchange.callCount).equals(0) + done() + }) + }) }) - o("onhashchange triggers on history.back()", function() { + o("onhashchange triggers on history.back()", function(done) { $window.location.href = "#a" - $window.onhashchange = o.spy() - $window.history.back() + callAsync(function(){ + $window.onhashchange = o.spy() + $window.history.back() - o($window.onhashchange.callCount).equals(1) + callAsync(function(){ + o($window.onhashchange.callCount).equals(1) + done() + }) + }) }) - o("onhashchange triggers on history.forward()", function() { + o("onhashchange triggers on history.forward()", function(done) { $window.location.href = "#a" - $window.onhashchange = o.spy() - $window.history.back() - $window.history.forward() - - o($window.onhashchange.callCount).equals(2) - }) - o("onhashchange does not trigger on history.back() that causes page change with different hash", function() { + callAsync(function(){ + $window.onhashchange = o.spy() + $window.history.back() + callAsync(function(){ + $window.history.forward() + + callAsync(function(){ + o($window.onhashchange.callCount).equals(2) + done() + }) + }) + }) + }) + o("onhashchange triggers once when the hash changes twice in a single tick", function(done) { + $window.location.href = "#a" + callAsync(function(){ + $window.onhashchange = o.spy() + $window.history.back() + $window.history.forward() + + callAsync(function(){ + o($window.onhashchange.callCount).equals(1) + done() + }) + }) + }) + o("onhashchange does not trigger on history.back() that causes page change with different hash", function(done) { $window.location.href = "#a" $window.location.href = "a#b" - $window.onhashchange = o.spy() - $window.history.back() + callAsync(function(){ + $window.onhashchange = o.spy() + $window.history.back() - o($window.onhashchange.callCount).equals(0) + callAsync(function(){ + o($window.onhashchange.callCount).equals(0) + done() + }) + }) }) - o("onhashchange does not trigger on history.back() that causes page change with same hash", function() { + o("onhashchange does not trigger on history.back() that causes page change with same hash", function(done) { $window.location.href = "#a" $window.location.href = "a#a" - $window.onhashchange = o.spy() - $window.history.back() + callAsync(function(){ + $window.onhashchange = o.spy() + $window.history.back() - o($window.onhashchange.callCount).equals(0) + callAsync(function(){ + o($window.onhashchange.callCount).equals(0) + done() + }) + }) }) - o("onhashchange does not trigger on history.forward() that causes page change with different hash", function() { + o("onhashchange does not trigger on history.forward() that causes page change with different hash", function(done) { $window.location.href = "#a" $window.location.href = "a#b" - $window.onhashchange = o.spy() - $window.history.back() - $window.history.forward() - - o($window.onhashchange.callCount).equals(0) - }) - o("onhashchange does not trigger on history.forward() that causes page change with same hash", function() { + callAsync(function(){ + $window.onhashchange = o.spy() + $window.history.back() + $window.history.forward() + + callAsync(function(){ + o($window.onhashchange.callCount).equals(0) + done() + }) + }) + }) + o("onhashchange does not trigger on history.forward() that causes page change with same hash", function(done) { $window.location.href = "#a" $window.location.href = "a#b" - $window.onhashchange = o.spy() - $window.history.back() - $window.history.forward() - - o($window.onhashchange.callCount).equals(0) + callAsync(function(){ + $window.onhashchange = o.spy() + $window.history.back() + $window.history.forward() + + callAsync(function(){ + o($window.onhashchange.callCount).equals(0) + done() + }) + }) }) }) o.spec("onunload", function() {