Merge pull request #1466 from pygy/rewrite-router-test-redirection-async-onmatch
[rewrite] (WIP) A few more tests for the router + mock fixes
This commit is contained in:
commit
a3a1516584
5 changed files with 285 additions and 124 deletions
|
|
@ -627,7 +627,7 @@ o.spec("route", function() {
|
|||
render: render
|
||||
},
|
||||
"/b" : {
|
||||
view: function(vnode){
|
||||
view: function() {
|
||||
redirected = true
|
||||
}
|
||||
}
|
||||
|
|
@ -644,6 +644,7 @@ o.spec("route", function() {
|
|||
o("onmatch can redirect to another route that has RouteResolver w/ only onmatch", function(done) {
|
||||
var redirected = false
|
||||
var render = o.spy()
|
||||
var view = o.spy(function() {return m("div")})
|
||||
|
||||
$window.location.href = prefix + "/a"
|
||||
route(root, "/a", {
|
||||
|
|
@ -656,16 +657,21 @@ o.spec("route", function() {
|
|||
"/b" : {
|
||||
onmatch: function() {
|
||||
redirected = true
|
||||
return {view: function() {}}
|
||||
return {view: view}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
callAsync(function() {
|
||||
o(render.callCount).equals(0)
|
||||
o(redirected).equals(true)
|
||||
callAsync(function() {
|
||||
o(render.callCount).equals(0)
|
||||
o(redirected).equals(true)
|
||||
o(view.callCount).equals(1)
|
||||
o(root.childNodes.length).equals(1)
|
||||
o(root.firstChild.nodeName).equals("DIV")
|
||||
|
||||
done()
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -696,6 +702,118 @@ o.spec("route", function() {
|
|||
})
|
||||
})
|
||||
|
||||
o("onmatch can redirect to another route that has RouteResolver whose onmatch resolves asynchronously", function(done) {
|
||||
var redirected = false
|
||||
var render = o.spy()
|
||||
var view = o.spy()
|
||||
|
||||
$window.location.href = prefix + "/a"
|
||||
route(root, "/a", {
|
||||
"/a" : {
|
||||
onmatch: function() {
|
||||
route.set("/b")
|
||||
},
|
||||
render: render
|
||||
},
|
||||
"/b" : {
|
||||
onmatch: function() {
|
||||
redirected = true
|
||||
return new Promise(function(fulfill){
|
||||
callAsync(function(){
|
||||
fulfill({view: view})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
callAsync(function() {
|
||||
callAsync(function() {
|
||||
callAsync(function() {
|
||||
o(render.callCount).equals(0)
|
||||
o(redirected).equals(true)
|
||||
o(view.callCount).equals(1)
|
||||
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
o("onmatch can redirect to another route asynchronously", function(done) {
|
||||
var redirected = false
|
||||
var render = o.spy()
|
||||
var view = o.spy()
|
||||
|
||||
$window.location.href = prefix + "/a"
|
||||
route(root, "/a", {
|
||||
"/a" : {
|
||||
onmatch: function() {
|
||||
callAsync(function() {route.set("/b")})
|
||||
return new Promise(function() {})
|
||||
},
|
||||
render: render
|
||||
},
|
||||
"/b" : {
|
||||
onmatch: function() {
|
||||
redirected = true
|
||||
return {view: view}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
callAsync(function() {
|
||||
callAsync(function() {
|
||||
callAsync(function() {
|
||||
o(render.callCount).equals(0)
|
||||
o(redirected).equals(true)
|
||||
o(view.callCount).equals(1)
|
||||
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
o("onmatch can redirect w/ window.history.back()", function(done) {
|
||||
|
||||
var render = o.spy()
|
||||
var component = {view: o.spy()}
|
||||
|
||||
$window.location.href = prefix + "/a"
|
||||
route(root, "/a", {
|
||||
"/a" : {
|
||||
onmatch: function() {
|
||||
return component
|
||||
},
|
||||
render: function(vnode) {
|
||||
return vnode
|
||||
}
|
||||
},
|
||||
"/b" : {
|
||||
onmatch: function() {
|
||||
$window.history.back()
|
||||
return new Promise(function() {})
|
||||
},
|
||||
render: render
|
||||
}
|
||||
})
|
||||
|
||||
callAsync(function() {
|
||||
route.set('/b')
|
||||
callAsync(function() {
|
||||
callAsync(function() {
|
||||
callAsync(function() {
|
||||
o(render.callCount).equals(0)
|
||||
o(component.view.callCount).equals(2)
|
||||
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
o("onmatch can redirect to a non-existent route that defaults to a RouteResolver w/ onmatch", function(done) {
|
||||
var redirected = false
|
||||
var render = o.spy()
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@ var domMock = require("./domMock")
|
|||
var xhrMock = require("./xhrMock")
|
||||
|
||||
module.exports = function(env) {
|
||||
var $window = {}
|
||||
env = env || {}
|
||||
var $window = env.window = {}
|
||||
|
||||
var dom = domMock()
|
||||
var xhr = xhrMock()
|
||||
var ps = pushStateMock(env)
|
||||
for (var key in dom) if (!$window[key]) $window[key] = dom[key]
|
||||
for (var key in xhr) if (!$window[key]) $window[key] = xhr[key]
|
||||
for (var key in ps) if (!$window[key]) $window[key] = ps[key]
|
||||
pushStateMock(env)
|
||||
|
||||
return $window
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ var parseURL = require("../test-utils/parseURL")
|
|||
module.exports = function(options) {
|
||||
if (options == null) options = {}
|
||||
|
||||
var $window = options.window || {}
|
||||
var protocol = options.protocol || "http:"
|
||||
var hostname = options.hostname || "localhost"
|
||||
var port = ""
|
||||
|
|
@ -32,7 +33,7 @@ module.exports = function(options) {
|
|||
}
|
||||
return isNew
|
||||
}
|
||||
|
||||
|
||||
function prefix(prefix, value) {
|
||||
if (value === "") return ""
|
||||
return (value.charAt(0) !== prefix ? prefix : "") + value
|
||||
|
|
@ -46,125 +47,125 @@ module.exports = function(options) {
|
|||
function unload() {
|
||||
if (typeof $window.onunload === "function") $window.onunload({type: "unload"})
|
||||
}
|
||||
var $window = {
|
||||
location: {
|
||||
get protocol() {
|
||||
return protocol
|
||||
},
|
||||
get hostname() {
|
||||
return hostname
|
||||
},
|
||||
get port() {
|
||||
return port
|
||||
},
|
||||
get pathname() {
|
||||
return pathname
|
||||
},
|
||||
get search() {
|
||||
return search
|
||||
},
|
||||
get hash() {
|
||||
return hash
|
||||
},
|
||||
get origin() {
|
||||
if (protocol === "file:") return "null"
|
||||
return protocol + "//" + hostname + prefix(":", port)
|
||||
},
|
||||
get host() {
|
||||
if (protocol === "file:") return ""
|
||||
return hostname + prefix(":", port)
|
||||
},
|
||||
get href() {
|
||||
return getURL()
|
||||
},
|
||||
|
||||
set protocol(value) {
|
||||
throw new Error("Protocol is read-only")
|
||||
},
|
||||
set hostname(value) {
|
||||
unload()
|
||||
past.push({url: getURL(), isNew: true})
|
||||
future = []
|
||||
hostname = value
|
||||
},
|
||||
set port(value) {
|
||||
if (protocol === "file:") throw new Error("Port is read-only under `file://` protocol")
|
||||
unload()
|
||||
past.push({url: getURL(), isNew: true})
|
||||
future = []
|
||||
port = value
|
||||
},
|
||||
set pathname(value) {
|
||||
if (protocol === "file:") throw new Error("Pathname is read-only under `file://` protocol")
|
||||
unload()
|
||||
past.push({url: getURL(), isNew: true})
|
||||
future = []
|
||||
pathname = prefix("/", value)
|
||||
},
|
||||
set search(value) {
|
||||
unload()
|
||||
past.push({url: getURL(), isNew: true})
|
||||
future = []
|
||||
search = prefix("?", value)
|
||||
},
|
||||
set hash(value) {
|
||||
var oldHash = hash
|
||||
past.push({url: getURL(), isNew: false})
|
||||
future = []
|
||||
hash = prefix("#", value)
|
||||
if (oldHash != hash) hashchange()
|
||||
},
|
||||
$window.location = {
|
||||
get protocol() {
|
||||
return protocol
|
||||
},
|
||||
get hostname() {
|
||||
return hostname
|
||||
},
|
||||
get port() {
|
||||
return port
|
||||
},
|
||||
get pathname() {
|
||||
return pathname
|
||||
},
|
||||
get search() {
|
||||
return search
|
||||
},
|
||||
get hash() {
|
||||
return hash
|
||||
},
|
||||
get origin() {
|
||||
if (protocol === "file:") return "null"
|
||||
return protocol + "//" + hostname + prefix(":", port)
|
||||
},
|
||||
get host() {
|
||||
if (protocol === "file:") return ""
|
||||
return hostname + prefix(":", port)
|
||||
},
|
||||
get href() {
|
||||
return getURL()
|
||||
},
|
||||
|
||||
set origin(value) {
|
||||
//origin is writable but ignored
|
||||
},
|
||||
set host(value) {
|
||||
//host is writable but ignored in Chrome
|
||||
},
|
||||
set href(value) {
|
||||
var url = getURL()
|
||||
var isNew = setURL(value)
|
||||
if (isNew) {
|
||||
setURL(url)
|
||||
unload()
|
||||
setURL(value)
|
||||
}
|
||||
past.push({url: url, isNew: isNew})
|
||||
future = []
|
||||
},
|
||||
set protocol(value) {
|
||||
throw new Error("Protocol is read-only")
|
||||
},
|
||||
history: {
|
||||
pushState: function(data, title, url) {
|
||||
past.push({url: getURL(), isNew: false})
|
||||
future = []
|
||||
setURL(url)
|
||||
},
|
||||
replaceState: function(data, title, url) {
|
||||
future = []
|
||||
setURL(url)
|
||||
},
|
||||
back: function() {
|
||||
var entry = past.pop()
|
||||
if (entry != null) {
|
||||
if (entry.isNew) unload()
|
||||
future.push({url: getURL(), isNew: false})
|
||||
setURL(entry.url)
|
||||
if (!entry.isNew) popstate()
|
||||
}
|
||||
},
|
||||
forward: function() {
|
||||
var entry = future.pop()
|
||||
if (entry != null) {
|
||||
if (entry.isNew) unload()
|
||||
past.push({url: getURL(), isNew: false})
|
||||
setURL(entry.url)
|
||||
if (!entry.isNew) popstate()
|
||||
}
|
||||
},
|
||||
set hostname(value) {
|
||||
unload()
|
||||
past.push({url: getURL(), isNew: true})
|
||||
future = []
|
||||
hostname = value
|
||||
},
|
||||
set port(value) {
|
||||
if (protocol === "file:") throw new Error("Port is read-only under `file://` protocol")
|
||||
unload()
|
||||
past.push({url: getURL(), isNew: true})
|
||||
future = []
|
||||
port = value
|
||||
},
|
||||
set pathname(value) {
|
||||
if (protocol === "file:") throw new Error("Pathname is read-only under `file://` protocol")
|
||||
unload()
|
||||
past.push({url: getURL(), isNew: true})
|
||||
future = []
|
||||
pathname = prefix("/", value)
|
||||
},
|
||||
set search(value) {
|
||||
unload()
|
||||
past.push({url: getURL(), isNew: true})
|
||||
future = []
|
||||
search = prefix("?", value)
|
||||
},
|
||||
set hash(value) {
|
||||
var oldHash = hash
|
||||
past.push({url: getURL(), isNew: false})
|
||||
future = []
|
||||
hash = prefix("#", value)
|
||||
if (oldHash != hash) hashchange()
|
||||
},
|
||||
|
||||
set origin(value) {
|
||||
//origin is writable but ignored
|
||||
},
|
||||
set host(value) {
|
||||
//host is writable but ignored in Chrome
|
||||
},
|
||||
set href(value) {
|
||||
var url = getURL()
|
||||
var isNew = setURL(value)
|
||||
if (isNew) {
|
||||
setURL(url)
|
||||
unload()
|
||||
setURL(value)
|
||||
}
|
||||
past.push({url: url, isNew: isNew})
|
||||
future = []
|
||||
},
|
||||
onpopstate: null,
|
||||
onhashchange: null,
|
||||
onunload: null,
|
||||
}
|
||||
$window.history = {
|
||||
pushState: function(data, title, url) {
|
||||
past.push({url: getURL(), isNew: false})
|
||||
future = []
|
||||
setURL(url)
|
||||
},
|
||||
replaceState: function(data, title, url) {
|
||||
future = []
|
||||
setURL(url)
|
||||
},
|
||||
back: function() {
|
||||
var entry = past.pop()
|
||||
if (entry != null) {
|
||||
if (entry.isNew) unload()
|
||||
future.push({url: getURL(), isNew: false})
|
||||
setURL(entry.url)
|
||||
if (!entry.isNew) popstate()
|
||||
}
|
||||
},
|
||||
forward: function() {
|
||||
var entry = future.pop()
|
||||
if (entry != null) {
|
||||
if (entry.isNew) unload()
|
||||
past.push({url: getURL(), isNew: false})
|
||||
setURL(entry.url)
|
||||
if (!entry.isNew) popstate()
|
||||
}
|
||||
},
|
||||
}
|
||||
$window.onpopstate = null,
|
||||
$window.onhashchange = null,
|
||||
$window.onunload = null
|
||||
|
||||
return $window
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,11 +13,13 @@
|
|||
<script src="../../test-utils/pushStateMock.js"></script>
|
||||
<script src="../../test-utils/xhrMock.js"></script>
|
||||
<script src="../../test-utils/domMock.js"></script>
|
||||
<script src="../../test-utils/browserMock.js"></script>
|
||||
<script src="test-callAsync.js"></script>
|
||||
<script src="test-parseURL.js"></script>
|
||||
<script src="test-pushStateMock.js"></script>
|
||||
<script src="test-xhrMock.js"></script>
|
||||
<script src="test-domMock.js"></script>
|
||||
<script src="test-browserMock.js"></script>
|
||||
|
||||
<script>require("../../ospec/ospec").run()</script>
|
||||
</body>
|
||||
|
|
|
|||
40
test-utils/tests/test-browserMock.js
Normal file
40
test-utils/tests/test-browserMock.js
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
"use strict"
|
||||
|
||||
var o = require("../../ospec/ospec")
|
||||
var browserMock = require("../../test-utils/browserMock")
|
||||
var callAsync = require("../../test-utils/callAsync")
|
||||
o.spec("browserMock", function() {
|
||||
|
||||
var $window
|
||||
o.beforeEach(function() {
|
||||
$window = browserMock()
|
||||
})
|
||||
|
||||
o("Mocks DOM, pushState and XHR", function() {
|
||||
o($window.location).notEquals(undefined)
|
||||
o($window.document).notEquals(undefined)
|
||||
o($window.XMLHttpRequest).notEquals(undefined)
|
||||
})
|
||||
o("$window.onhashchange can be reached from the pushStateMock functions", function(done) {
|
||||
$window.onhashchange = o.spy()
|
||||
$window.location.hash = '#a'
|
||||
|
||||
callAsync(function(){
|
||||
o($window.onhashchange.callCount).equals(1)
|
||||
done()
|
||||
})
|
||||
})
|
||||
o("$window.onpopstate can be reached from the pushStateMock functions", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "#a")
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(1)
|
||||
})
|
||||
o("$window.onunload can be reached from the pushStateMock functions", function() {
|
||||
$window.onunload = o.spy()
|
||||
$window.location.href = '/a'
|
||||
|
||||
o($window.onunload.callCount).equals(1)
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue