initial commit (work in progress)
This commit is contained in:
parent
13fdb60f66
commit
559369016d
83 changed files with 10461 additions and 0 deletions
12
test-utils/README.md
Normal file
12
test-utils/README.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Test utils
|
||||
|
||||
Utilities for testing Mithril
|
||||
|
||||
Version: 1.0
|
||||
License: MIT
|
||||
|
||||
## About
|
||||
|
||||
- pushStateMock - mock for `history.pushState` and `location`
|
||||
- ajaxMock - mock for XMLHttpRequest and JSONP transporters
|
||||
- parseURL - helper function for URL parsing
|
||||
77
test-utils/ajaxMock.js
Normal file
77
test-utils/ajaxMock.js
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
"use strict"
|
||||
|
||||
var callAsync = require("../test-utils/callAsync")
|
||||
var parseURL = require("../test-utils/parseURL")
|
||||
var parseQueryString = require("../querystring/parse")
|
||||
|
||||
module.exports = function() {
|
||||
var routes = {}
|
||||
var callback = "callback"
|
||||
var serverErrorHandler = function() {
|
||||
return {status: 500, responseText: "server error"}
|
||||
}
|
||||
|
||||
var $window = {
|
||||
XMLHttpRequest: function XMLHttpRequest() {
|
||||
var args = {}
|
||||
this.setRequestHeader = function(header, value) {}
|
||||
this.open = function(method, url, async, user, password) {
|
||||
var urlData = parseURL(url, {protocol: "http:", hostname: "localhost", port: "", pathname: "/"})
|
||||
args.method = method
|
||||
args.pathname = urlData.pathname
|
||||
args.search = urlData.search
|
||||
args.async = async != null ? async : true
|
||||
args.user = user
|
||||
args.password = password
|
||||
}
|
||||
this.send = function(body) {
|
||||
var self = this
|
||||
var handler = routes[args.method + " " + args.pathname] || serverErrorHandler
|
||||
var data = handler({url: args.pathname, query: args.search || {}, body: body || null})
|
||||
self.readyState = 4
|
||||
self.status = data.status
|
||||
self.responseText = data.responseText
|
||||
if (args.async === true) {
|
||||
var s = new Date
|
||||
callAsync(function() {
|
||||
if (typeof self.onreadystatechange === "function") self.onreadystatechange()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
document: {
|
||||
createElement: function(tag) {
|
||||
return {nodeName: tag.toUpperCase(), parentNode: null}
|
||||
},
|
||||
documentElement: {
|
||||
appendChild: function(element) {
|
||||
element.parentNode = this
|
||||
if (element.nodeName === "SCRIPT") {
|
||||
var urlData = parseURL(element.src, {protocol: "http:", hostname: "localhost", port: "", pathname: "/"})
|
||||
var handler = routes["GET " + urlData.pathname] || serverErrorHandler
|
||||
var data = handler({url: urlData.pathname, query: urlData.search, body: null})
|
||||
var query = parseQueryString(urlData.search)
|
||||
callAsync(function() {
|
||||
if (data.status === 200) {
|
||||
new Function("$window", "with ($window) return " + data.responseText).call($window, $window)
|
||||
}
|
||||
else if (typeof element.onerror === "function") {
|
||||
element.onerror({type: "error"})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
removeChild: function(element) {
|
||||
element.parentNode = null
|
||||
},
|
||||
},
|
||||
},
|
||||
$defineRoutes: function(rules) {
|
||||
routes = rules
|
||||
},
|
||||
$defineJSONPCallbackKey: function(key) {
|
||||
callback = key
|
||||
},
|
||||
}
|
||||
return $window
|
||||
}
|
||||
3
test-utils/callAsync.js
Normal file
3
test-utils/callAsync.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
"use strict"
|
||||
|
||||
module.exports = typeof process === "object" ? process.nextTick : window.setImmediate || window.setTimeout
|
||||
219
test-utils/domMock.js
Normal file
219
test-utils/domMock.js
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
"use strict"
|
||||
|
||||
module.exports = function() {
|
||||
function appendChild(child) {
|
||||
var ancestor = this
|
||||
while (ancestor !== child && ancestor !== null) ancestor = ancestor.parentNode
|
||||
if (ancestor === child) throw new Error("Node cannot be inserted at the specified point in the hierarchy")
|
||||
|
||||
if (child.nodeType == null) throw new Error("Argument is not a DOM element")
|
||||
|
||||
var index = this.childNodes.indexOf(child)
|
||||
if (index > -1) this.childNodes.splice(index, 1)
|
||||
if (child.nodeType === 11) {
|
||||
while (child.firstChild != null) this.appendChild(child.firstChild)
|
||||
child.childNodes = []
|
||||
}
|
||||
else {
|
||||
this.childNodes.push(child)
|
||||
if (child.parentNode != null && child.parentNode !== this) child.parentNode.removeChild(child)
|
||||
child.parentNode = this
|
||||
}
|
||||
}
|
||||
function removeChild(child) {
|
||||
var index = this.childNodes.indexOf(child)
|
||||
if (index > -1) {
|
||||
this.childNodes.splice(index, 1)
|
||||
child.parentNode = null
|
||||
}
|
||||
else throw new TypeError("Failed to execute 'removeChild'")
|
||||
}
|
||||
function insertBefore(child, reference) {
|
||||
var ancestor = this
|
||||
while (ancestor !== child && ancestor !== null) ancestor = ancestor.parentNode
|
||||
if (ancestor === child) throw new Error("Node cannot be inserted at the specified point in the hierarchy")
|
||||
|
||||
if (child.nodeType == null) throw new Error("Argument is not a DOM element")
|
||||
|
||||
var refIndex = this.childNodes.indexOf(reference)
|
||||
var index = this.childNodes.indexOf(child)
|
||||
if (reference !== null && refIndex < 0) throw new TypeError("Invalid argument")
|
||||
if (index > -1) this.childNodes.splice(index, 1)
|
||||
if (reference === null) this.appendChild(child)
|
||||
else {
|
||||
if (child.nodeType === 11) {
|
||||
this.childNodes.splice.apply(this.childNodes, [refIndex, 0].concat(child.childNodes))
|
||||
while (child.firstChild) {
|
||||
var subchild = child.firstChild
|
||||
child.removeChild(subchild)
|
||||
subchild.parentNode = this
|
||||
}
|
||||
child.childNodes = []
|
||||
}
|
||||
else {
|
||||
this.childNodes.splice(refIndex, 0, child)
|
||||
if (child.parentNode != null && child.parentNode !== this) child.parentNode.removeChild(child)
|
||||
child.parentNode = this
|
||||
}
|
||||
}
|
||||
}
|
||||
function setAttribute(name, value) {
|
||||
var nodeValue = String(value)
|
||||
this.attributes[name] = {
|
||||
namespaceURI: null,
|
||||
get nodeValue() {return nodeValue},
|
||||
set nodeValue(value) {nodeValue = String(value)},
|
||||
}
|
||||
}
|
||||
function setAttributeNS(ns, name, value) {
|
||||
this.setAttribute(name, value)
|
||||
this.attributes[name].namespaceURI = ns
|
||||
}
|
||||
function removeAttribute(name) {
|
||||
delete this.attributes[name]
|
||||
}
|
||||
var activeElement
|
||||
var $window = {
|
||||
document: {
|
||||
createElement: function(tag, is) {
|
||||
var style = {}
|
||||
var element = {
|
||||
nodeType: 1,
|
||||
nodeName: tag.toUpperCase(),
|
||||
namespaceURI: "http://www.w3.org/1999/xhtml",
|
||||
appendChild: appendChild,
|
||||
removeChild: removeChild,
|
||||
insertBefore: insertBefore,
|
||||
setAttribute: setAttribute,
|
||||
setAttributeNS: setAttributeNS,
|
||||
removeAttribute: removeAttribute,
|
||||
parentNode: null,
|
||||
childNodes: [],
|
||||
attributes: {},
|
||||
get firstChild() {
|
||||
return this.childNodes[0] || null
|
||||
},
|
||||
get nextSibling() {
|
||||
if (this.parentNode == null) return null
|
||||
var index = this.parentNode.childNodes.indexOf(this)
|
||||
if (index < 0) throw new TypeError("Parent's childNodes is out of sync")
|
||||
return this.parentNode.childNodes[index + 1] || null
|
||||
},
|
||||
set textContent(value) {
|
||||
this.childNodes = []
|
||||
if (value !== "") this.appendChild($window.document.createTextNode(value))
|
||||
},
|
||||
set innerHTML(value) {
|
||||
while (this.firstChild) this.removeChild(this.firstChild)
|
||||
|
||||
var stack = [this], depth = 0, voidElements = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"]
|
||||
value.replace(/<([a-z0-9\-]+?)((?:\s+?[^=]+?=(?:"[^"]*?"|'[^']*?'|[^\s>]*))*?)(\s*\/)?>|<\/([a-z0-9\-]+?)>|([^<]+)/g, function(match, startTag, attrs, selfClosed, endTag, text) {
|
||||
if (startTag) {
|
||||
var element = $window.document.createElement(startTag)
|
||||
attrs.replace(/\s+?([^=]+?)=(?:"([^"]*?)"|'([^']*?)'|([^\s>]*))/g, function(match, key, doubleQuoted, singleQuoted, unquoted) {
|
||||
var keyParts = key.split(":")
|
||||
var name = keyParts.pop()
|
||||
var ns = keyParts[0]
|
||||
var value = doubleQuoted || singleQuoted || unquoted || ""
|
||||
if (ns != null) element.setAttributeNS(ns, name, value)
|
||||
else element.setAttribute(name, value)
|
||||
})
|
||||
stack[depth].appendChild(element)
|
||||
if (!selfClosed && voidElements.indexOf(startTag.toLowerCase()) < 0) stack[++depth] = element
|
||||
}
|
||||
else if (endTag) {
|
||||
depth--
|
||||
}
|
||||
else if (text) {
|
||||
stack[depth].appendChild($window.document.createTextNode(text)) // FIXME handle html entities
|
||||
}
|
||||
})
|
||||
},
|
||||
get style() {
|
||||
return style
|
||||
},
|
||||
set style(value) {
|
||||
if (typeof value === "string") {
|
||||
for (var key in style) style[key] = ""
|
||||
var rules = value.split(";")
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
var rule = rules[i]
|
||||
var colonIndex = rule.indexOf(":")
|
||||
if (colonIndex > -1) {
|
||||
var key = rule.slice(0, colonIndex).trim().replace(/-\D/g, function(match) {return match[1].toUpperCase()})
|
||||
var value = rule.slice(colonIndex + 1).trim()
|
||||
style[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
focus: function() {activeElement = this},
|
||||
dispatchEvent: function(e) {
|
||||
e.target = this
|
||||
if (typeof this["on" + e.type] === "function") this["on" + e.type](e)
|
||||
},
|
||||
}
|
||||
if (element.nodeName === "A") {
|
||||
var href
|
||||
Object.defineProperty(element, "href", {
|
||||
get: function() {return this.attributes["href"] === undefined ? "" : "[FIXME implement]"},
|
||||
set: function(value) {this.setAttribute("href", value)},
|
||||
enumerable: true,
|
||||
})
|
||||
}
|
||||
if (element.nodeName === "INPUT") {
|
||||
var checked
|
||||
Object.defineProperty(element, "checked", {
|
||||
get: function() {return checked === undefined ? this.attributes["checked"] !== undefined : checked},
|
||||
set: function(value) {checked = Boolean(value)},
|
||||
enumerable: true,
|
||||
})
|
||||
}
|
||||
return element
|
||||
},
|
||||
createElementNS: function(ns, tag, is) {
|
||||
var element = this.createElement(tag, is)
|
||||
element.nodeName = tag
|
||||
element.namespaceURI = ns
|
||||
return element
|
||||
},
|
||||
createTextNode: function(text) {
|
||||
var nodeValue = String(text)
|
||||
return {
|
||||
nodeType: 3,
|
||||
nodeName: "#text",
|
||||
parentNode: null,
|
||||
get nodeValue() {return nodeValue},
|
||||
set nodeValue(value) {nodeValue = String(value)},
|
||||
}
|
||||
},
|
||||
createDocumentFragment: function() {
|
||||
return {
|
||||
nodeType: 11,
|
||||
nodeName: "#document-fragment",
|
||||
appendChild: appendChild,
|
||||
insertBefore: insertBefore,
|
||||
removeChild: removeChild,
|
||||
parentNode: null,
|
||||
childNodes: [],
|
||||
get firstChild() {
|
||||
return this.childNodes[0] || null
|
||||
},
|
||||
}
|
||||
},
|
||||
createEvent: function() {
|
||||
return {
|
||||
initEvent: function(type) {this.type = type},
|
||||
}
|
||||
},
|
||||
get activeElement() {return activeElement},
|
||||
},
|
||||
}
|
||||
$window.document.documentElement = $window.document.createElement("html")
|
||||
$window.document.documentElement.appendChild($window.document.createElement("head"))
|
||||
$window.document.body = $window.document.createElement("body")
|
||||
$window.document.documentElement.appendChild($window.document.body)
|
||||
activeElement = $window.document.body
|
||||
|
||||
return $window
|
||||
}
|
||||
47
test-utils/parseURL.js
Normal file
47
test-utils/parseURL.js
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
"use strict"
|
||||
|
||||
module.exports = function parseURL(url, root) {
|
||||
var data = {}
|
||||
var protocolIndex = url.indexOf("://")
|
||||
var pathnameIndex = protocolIndex > - 1 ? url.indexOf("/", protocolIndex + 3) : url.indexOf("/")
|
||||
var searchIndex = url.indexOf("?")
|
||||
var hashIndex = url.indexOf("#")
|
||||
if ((pathnameIndex > searchIndex && searchIndex > -1) || (pathnameIndex > hashIndex && hashIndex > -1)) pathnameIndex = -1
|
||||
if (searchIndex > hashIndex && hashIndex > -1) searchIndex = -1
|
||||
var pathnameEnd = searchIndex > -1 ? searchIndex : hashIndex > -1 ? hashIndex : url.length
|
||||
if (protocolIndex > -1) {
|
||||
//it's a full URL
|
||||
if (pathnameIndex < 0) pathnameIndex = url.length
|
||||
var portIndex = url.indexOf(":", protocolIndex + 1)
|
||||
if (portIndex < 0) portIndex = pathnameIndex
|
||||
data.protocol = url.slice(0, protocolIndex + 1)
|
||||
data.hostname = url.slice(protocolIndex + 3, portIndex)
|
||||
data.port = url.slice(portIndex + 1, pathnameIndex)
|
||||
data.pathname = url.slice(pathnameIndex, pathnameEnd) || "/"
|
||||
}
|
||||
else {
|
||||
data.protocol = root.protocol
|
||||
data.hostname = root.hostname
|
||||
data.port = root.port
|
||||
if (pathnameIndex === 0) {
|
||||
//it's an absolute path
|
||||
data.pathname = url.slice(pathnameIndex, pathnameEnd) || "/"
|
||||
}
|
||||
else if (searchIndex !== 0 && hashIndex !== 0) {
|
||||
//it's a relative path
|
||||
var slashIndex = root.pathname.lastIndexOf("/")
|
||||
var path = slashIndex > -1 ? root.pathname.slice(0, slashIndex + 1) : "./"
|
||||
var normalized = url.slice(0, pathnameEnd).replace(/^\.$/, root.pathname.slice(slashIndex + 1)).replace(/^\.\//, "")
|
||||
var dotdot = /\/[^\/]+?\/\.{2}/g
|
||||
var pathname = path + normalized
|
||||
pathname = path + normalized
|
||||
while (dotdot.test(pathname)) pathname = pathname.replace(dotdot, "")
|
||||
pathname = pathname.replace(/\/\.\//g, "/").replace(/^(\/\.{2})+/, "") || "/"
|
||||
data.pathname = pathname
|
||||
}
|
||||
}
|
||||
var searchEnd = hashIndex > -1 ? hashIndex : url.length
|
||||
data.search = searchIndex > -1 ? url.slice(searchIndex, searchEnd) : ""
|
||||
data.hash = hashIndex > -1 ? url.slice(hashIndex) : ""
|
||||
return data
|
||||
}
|
||||
169
test-utils/pushStateMock.js
Normal file
169
test-utils/pushStateMock.js
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
"use strict"
|
||||
|
||||
var parseURL = require("../test-utils/parseURL")
|
||||
|
||||
module.exports = function() {
|
||||
var protocol = "http:"
|
||||
var hostname = "localhost"
|
||||
var port = ""
|
||||
var pathname = "/"
|
||||
var search = ""
|
||||
var hash = ""
|
||||
|
||||
var past = [], future = []
|
||||
|
||||
function getURL() {
|
||||
if (protocol === "file:") return protocol + "//" + pathname + search + hash
|
||||
return protocol + "//" + hostname + prefix(":", port) + pathname + search + hash
|
||||
}
|
||||
function setURL(value) {
|
||||
var data = parseURL(value, {protocol: protocol, hostname: hostname, port: port, pathname: pathname})
|
||||
var isNew = false
|
||||
if (data.protocol != null && data.protocol !== protocol) protocol = data.protocol, isNew = true
|
||||
if (data.hostname != null && data.hostname !== hostname) hostname = data.hostname, isNew = true
|
||||
if (data.port != null && data.port !== port) port = data.port, isNew = true
|
||||
if (data.pathname != null && data.pathname !== pathname) pathname = data.pathname, isNew = true
|
||||
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()
|
||||
}
|
||||
return isNew
|
||||
}
|
||||
|
||||
function prefix(prefix, value) {
|
||||
if (value === "") return ""
|
||||
return (value.charAt(0) !== prefix ? prefix : "") + value
|
||||
}
|
||||
function hashchange() {
|
||||
if (typeof $window.onhashchange === "function") $window.onhashchange({type: "hashchange"})
|
||||
}
|
||||
function popstate() {
|
||||
if (typeof $window.onpopstate === "function") $window.onpopstate({type: "popstate"})
|
||||
}
|
||||
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()
|
||||
},
|
||||
|
||||
set origin(value) {
|
||||
console.warn("Origin is writable but ignored")
|
||||
},
|
||||
set host(value) {
|
||||
console.warn("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 = []
|
||||
},
|
||||
},
|
||||
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()
|
||||
}
|
||||
},
|
||||
},
|
||||
scrollTo: function(x, y) {},
|
||||
onpopstate: null,
|
||||
onhashchange: null,
|
||||
onunload: null,
|
||||
}
|
||||
return $window
|
||||
}
|
||||
23
test-utils/tests/index.html
Normal file
23
test-utils/tests/index.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script src="../../module/module.js"></script>
|
||||
<script src="../../ospec/ospec.js"></script>
|
||||
<script src="../../querystring/parse.js"></script>
|
||||
|
||||
<script src="../../test-utils/callAsync.js"></script>
|
||||
<script src="../../test-utils/parseURL.js"></script>
|
||||
<script src="../../test-utils/pushStateMock.js"></script>
|
||||
<script src="../../test-utils/ajaxMock.js"></script>
|
||||
<script src="../../test-utils/domMock.js"></script>
|
||||
<script src="test-parseURL.js"></script>
|
||||
<script src="test-pushStateMock.js"></script>
|
||||
<script src="test-ajaxMock.js"></script>
|
||||
<script src="test-domMock.js"></script>
|
||||
|
||||
<script>require("../../ospec/ospec").run()</script>
|
||||
</body>
|
||||
</html>
|
||||
147
test-utils/tests/test-ajaxMock.js
Normal file
147
test-utils/tests/test-ajaxMock.js
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
"use strict"
|
||||
|
||||
var o = require("../../ospec/ospec")
|
||||
var ajaxMock = require("../../test-utils/ajaxMock")
|
||||
var parseQueryString = require("../../querystring/parse")
|
||||
|
||||
o.spec("ajaxMock", function() {
|
||||
var $window, ajax
|
||||
o.beforeEach(function() {
|
||||
$window = ajaxMock()
|
||||
})
|
||||
|
||||
o.spec("xhr", function() {
|
||||
o("works", function(done, timeout) {
|
||||
$window.$defineRoutes({
|
||||
"GET /item": function(request) {
|
||||
o(request.url).equals("/item")
|
||||
return {status: 200, responseText: "test"}
|
||||
}
|
||||
})
|
||||
var xhr = new $window.XMLHttpRequest()
|
||||
xhr.open("GET", "/item")
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4) {
|
||||
o(xhr.status).equals(200)
|
||||
o(xhr.responseText).equals("test")
|
||||
done()
|
||||
}
|
||||
}
|
||||
xhr.send()
|
||||
})
|
||||
o("works w/ search", function(done, timeout) {
|
||||
$window.$defineRoutes({
|
||||
"GET /item": function(request) {
|
||||
o(request.query).equals("?a=b")
|
||||
return {status: 200, responseText: "test"}
|
||||
}
|
||||
})
|
||||
var xhr = new $window.XMLHttpRequest()
|
||||
xhr.open("GET", "/item?a=b")
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4) {
|
||||
done()
|
||||
}
|
||||
}
|
||||
xhr.send()
|
||||
})
|
||||
o("works w/ body", function(done, timeout) {
|
||||
$window.$defineRoutes({
|
||||
"POST /item": function(request) {
|
||||
o(request.body).equals("a=b")
|
||||
return {status: 200, responseText: "test"}
|
||||
}
|
||||
})
|
||||
var xhr = new $window.XMLHttpRequest()
|
||||
xhr.open("POST", "/item")
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4) {
|
||||
done()
|
||||
}
|
||||
}
|
||||
xhr.send("a=b")
|
||||
})
|
||||
o("handles routing error", function(done, timeout) {
|
||||
var xhr = new $window.XMLHttpRequest()
|
||||
xhr.open("GET", "/nonexistent")
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4) {
|
||||
o(xhr.status).equals(500)
|
||||
done()
|
||||
}
|
||||
}
|
||||
xhr.send("a=b")
|
||||
})
|
||||
})
|
||||
o.spec("jsonp", function() {
|
||||
o("works", function(done) {
|
||||
$window.$defineRoutes({
|
||||
"GET /test": function(request) {
|
||||
var queryData = parseQueryString(request.query)
|
||||
return {status: 200, responseText: queryData["callback"] + "(" + JSON.stringify({a: 1}) + ")"}
|
||||
}
|
||||
})
|
||||
|
||||
$window["cb"] = finish
|
||||
|
||||
var script = $window.document.createElement("script")
|
||||
script.src = "/test?callback=cb"
|
||||
$window.document.documentElement.appendChild(script)
|
||||
|
||||
function finish(data) {
|
||||
o(data).deepEquals({a: 1})
|
||||
done()
|
||||
}
|
||||
})
|
||||
o("works w/ custom callback key", function(done) {
|
||||
$window.$defineRoutes({
|
||||
"GET /test": function(request) {
|
||||
var queryData = parseQueryString(request.query)
|
||||
return {status: 200, responseText: queryData["cb"] + "(" + JSON.stringify({a: 2}) + ")"}
|
||||
}
|
||||
})
|
||||
$window.$defineJSONPCallbackKey("cb")
|
||||
|
||||
$window["customcb"] = finish2
|
||||
|
||||
var script = $window.document.createElement("script")
|
||||
script.src = "/test?cb=customcb"
|
||||
$window.document.documentElement.appendChild(script)
|
||||
|
||||
function finish2(data) {
|
||||
o(data).deepEquals({a: 2})
|
||||
done()
|
||||
}
|
||||
})
|
||||
o("works with other querystring params", function(done, timeout) {
|
||||
$window.$defineRoutes({
|
||||
"GET /test": function(request) {
|
||||
var queryData = parseQueryString(request.query)
|
||||
return {status: 200, responseText: queryData["callback"] + "(" + JSON.stringify({a: 3}) + ")"}
|
||||
}
|
||||
})
|
||||
|
||||
$window["cbwithinparams"] = finish
|
||||
|
||||
var script = $window.document.createElement("script")
|
||||
script.src = "/test?a=b&callback=cbwithinparams&c=d"
|
||||
$window.document.documentElement.appendChild(script)
|
||||
|
||||
function finish(data) {
|
||||
o(data).deepEquals({a: 3})
|
||||
done()
|
||||
}
|
||||
})
|
||||
o("handles error", function(done) {
|
||||
var script = $window.document.createElement("script")
|
||||
script.onerror = finish
|
||||
script.src = "/test?cb=nonexistent"
|
||||
$window.document.documentElement.appendChild(script)
|
||||
|
||||
function finish(e) {
|
||||
o(e.type).equals("error")
|
||||
done()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
580
test-utils/tests/test-domMock.js
Normal file
580
test-utils/tests/test-domMock.js
Normal file
|
|
@ -0,0 +1,580 @@
|
|||
"use strict"
|
||||
|
||||
var o = require("../../ospec/ospec")
|
||||
var domMock = require("../../test-utils/domMock")
|
||||
|
||||
o.spec("domMock", function() {
|
||||
var $document
|
||||
o.beforeEach(function() {
|
||||
$document = domMock().document
|
||||
//$document = document //TODO clean up
|
||||
})
|
||||
|
||||
o.spec("createElement", function() {
|
||||
o("works", function() {
|
||||
var node = $document.createElement("div")
|
||||
|
||||
o(node.nodeType).equals(1)
|
||||
o(node.nodeName).equals("DIV")
|
||||
o(node.namespaceURI).equals("http://www.w3.org/1999/xhtml")
|
||||
o(node.parentNode).equals(null)
|
||||
o(node.childNodes.length).equals(0)
|
||||
o(node.firstChild).equals(null)
|
||||
o(node.nextSibling).equals(null)
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("createElementNS", function() {
|
||||
o("works", function() {
|
||||
var node = $document.createElementNS("http://www.w3.org/2000/svg", "svg")
|
||||
|
||||
o(node.nodeType).equals(1)
|
||||
o(node.nodeName).equals("svg")
|
||||
o(node.namespaceURI).equals("http://www.w3.org/2000/svg")
|
||||
o(node.parentNode).equals(null)
|
||||
o(node.childNodes.length).equals(0)
|
||||
o(node.firstChild).equals(null)
|
||||
o(node.nextSibling).equals(null)
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("createTextNode", function() {
|
||||
o("works", function() {
|
||||
var node = $document.createTextNode("abc")
|
||||
|
||||
o(node.nodeType).equals(3)
|
||||
o(node.nodeName).equals("#text")
|
||||
o(node.parentNode).equals(null)
|
||||
o(node.nodeValue).equals("abc")
|
||||
})
|
||||
o("works w/ number", function() {
|
||||
var node = $document.createTextNode(123)
|
||||
|
||||
o(node.nodeValue).equals("123")
|
||||
})
|
||||
o("works w/ null", function() {
|
||||
var node = $document.createTextNode(null)
|
||||
|
||||
o(node.nodeValue).equals("null")
|
||||
})
|
||||
o("works w/ undefined", function() {
|
||||
var node = $document.createTextNode(undefined)
|
||||
|
||||
o(node.nodeValue).equals("undefined")
|
||||
})
|
||||
o("works w/ object", function() {
|
||||
var node = $document.createTextNode({})
|
||||
|
||||
o(node.nodeValue).equals("[object Object]")
|
||||
})
|
||||
o("does not unescape HTML", function() {
|
||||
var node = $document.createTextNode("<a>&</a>")
|
||||
|
||||
o(node.nodeValue).equals("<a>&</a>")
|
||||
})
|
||||
o("nodeValue casts to string", function() {
|
||||
var node = $document.createTextNode("a")
|
||||
node.nodeValue = true
|
||||
|
||||
o(node.nodeValue).equals("true")
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("createDocumentFragment", function() {
|
||||
o("works", function() {
|
||||
var node = $document.createDocumentFragment()
|
||||
|
||||
o(node.nodeType).equals(11)
|
||||
o(node.nodeName).equals("#document-fragment")
|
||||
o(node.parentNode).equals(null)
|
||||
o(node.childNodes.length).equals(0)
|
||||
o(node.firstChild).equals(null)
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("appendChild", function() {
|
||||
o("works", function() {
|
||||
var parent = $document.createElement("div")
|
||||
var child = $document.createElement("a")
|
||||
parent.appendChild(child)
|
||||
|
||||
o(parent.childNodes.length).equals(1)
|
||||
o(parent.childNodes[0]).equals(child)
|
||||
o(parent.firstChild).equals(child)
|
||||
o(child.parentNode).equals(parent)
|
||||
})
|
||||
o("moves existing", function() {
|
||||
var parent = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
var b = $document.createElement("b")
|
||||
parent.appendChild(a)
|
||||
parent.appendChild(b)
|
||||
parent.appendChild(a)
|
||||
|
||||
o(parent.childNodes.length).equals(2)
|
||||
o(parent.childNodes[0]).equals(b)
|
||||
o(parent.childNodes[1]).equals(a)
|
||||
o(parent.firstChild).equals(b)
|
||||
o(parent.firstChild.nextSibling).equals(a)
|
||||
o(a.parentNode).equals(parent)
|
||||
o(b.parentNode).equals(parent)
|
||||
})
|
||||
o("removes from old parent", function() {
|
||||
var parent = $document.createElement("div")
|
||||
var source = $document.createElement("span")
|
||||
var a = $document.createElement("a")
|
||||
var b = $document.createElement("b")
|
||||
parent.appendChild(a)
|
||||
source.appendChild(b)
|
||||
parent.appendChild(b)
|
||||
|
||||
o(source.childNodes.length).equals(0)
|
||||
})
|
||||
o("transfers from fragment", function() {
|
||||
var parent = $document.createElement("div")
|
||||
var a = $document.createDocumentFragment("a")
|
||||
var b = $document.createElement("b")
|
||||
var c = $document.createElement("c")
|
||||
a.appendChild(b)
|
||||
a.appendChild(c)
|
||||
parent.appendChild(a)
|
||||
|
||||
o(parent.childNodes.length).equals(2)
|
||||
o(parent.childNodes[0]).equals(b)
|
||||
o(parent.childNodes[1]).equals(c)
|
||||
o(parent.firstChild).equals(b)
|
||||
o(parent.firstChild.nextSibling).equals(c)
|
||||
o(a.childNodes.length).equals(0)
|
||||
o(a.firstChild).equals(null)
|
||||
o(a.parentNode).equals(null)
|
||||
o(b.parentNode).equals(parent)
|
||||
o(c.parentNode).equals(parent)
|
||||
})
|
||||
o("throws if appended to self", function(done) {
|
||||
var div = $document.createElement("div")
|
||||
try {div.appendChild(div)}
|
||||
catch (e) {done()}
|
||||
})
|
||||
o("throws if appended to child", function(done) {
|
||||
var parent = $document.createElement("div")
|
||||
var child = $document.createElement("a")
|
||||
parent.appendChild(child)
|
||||
try {child.appendChild(parent)}
|
||||
catch (e) {done()}
|
||||
})
|
||||
o("throws if child is not element", function(done) {
|
||||
var parent = $document.createElement("div")
|
||||
var child = 1
|
||||
try {parent.appendChild(child)}
|
||||
catch (e) {done()}
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("removeChild", function() {
|
||||
o("works", function() {
|
||||
var parent = $document.createElement("div")
|
||||
var child = $document.createElement("a")
|
||||
parent.appendChild(child)
|
||||
parent.removeChild(child)
|
||||
|
||||
o(parent.childNodes.length).equals(0)
|
||||
o(parent.firstChild).equals(null)
|
||||
o(child.parentNode).equals(null)
|
||||
})
|
||||
o("throws if not a child", function(done) {
|
||||
var parent = $document.createElement("div")
|
||||
var child = $document.createElement("a")
|
||||
try {parent.removeChild(child)}
|
||||
catch (e) {done()}
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("insertBefore", function() {
|
||||
o("works", function() {
|
||||
var parent = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
var b = $document.createElement("b")
|
||||
parent.appendChild(a)
|
||||
parent.insertBefore(b, a)
|
||||
|
||||
o(parent.childNodes.length).equals(2)
|
||||
o(parent.childNodes[0]).equals(b)
|
||||
o(parent.childNodes[1]).equals(a)
|
||||
o(parent.firstChild).equals(b)
|
||||
o(parent.firstChild.nextSibling).equals(a)
|
||||
o(a.parentNode).equals(parent)
|
||||
o(b.parentNode).equals(parent)
|
||||
})
|
||||
o("moves existing", function() {
|
||||
var parent = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
var b = $document.createElement("b")
|
||||
parent.appendChild(a)
|
||||
parent.appendChild(b)
|
||||
parent.insertBefore(b, a)
|
||||
|
||||
o(parent.childNodes.length).equals(2)
|
||||
o(parent.childNodes[0]).equals(b)
|
||||
o(parent.childNodes[1]).equals(a)
|
||||
o(parent.firstChild).equals(b)
|
||||
o(parent.firstChild.nextSibling).equals(a)
|
||||
o(a.parentNode).equals(parent)
|
||||
o(b.parentNode).equals(parent)
|
||||
})
|
||||
o("removes from old parent", function() {
|
||||
var parent = $document.createElement("div")
|
||||
var source = $document.createElement("span")
|
||||
var a = $document.createElement("a")
|
||||
var b = $document.createElement("b")
|
||||
parent.appendChild(a)
|
||||
source.appendChild(b)
|
||||
parent.insertBefore(b, a)
|
||||
|
||||
o(source.childNodes.length).equals(0)
|
||||
})
|
||||
o("transfers from fragment", function() {
|
||||
var parent = $document.createElement("div")
|
||||
var ref = $document.createElement("span")
|
||||
var a = $document.createDocumentFragment("a")
|
||||
var b = $document.createElement("b")
|
||||
var c = $document.createElement("c")
|
||||
parent.appendChild(ref)
|
||||
a.appendChild(b)
|
||||
a.appendChild(c)
|
||||
parent.insertBefore(a, ref)
|
||||
|
||||
o(parent.childNodes.length).equals(3)
|
||||
o(parent.childNodes[0]).equals(b)
|
||||
o(parent.childNodes[1]).equals(c)
|
||||
o(parent.childNodes[2]).equals(ref)
|
||||
o(parent.firstChild).equals(b)
|
||||
o(parent.firstChild.nextSibling).equals(c)
|
||||
o(parent.firstChild.nextSibling.nextSibling).equals(ref)
|
||||
o(a.childNodes.length).equals(0)
|
||||
o(a.firstChild).equals(null)
|
||||
o(a.parentNode).equals(null)
|
||||
o(b.parentNode).equals(parent)
|
||||
o(c.parentNode).equals(parent)
|
||||
})
|
||||
o("appends if second arg is null", function() {
|
||||
var parent = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
var b = $document.createElement("b")
|
||||
parent.appendChild(a)
|
||||
parent.insertBefore(b, null)
|
||||
|
||||
o(parent.childNodes.length).equals(2)
|
||||
o(parent.childNodes[0]).equals(a)
|
||||
o(parent.childNodes[1]).equals(b)
|
||||
o(parent.firstChild).equals(a)
|
||||
o(parent.firstChild.nextSibling).equals(b)
|
||||
o(a.parentNode).equals(parent)
|
||||
})
|
||||
o("throws if appended to self", function(done) {
|
||||
var div = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
div.appendChild(a)
|
||||
try {div.isnertBefore(div, a)}
|
||||
catch (e) {done()}
|
||||
})
|
||||
o("throws if appended to child", function(done) {
|
||||
var parent = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
var b = $document.createElement("b")
|
||||
parent.appendChild(a)
|
||||
a.appendChild(b)
|
||||
try {a.insertBefore(parent, b)}
|
||||
catch (e) {done()}
|
||||
})
|
||||
o("throws if child is not element", function(done) {
|
||||
var parent = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
parent.appendChild(a)
|
||||
try {parent.insertBefore(1, a)}
|
||||
catch (e) {done()}
|
||||
})
|
||||
o("throws if inserted before itself", function(done) {
|
||||
var parent = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
try {parent.insertBefore(a, a)}
|
||||
catch (e) {done()}
|
||||
})
|
||||
o("throws if second arg is undefined", function(done) {
|
||||
var parent = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
try {parent.insertBefore(a)}
|
||||
catch (e) {done()}
|
||||
})
|
||||
o("throws if reference is not child", function(done) {
|
||||
var parent = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
var b = $document.createElement("b")
|
||||
try {parent.insertBefore(a, b)}
|
||||
catch (e) {done()}
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("setAttribute", function() {
|
||||
o("works", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.setAttribute("id", "aaa")
|
||||
|
||||
o(div.attributes["id"].nodeValue).equals("aaa")
|
||||
o(div.attributes["id"].namespaceURI).equals(null)
|
||||
})
|
||||
o("works w/ number", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.setAttribute("id", 123)
|
||||
|
||||
o(div.attributes["id"].nodeValue).equals("123")
|
||||
})
|
||||
o("works w/ null", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.setAttribute("id", null)
|
||||
|
||||
o(div.attributes["id"].nodeValue).equals("null")
|
||||
})
|
||||
o("works w/ undefined", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.setAttribute("id", undefined)
|
||||
|
||||
o(div.attributes["id"].nodeValue).equals("undefined")
|
||||
})
|
||||
o("works w/ object", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.setAttribute("id", {})
|
||||
|
||||
o(div.attributes["id"].nodeValue).equals("[object Object]")
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("setAttributeNS", function() {
|
||||
o("works", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.setAttributeNS("http://www.w3.org/1999/xlink", "href", "aaa")
|
||||
|
||||
o(div.attributes["href"].nodeValue).equals("aaa")
|
||||
o(div.attributes["href"].namespaceURI).equals("http://www.w3.org/1999/xlink")
|
||||
})
|
||||
o("works w/ number", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.setAttributeNS("http://www.w3.org/1999/xlink", "href", 123)
|
||||
|
||||
o(div.attributes["href"].nodeValue).equals("123")
|
||||
o(div.attributes["href"].namespaceURI).equals("http://www.w3.org/1999/xlink")
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("removeAttribute", function() {
|
||||
o("works", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.setAttribute("id", "aaa")
|
||||
div.removeAttribute("id")
|
||||
|
||||
o("id" in div.attributes).equals(false)
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("textContent", function() {
|
||||
o("works", function() {
|
||||
var div = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
div.textContent = "aaa"
|
||||
|
||||
o(div.childNodes.length).equals(1)
|
||||
o(div.firstChild.nodeType).equals(3)
|
||||
o(div.firstChild.nodeValue).equals("aaa")
|
||||
})
|
||||
o("works with empty string", function() {
|
||||
var div = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
div.textContent = ""
|
||||
|
||||
o(div.childNodes.length).equals(0)
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("innerHTML", function() {
|
||||
o("works", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.innerHTML = "<br /><a class='aaa' id='xyz'>123<b class=\"bbb\"></b>234<br class=ccc>345</a>"
|
||||
o(div.childNodes.length).equals(2)
|
||||
o(div.childNodes[0].nodeType).equals(1)
|
||||
o(div.childNodes[0].nodeName).equals("BR")
|
||||
o(div.childNodes[1].nodeType).equals(1)
|
||||
o(div.childNodes[1].nodeName).equals("A")
|
||||
o(div.childNodes[1].attributes["class"].nodeValue).equals("aaa")
|
||||
o(div.childNodes[1].attributes["id"].nodeValue).equals("xyz")
|
||||
o(div.childNodes[1].childNodes[0].nodeType).equals(3)
|
||||
o(div.childNodes[1].childNodes[0].nodeValue).equals("123")
|
||||
o(div.childNodes[1].childNodes[1].nodeType).equals(1)
|
||||
o(div.childNodes[1].childNodes[1].nodeName).equals("B")
|
||||
o(div.childNodes[1].childNodes[1].attributes["class"].nodeValue).equals("bbb")
|
||||
o(div.childNodes[1].childNodes[2].nodeType).equals(3)
|
||||
o(div.childNodes[1].childNodes[2].nodeValue).equals("234")
|
||||
o(div.childNodes[1].childNodes[3].nodeType).equals(1)
|
||||
o(div.childNodes[1].childNodes[3].nodeName).equals("BR")
|
||||
o(div.childNodes[1].childNodes[3].attributes["class"].nodeValue).equals("ccc")
|
||||
o(div.childNodes[1].childNodes[4].nodeType).equals(3)
|
||||
o(div.childNodes[1].childNodes[4].nodeValue).equals("345")
|
||||
})
|
||||
o("headers work", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.innerHTML = "<h1></h1><h2></h2><h3></h3><h4></h4><h5></h5><h6></h6>"
|
||||
o(div.childNodes.length).equals(6)
|
||||
o(div.childNodes[0].nodeType).equals(1)
|
||||
o(div.childNodes[0].nodeName).equals("H1")
|
||||
o(div.childNodes[1].nodeType).equals(1)
|
||||
o(div.childNodes[1].nodeName).equals("H2")
|
||||
o(div.childNodes[2].nodeType).equals(1)
|
||||
o(div.childNodes[2].nodeName).equals("H3")
|
||||
o(div.childNodes[3].nodeType).equals(1)
|
||||
o(div.childNodes[3].nodeName).equals("H4")
|
||||
o(div.childNodes[4].nodeType).equals(1)
|
||||
o(div.childNodes[4].nodeName).equals("H5")
|
||||
o(div.childNodes[5].nodeType).equals(1)
|
||||
o(div.childNodes[5].nodeName).equals("H6")
|
||||
})
|
||||
o("detaches old elements", function() {
|
||||
var div = $document.createElement("div")
|
||||
var a = $document.createElement("a")
|
||||
div.appendChild(a)
|
||||
div.innerHTML = "<b></b>"
|
||||
|
||||
o(a.parentNode).equals(null)
|
||||
})
|
||||
})
|
||||
o.spec("focus", function() {
|
||||
o("body is active by default", function() {
|
||||
o($document.documentElement.nodeName).equals("HTML")
|
||||
o($document.body.nodeName).equals("BODY")
|
||||
o($document.documentElement.firstChild.nodeName).equals("HEAD")
|
||||
o($document.documentElement).equals($document.body.parentNode)
|
||||
o($document.activeElement).equals($document.body)
|
||||
})
|
||||
o("focus changes activeElement", function() {
|
||||
var input = $document.createElement("input")
|
||||
$document.body.appendChild(input)
|
||||
input.focus()
|
||||
|
||||
o($document.activeElement).equals(input)
|
||||
|
||||
$document.body.removeChild(input)
|
||||
})
|
||||
})
|
||||
o.spec("style", function() {
|
||||
o("has style property", function() {
|
||||
var div = $document.createElement("div")
|
||||
|
||||
o(typeof div.style).equals("object")
|
||||
})
|
||||
o("setting style string works", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.style = "background-color: red; border-bottom: 1px solid red;"
|
||||
|
||||
o(div.style.backgroundColor).equals("red")
|
||||
o(div.style.borderBottom).equals("1px solid red")
|
||||
})
|
||||
o("removing via setting style string works", function() {
|
||||
var div = $document.createElement("div")
|
||||
div.style = "background: red;"
|
||||
div.style = ""
|
||||
|
||||
o(div.style.background).equals("")
|
||||
})
|
||||
})
|
||||
o.spec("events", function() {
|
||||
var spy, div, e
|
||||
o.beforeEach(function() {
|
||||
spy = o.spy()
|
||||
div = $document.createElement("div")
|
||||
e = $document.createEvent("MouseEvents")
|
||||
e.initEvent("click", true, true)
|
||||
|
||||
$document.body.appendChild(div)
|
||||
})
|
||||
o.afterEach(function() {
|
||||
$document.body.removeChild(div)
|
||||
})
|
||||
|
||||
o("click fires onclick", function() {
|
||||
div.onclick = spy
|
||||
div.dispatchEvent(e)
|
||||
|
||||
o(spy.callCount).equals(1)
|
||||
o(spy.this).equals(div)
|
||||
o(spy.args[0].type).equals("click")
|
||||
o(spy.args[0].target).equals(div)
|
||||
})
|
||||
o("click without onclick doesn't throw", function(done) {
|
||||
div.dispatchEvent(e)
|
||||
done()
|
||||
})
|
||||
})
|
||||
o.spec("attributes", function() {
|
||||
o.spec("link href", function() {
|
||||
o("is empty string if no attribute", function() {
|
||||
var a = $document.createElement("a")
|
||||
|
||||
o(a.href).equals("")
|
||||
o(a.attributes["href"]).equals(undefined)
|
||||
})
|
||||
o("is path if attribute is set", function() {
|
||||
var a = $document.createElement("a")
|
||||
a.setAttribute("href", "")
|
||||
|
||||
o(a.href).notEquals("")
|
||||
o(a.attributes["href"].nodeValue).equals("")
|
||||
})
|
||||
o("is path if property is set", function() {
|
||||
var a = $document.createElement("a")
|
||||
a.href = ""
|
||||
|
||||
o(a.href).notEquals("")
|
||||
o(a.attributes["href"].nodeValue).equals("")
|
||||
})
|
||||
})
|
||||
o.spec("input checked", function() {
|
||||
o("only exists in input elements", function() {
|
||||
var input = $document.createElement("input")
|
||||
var a = $document.createElement("a")
|
||||
|
||||
o("checked" in input).equals(true)
|
||||
o("checked" in a).equals(false)
|
||||
})
|
||||
o("tracks attribute value when unset", function() {
|
||||
var input = $document.createElement("input")
|
||||
input.setAttribute("type", "checkbox")
|
||||
|
||||
o(input.checked).equals(false)
|
||||
o(input.attributes["checked"]).equals(undefined)
|
||||
|
||||
input.setAttribute("checked", "")
|
||||
|
||||
o(input.checked).equals(true)
|
||||
o(input.attributes["checked"].nodeValue).equals("")
|
||||
|
||||
input.removeAttribute("checked")
|
||||
|
||||
o(input.checked).equals(false)
|
||||
o(input.attributes["checked"]).equals(undefined)
|
||||
})
|
||||
o("does not track attribute value when set", function() {
|
||||
var input = $document.createElement("input")
|
||||
input.setAttribute("type", "checkbox")
|
||||
input.checked = true
|
||||
|
||||
o(input.checked).equals(true)
|
||||
o(input.attributes["checked"]).equals(undefined)
|
||||
|
||||
input.checked = false
|
||||
input.setAttribute("checked", "")
|
||||
|
||||
input.checked = true
|
||||
input.removeAttribute("checked")
|
||||
|
||||
o(input.checked).equals(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
150
test-utils/tests/test-parseURL.js
Normal file
150
test-utils/tests/test-parseURL.js
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
"use strict"
|
||||
|
||||
var o = require("../../ospec/ospec")
|
||||
var parseURL = require("../../test-utils/parseURL")
|
||||
|
||||
o.spec("parseURL", function() {
|
||||
var root = {protocol: "http:", hostname: "localhost", port: "", pathname: "/"}
|
||||
|
||||
o.spec("full URL", function() {
|
||||
o("parses full URL", function() {
|
||||
var data = parseURL("http://www.google.com:80/test?a=b#c")
|
||||
o(data.protocol).equals("http:")
|
||||
o(data.hostname).equals("www.google.com")
|
||||
o(data.port).equals("80")
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("?a=b")
|
||||
o(data.hash).equals("#c")
|
||||
})
|
||||
o("parses full URL omitting optionals", function() {
|
||||
var data = parseURL("http://www.google.com")
|
||||
o(data.protocol).equals("http:")
|
||||
o(data.hostname).equals("www.google.com")
|
||||
o(data.port).equals("")
|
||||
o(data.pathname).equals("/")
|
||||
o(data.search).equals("")
|
||||
o(data.hash).equals("")
|
||||
})
|
||||
})
|
||||
o.spec("absolute path", function() {
|
||||
o("parses absolute path", function() {
|
||||
var data = parseURL("/test?a=b#c", root)
|
||||
o(data.protocol).equals(root.protocol)
|
||||
o(data.hostname).equals(root.hostname)
|
||||
o(data.port).equals(root.port)
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("?a=b")
|
||||
o(data.hash).equals("#c")
|
||||
})
|
||||
o("parses absolute path omitting optionals", function() {
|
||||
var data = parseURL("/test?a=b#c", root)
|
||||
o(data.protocol).equals(root.protocol)
|
||||
o(data.hostname).equals(root.hostname)
|
||||
o(data.port).equals(root.port)
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("?a=b")
|
||||
o(data.hash).equals("#c")
|
||||
})
|
||||
})
|
||||
o.spec("relative path", function() {
|
||||
o("parses relative URL", function() {
|
||||
var data = parseURL("test?a=b#c", root)
|
||||
o(data.protocol).equals(root.protocol)
|
||||
o(data.hostname).equals(root.hostname)
|
||||
o(data.port).equals(root.port)
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("?a=b")
|
||||
o(data.hash).equals("#c")
|
||||
})
|
||||
o("parses relative URL omitting optionals", function() {
|
||||
var data = parseURL("test", root)
|
||||
o(data.protocol).equals(root.protocol)
|
||||
o(data.hostname).equals(root.hostname)
|
||||
o(data.port).equals(root.port)
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("")
|
||||
o(data.hash).equals("")
|
||||
})
|
||||
o("parses relative URL with dot", function() {
|
||||
var data = parseURL("././test?a=b#c", root)
|
||||
o(data.protocol).equals(root.protocol)
|
||||
o(data.hostname).equals(root.hostname)
|
||||
o(data.port).equals(root.port)
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("?a=b")
|
||||
o(data.hash).equals("#c")
|
||||
})
|
||||
o("parses relative URL with dotdot", function() {
|
||||
var data = parseURL("foo/bar/../../test?a=b#c", root)
|
||||
o(data.protocol).equals(root.protocol)
|
||||
o(data.hostname).equals(root.hostname)
|
||||
o(data.port).equals(root.port)
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("?a=b")
|
||||
o(data.hash).equals("#c")
|
||||
})
|
||||
o("clamps invalid dotdot", function() {
|
||||
var data = parseURL("../../test?a=b#c", root)
|
||||
o(data.protocol).equals(root.protocol)
|
||||
o(data.hostname).equals(root.hostname)
|
||||
o(data.port).equals(root.port)
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("?a=b")
|
||||
o(data.hash).equals("#c")
|
||||
})
|
||||
o("clamps invalid dotdot after dot", function() {
|
||||
var data = parseURL("./../../test?a=b#c", root)
|
||||
o(data.protocol).equals(root.protocol)
|
||||
o(data.hostname).equals(root.hostname)
|
||||
o(data.port).equals(root.port)
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("?a=b")
|
||||
o(data.hash).equals("#c")
|
||||
})
|
||||
o("clamps invalid dotdot after valid path", function() {
|
||||
var data = parseURL("a/../../test?a=b#c", root)
|
||||
o(data.protocol).equals(root.protocol)
|
||||
o(data.hostname).equals(root.hostname)
|
||||
o(data.port).equals(root.port)
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("?a=b")
|
||||
o(data.hash).equals("#c")
|
||||
})
|
||||
})
|
||||
o.spec("edge cases", function() {
|
||||
o("handles hash w/ question mark", function() {
|
||||
var data = parseURL("http://www.google.com/test#a?c")
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("")
|
||||
o(data.hash).equals("#a?c")
|
||||
})
|
||||
o("handles hash w/ slash", function() {
|
||||
var data = parseURL("http://www.google.com/test#a/c")
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("")
|
||||
o(data.hash).equals("#a/c")
|
||||
})
|
||||
o("handles hash w/ colon", function() {
|
||||
var data = parseURL("http://www.google.com/test#a:c")
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("")
|
||||
o(data.hash).equals("#a:c")
|
||||
})
|
||||
o("handles search w/ slash", function() {
|
||||
var data = parseURL("http://www.google.com/test?a/c")
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("?a/c")
|
||||
o(data.hash).equals("")
|
||||
})
|
||||
o("handles search w/ slash", function() {
|
||||
var data = parseURL("http://www.google.com/test?a:c")
|
||||
o(data.pathname).equals("/test")
|
||||
o(data.search).equals("?a:c")
|
||||
o(data.hash).equals("")
|
||||
})
|
||||
o("handles pathname w/ colon", function() {
|
||||
var data = parseURL("http://www.google.com/a:b")
|
||||
o(data.pathname).equals("/a:b")
|
||||
})
|
||||
})
|
||||
})
|
||||
520
test-utils/tests/test-pushStateMock.js
Normal file
520
test-utils/tests/test-pushStateMock.js
Normal file
|
|
@ -0,0 +1,520 @@
|
|||
"use strict"
|
||||
|
||||
var o = require("../../ospec/ospec")
|
||||
var pushStateMock = require("../../test-utils/pushStateMock")
|
||||
|
||||
o.spec("pushStateMock", function() {
|
||||
|
||||
var $window
|
||||
o.beforeEach(function() {
|
||||
$window = pushStateMock()
|
||||
})
|
||||
|
||||
o.spec("initial state", function() {
|
||||
o("has url on page load", function() {
|
||||
o($window.location.href).equals("http://localhost/")
|
||||
})
|
||||
})
|
||||
|
||||
o.spec("set href", function() {
|
||||
o("changes url on location.href change", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = "http://localhost/a"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/a")
|
||||
})
|
||||
o("changes url on relative location.href change", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = "a"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/a")
|
||||
o($window.location.pathname).equals("/a")
|
||||
})
|
||||
o("changes url on dotdot location.href change", function() {
|
||||
$window.location.href = "a"
|
||||
var old = $window.location.href
|
||||
$window.location.href = ".."
|
||||
|
||||
o(old).equals("http://localhost/a")
|
||||
o($window.location.href).equals("http://localhost/")
|
||||
o($window.location.pathname).equals("/")
|
||||
})
|
||||
o("changes url on deep dotdot location.href change", function() {
|
||||
$window.location.href = "a/b/c"
|
||||
var old = $window.location.href
|
||||
$window.location.href = ".."
|
||||
|
||||
o(old).equals("http://localhost/a/b/c")
|
||||
o($window.location.href).equals("http://localhost/a")
|
||||
o($window.location.pathname).equals("/a")
|
||||
})
|
||||
o("does not change url on dotdot location.href change from root", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = ".."
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/")
|
||||
o($window.location.pathname).equals("/")
|
||||
})
|
||||
o("changes url on dot relative location.href change", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = "a"
|
||||
$window.location.href = "./b"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/b")
|
||||
o($window.location.pathname).equals("/b")
|
||||
})
|
||||
o("does not change url on dot location.href change", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = "a"
|
||||
$window.location.href = "."
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/a")
|
||||
o($window.location.pathname).equals("/a")
|
||||
})
|
||||
o("changes url on hash-only location.href change", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = "#a"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/#a")
|
||||
o($window.location.hash).equals("#a")
|
||||
})
|
||||
o("changes url on search-only location.href change", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = "?a"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/?a")
|
||||
o($window.location.search).equals("?a")
|
||||
})
|
||||
o("changes hash on location.href change", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = "http://localhost/a#b"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/a#b")
|
||||
o($window.location.hash).equals("#b")
|
||||
})
|
||||
o("changes search on location.href change", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = "http://localhost/a?b"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/a?b")
|
||||
o($window.location.search).equals("?b")
|
||||
})
|
||||
o("changes search and hash on location.href change", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = "http://localhost/a?b#c"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/a?b#c")
|
||||
o($window.location.search).equals("?b")
|
||||
o($window.location.hash).equals("#c")
|
||||
})
|
||||
o("handles search with search and hash", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = "http://localhost/a?b?c#d"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/a?b?c#d")
|
||||
o($window.location.search).equals("?b?c")
|
||||
o($window.location.hash).equals("#d")
|
||||
})
|
||||
o("handles hash with search and hash", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.href = "http://localhost/a#b?c#d"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/a#b?c#d")
|
||||
o($window.location.search).equals("")
|
||||
o($window.location.hash).equals("#b?c#d")
|
||||
})
|
||||
})
|
||||
o.spec("set search", function() {
|
||||
o("changes url on location.search change", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.search = "?b"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/?b")
|
||||
o($window.location.search).equals("?b")
|
||||
})
|
||||
})
|
||||
o.spec("set hash", function() {
|
||||
o("changes url on location.hash change", function() {
|
||||
var old = $window.location.href
|
||||
$window.location.hash = "#b"
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/#b")
|
||||
o($window.location.hash).equals("#b")
|
||||
})
|
||||
})
|
||||
o.spec("pushState", function() {
|
||||
o("changes url on pushstate", function() {
|
||||
var old = $window.location.href
|
||||
$window.history.pushState(null, null, "http://localhost/a")
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/a")
|
||||
})
|
||||
o("changes search on pushstate", function() {
|
||||
var old = $window.location.href
|
||||
$window.history.pushState(null, null, "http://localhost/?a")
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/?a")
|
||||
o($window.location.search).equals("?a")
|
||||
})
|
||||
o("changes search on relative pushstate", function() {
|
||||
var old = $window.location.href
|
||||
$window.history.pushState(null, null, "?a")
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/?a")
|
||||
o($window.location.search).equals("?a")
|
||||
})
|
||||
o("changes hash on pushstate", function() {
|
||||
var old = $window.location.href
|
||||
$window.history.pushState(null, null, "http://localhost/#a")
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/#a")
|
||||
o($window.location.hash).equals("#a")
|
||||
})
|
||||
o("changes hash on relative pushstate", function() {
|
||||
var old = $window.location.href
|
||||
$window.history.pushState(null, null, "#a")
|
||||
|
||||
o(old).equals("http://localhost/")
|
||||
o($window.location.href).equals("http://localhost/#a")
|
||||
o($window.location.hash).equals("#a")
|
||||
})
|
||||
})
|
||||
o.spec("onpopstate", function() {
|
||||
o("history.back() without history does not trigger onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(0)
|
||||
})
|
||||
o("history.back() after pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "http://localhost/a")
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(1)
|
||||
o($window.onpopstate.args[0].type).equals("popstate")
|
||||
})
|
||||
o("history.back() after relative pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "a")
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(1)
|
||||
})
|
||||
o("history.back() after search pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "http://localhost/?a")
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(1)
|
||||
})
|
||||
o("history.back() after relative search pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "?a")
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(1)
|
||||
})
|
||||
o("history.back() after hash pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "http://localhost/#a")
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(1)
|
||||
})
|
||||
o("history.back() after relative hash pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "#a")
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(1)
|
||||
})
|
||||
o("history.back() after replacestate does not trigger onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.replaceState(null, null, "http://localhost/a")
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(0)
|
||||
})
|
||||
o("history.back() after relative replacestate does not trigger onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.replaceState(null, null, "a")
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(0)
|
||||
})
|
||||
o("history.back() after relative search replacestate does not trigger onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.replaceState(null, null, "?a")
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(0)
|
||||
})
|
||||
o("history.back() after relative hash replacestate does not trigger onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.replaceState(null, null, "#a")
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(0)
|
||||
})
|
||||
o("history.forward() after pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "http://localhost/a")
|
||||
$window.history.back()
|
||||
$window.history.forward()
|
||||
|
||||
o($window.onpopstate.callCount).equals(2)
|
||||
})
|
||||
o("history.forward() after relative pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "a")
|
||||
$window.history.back()
|
||||
$window.history.forward()
|
||||
|
||||
o($window.onpopstate.callCount).equals(2)
|
||||
})
|
||||
o("history.forward() after search pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "http://localhost/?a")
|
||||
$window.history.back()
|
||||
$window.history.forward()
|
||||
|
||||
o($window.onpopstate.callCount).equals(2)
|
||||
})
|
||||
o("history.forward() after relative search pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "?a")
|
||||
$window.history.back()
|
||||
$window.history.forward()
|
||||
|
||||
o($window.onpopstate.callCount).equals(2)
|
||||
})
|
||||
o("history.forward() after hash pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "http://localhost/#a")
|
||||
$window.history.back()
|
||||
$window.history.forward()
|
||||
|
||||
o($window.onpopstate.callCount).equals(2)
|
||||
})
|
||||
o("history.forward() after relative hash pushstate triggers onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.pushState(null, null, "#a")
|
||||
$window.history.back()
|
||||
$window.history.forward()
|
||||
|
||||
o($window.onpopstate.callCount).equals(2)
|
||||
})
|
||||
o("history.back() without history does not trigger onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(0)
|
||||
})
|
||||
o("history.forward() without history does not trigger onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.forward()
|
||||
|
||||
o($window.onpopstate.callCount).equals(0)
|
||||
})
|
||||
o("history navigation without history does not trigger onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.back()
|
||||
$window.history.forward()
|
||||
|
||||
o($window.onpopstate.callCount).equals(0)
|
||||
})
|
||||
o("reverse history navigation without history does not trigger onpopstate", function() {
|
||||
$window.onpopstate = o.spy()
|
||||
$window.history.forward()
|
||||
$window.history.back()
|
||||
|
||||
o($window.onpopstate.callCount).equals(0)
|
||||
})
|
||||
o("onpopstate has correct url during call", function(done) {
|
||||
$window.location.href = "a"
|
||||
$window.onpopstate = function() {
|
||||
o($window.location.href).equals("http://localhost/a")
|
||||
done()
|
||||
}
|
||||
$window.history.pushState(null, null, "b")
|
||||
$window.history.back()
|
||||
})
|
||||
})
|
||||
o.spec("onhashchance", function() {
|
||||
o("onhashchange triggers on location.href change", function() {
|
||||
$window.onhashchange = o.spy()
|
||||
$window.location.href = "http://localhost/#a"
|
||||
|
||||
o($window.onhashchange.callCount).equals(1)
|
||||
o($window.onhashchange.args[0].type).equals("hashchange")
|
||||
})
|
||||
o("onhashchange triggers on relative location.href change", function() {
|
||||
$window.onhashchange = o.spy()
|
||||
$window.location.href = "#a"
|
||||
|
||||
o($window.onhashchange.callCount).equals(1)
|
||||
})
|
||||
o("onhashchange triggers on location.hash change", function() {
|
||||
$window.onhashchange = o.spy()
|
||||
$window.location.hash = "#a"
|
||||
|
||||
o($window.onhashchange.callCount).equals(1)
|
||||
})
|
||||
o("onhashchange does not trigger on page change", function() {
|
||||
$window.onhashchange = o.spy()
|
||||
$window.location.href = "http://localhost/a"
|
||||
|
||||
o($window.onhashchange.callCount).equals(0)
|
||||
})
|
||||
o("onhashchange does not trigger on page change with different hash", function() {
|
||||
$window.location.href = "http://localhost/#a"
|
||||
$window.onhashchange = o.spy()
|
||||
$window.location.href = "http://localhost/a#b"
|
||||
|
||||
o($window.onhashchange.callCount).equals(0)
|
||||
})
|
||||
o("onhashchange does not trigger on page change with same hash", function() {
|
||||
$window.location.href = "http://localhost/#b"
|
||||
$window.onhashchange = o.spy()
|
||||
$window.location.href = "http://localhost/a#b"
|
||||
|
||||
o($window.onhashchange.callCount).equals(0)
|
||||
})
|
||||
o("onhashchange triggers on history.back()", function() {
|
||||
$window.location.href = "#a"
|
||||
$window.onhashchange = o.spy()
|
||||
$window.history.back()
|
||||
|
||||
o($window.onhashchange.callCount).equals(1)
|
||||
})
|
||||
o("onhashchange triggers on history.forward()", function() {
|
||||
$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() {
|
||||
$window.location.href = "#a"
|
||||
$window.location.href = "a#b"
|
||||
$window.onhashchange = o.spy()
|
||||
$window.history.back()
|
||||
|
||||
o($window.onhashchange.callCount).equals(0)
|
||||
})
|
||||
o("onhashchange does not trigger on history.back() that causes page change with same hash", function() {
|
||||
$window.location.href = "#a"
|
||||
$window.location.href = "a#a"
|
||||
$window.onhashchange = o.spy()
|
||||
$window.history.back()
|
||||
|
||||
o($window.onhashchange.callCount).equals(0)
|
||||
})
|
||||
o("onhashchange does not trigger on history.forward() that causes page change with different hash", function() {
|
||||
$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() {
|
||||
$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.spec("onunload", function() {
|
||||
o("onunload triggers on location.href change", function() {
|
||||
$window.onunload = o.spy()
|
||||
$window.location.href = "http://localhost/a"
|
||||
|
||||
o($window.onunload.callCount).equals(1)
|
||||
o($window.onunload.args[0].type).equals("unload")
|
||||
})
|
||||
o("onunload triggers on relative location.href change", function() {
|
||||
$window.onunload = o.spy()
|
||||
$window.location.href = "a"
|
||||
|
||||
o($window.onunload.callCount).equals(1)
|
||||
})
|
||||
o("onunload triggers on search change via location.href", function() {
|
||||
$window.onunload = o.spy()
|
||||
$window.location.href = "http://localhost/?a"
|
||||
|
||||
o($window.onunload.callCount).equals(1)
|
||||
})
|
||||
o("onunload triggers on relative search change via location.href", function() {
|
||||
$window.onunload = o.spy()
|
||||
$window.location.href = "?a"
|
||||
|
||||
o($window.onunload.callCount).equals(1)
|
||||
})
|
||||
o("onunload does not trigger on hash change via location.href", function() {
|
||||
$window.onunload = o.spy()
|
||||
$window.location.href = "http://localhost/#a"
|
||||
|
||||
o($window.onunload.callCount).equals(0)
|
||||
})
|
||||
o("onunload does not trigger on relative hash change via location.href", function() {
|
||||
$window.onunload = o.spy()
|
||||
$window.location.href = "#a"
|
||||
|
||||
o($window.onunload.callCount).equals(0)
|
||||
})
|
||||
o("onunload does not trigger on hash-only history.back()", function() {
|
||||
$window.location.href = "#a"
|
||||
$window.onunload = o.spy()
|
||||
$window.history.back()
|
||||
|
||||
o($window.onunload.callCount).equals(0)
|
||||
})
|
||||
o("onunload does not trigger on hash-only history.forward()", function() {
|
||||
$window.location.href = "#a"
|
||||
$window.history.back()
|
||||
$window.onunload = o.spy()
|
||||
$window.history.forward()
|
||||
|
||||
o($window.onunload.callCount).equals(0)
|
||||
})
|
||||
o("onunload has correct url during call via location.href change", function(done) {
|
||||
$window.onunload = function() {
|
||||
o($window.location.href).equals("http://localhost/")
|
||||
done()
|
||||
}
|
||||
$window.location.href = "a"
|
||||
})
|
||||
o("onunload has correct url during call via location.search change", function(done) {
|
||||
$window.onunload = function() {
|
||||
o($window.location.href).equals("http://localhost/")
|
||||
done()
|
||||
}
|
||||
$window.location.search = "?a"
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue