make setPath always async
This commit is contained in:
parent
520d15a060
commit
e8e0bae726
10 changed files with 154 additions and 61 deletions
|
|
@ -38,7 +38,7 @@ Mithril's `config` method is now replaced by several lifecycle methods to improv
|
||||||
|
|
||||||
## Robustness
|
## Robustness
|
||||||
|
|
||||||
There are over 2600 assertions in the test suite, and tests cover even difficult-to-test things like `location.href`, `element.innerHTML` and `XMLHttpRequest` usage.
|
There are over 2700 assertions in the test suite, and tests cover even difficult-to-test things like `location.href`, `element.innerHTML` and `XMLHttpRequest` usage.
|
||||||
|
|
||||||
## Modularity
|
## Modularity
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
<script src="../../test-utils/domMock.js"></script>
|
<script src="../../test-utils/domMock.js"></script>
|
||||||
<script src="../../test-utils/pushStateMock.js"></script>
|
<script src="../../test-utils/pushStateMock.js"></script>
|
||||||
|
|
||||||
|
<script src="../../util/stream.js"></script>
|
||||||
<script src="../../render/node.js"></script>
|
<script src="../../render/node.js"></script>
|
||||||
<script src="../../render/trust.js"></script>
|
<script src="../../render/trust.js"></script>
|
||||||
<script src="../../render/hyperscript.js"></script>
|
<script src="../../render/hyperscript.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
"use strict"
|
"use strict"
|
||||||
|
|
||||||
var o = require("../../ospec/ospec")
|
var o = require("../../ospec/ospec")
|
||||||
|
var callAsync = require("../../test-utils/callAsync")
|
||||||
var pushStateMock = require("../../test-utils/pushStateMock")
|
var pushStateMock = require("../../test-utils/pushStateMock")
|
||||||
var domMock = require("../../test-utils/domMock")
|
var domMock = require("../../test-utils/domMock")
|
||||||
|
|
||||||
|
|
@ -28,7 +29,7 @@ o.spec("route", function() {
|
||||||
route = apiRouter($window, coreRenderer($window), redraw)
|
route = apiRouter($window, coreRenderer($window), redraw)
|
||||||
})
|
})
|
||||||
|
|
||||||
o("renders into `root`", function() {
|
o("renders into `root`", function(done) {
|
||||||
route(root, "/", {
|
route(root, "/", {
|
||||||
"/" : {
|
"/" : {
|
||||||
view: function() {
|
view: function() {
|
||||||
|
|
@ -37,7 +38,11 @@ o.spec("route", function() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
o(root.firstChild.nodeName).equals("DIV")
|
callAsync(function() {
|
||||||
|
o(root.firstChild.nodeName).equals("DIV")
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
o("redraws when render function is executed", function(done) {
|
o("redraws when render function is executed", function(done) {
|
||||||
|
|
@ -55,19 +60,21 @@ o.spec("route", function() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
o(oninit.callCount).equals(1)
|
callAsync(function() {
|
||||||
|
o(oninit.callCount).equals(1)
|
||||||
|
|
||||||
redraw.publish()
|
redraw.publish()
|
||||||
|
|
||||||
// Wrapped to give time for the rate-limited redraw to fire
|
// Wrapped to give time for the rate-limited redraw to fire
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
o(onupdate.callCount).equals(1)
|
o(onupdate.callCount).equals(1)
|
||||||
|
|
||||||
done()
|
done()
|
||||||
}, FRAME_BUDGET)
|
}, FRAME_BUDGET)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
o("redraws on events", function(done, timeout) {
|
o("redraws on events", function(done) {
|
||||||
var onupdate = o.spy()
|
var onupdate = o.spy()
|
||||||
var oninit = o.spy()
|
var oninit = o.spy()
|
||||||
var onclick = o.spy()
|
var onclick = o.spy()
|
||||||
|
|
@ -87,21 +94,23 @@ o.spec("route", function() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
root.firstChild.dispatchEvent(e)
|
callAsync(function() {
|
||||||
|
root.firstChild.dispatchEvent(e)
|
||||||
|
|
||||||
o(oninit.callCount).equals(1)
|
o(oninit.callCount).equals(1)
|
||||||
|
|
||||||
o(onclick.callCount).equals(1)
|
o(onclick.callCount).equals(1)
|
||||||
o(onclick.this).equals(root.firstChild)
|
o(onclick.this).equals(root.firstChild)
|
||||||
o(onclick.args[0].type).equals("click")
|
o(onclick.args[0].type).equals("click")
|
||||||
o(onclick.args[0].target).equals(root.firstChild)
|
o(onclick.args[0].target).equals(root.firstChild)
|
||||||
|
|
||||||
// Wrapped to give time for the rate-limited redraw to fire
|
// Wrapped to give time for the rate-limited redraw to fire
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
o(onupdate.callCount).equals(1)
|
o(onupdate.callCount).equals(1)
|
||||||
|
|
||||||
done()
|
done()
|
||||||
}, FRAME_BUDGET)
|
}, FRAME_BUDGET)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
o("event handlers can skip redraw", function(done) {
|
o("event handlers can skip redraw", function(done) {
|
||||||
|
|
@ -126,19 +135,21 @@ o.spec("route", function() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
root.firstChild.dispatchEvent(e)
|
callAsync(function() {
|
||||||
|
root.firstChild.dispatchEvent(e)
|
||||||
|
|
||||||
o(oninit.callCount).equals(1)
|
o(oninit.callCount).equals(1)
|
||||||
|
|
||||||
// Wrapped to ensure no redraw fired
|
// Wrapped to ensure no redraw fired
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
o(onupdate.callCount).equals(0)
|
o(onupdate.callCount).equals(0)
|
||||||
|
|
||||||
done()
|
done()
|
||||||
}, FRAME_BUDGET)
|
}, FRAME_BUDGET)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
o("changes location on route.link", function() {
|
o("changes location on route.link", function(done) {
|
||||||
var e = $window.document.createEvent("MouseEvents")
|
var e = $window.document.createEvent("MouseEvents")
|
||||||
|
|
||||||
e.initEvent("click", true, true)
|
e.initEvent("click", true, true)
|
||||||
|
|
@ -161,10 +172,14 @@ o.spec("route", function() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
o($window.location.href).equals("http://localhost/?/")
|
callAsync(function() {
|
||||||
|
o($window.location.href).equals("http://localhost/?/")
|
||||||
|
|
||||||
root.firstChild.dispatchEvent(e)
|
root.firstChild.dispatchEvent(e)
|
||||||
|
|
||||||
o($window.location.href).equals("http://localhost/?/test")
|
o($window.location.href).equals("http://localhost/?/test")
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
73
mithril.js
73
mithril.js
|
|
@ -16,8 +16,8 @@ function initStream(stream, args) {
|
||||||
stream.constructor = createStream
|
stream.constructor = createStream
|
||||||
stream._state = {id: guid++, value: undefined, error: undefined, state: 0, derive: undefined, recover: undefined, deps: {}, parents: [], errorStream: undefined, endStream: undefined}
|
stream._state = {id: guid++, value: undefined, error: undefined, state: 0, derive: undefined, recover: undefined, deps: {}, parents: [], errorStream: undefined, endStream: undefined}
|
||||||
stream.map = map, stream.ap = ap, stream.of = createStream
|
stream.map = map, stream.ap = ap, stream.of = createStream
|
||||||
stream.valueOf = valueOf
|
stream.valueOf = valueOf, stream.toJSON = toJSON
|
||||||
stream.catch = doCatch
|
stream.run = run, stream.catch = doCatch
|
||||||
|
|
||||||
Object.defineProperties(stream, {
|
Object.defineProperties(stream, {
|
||||||
error: {get: function() {
|
error: {get: function() {
|
||||||
|
|
@ -46,15 +46,18 @@ function initStream(stream, args) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
function updateStream(stream, value, error) {
|
function updateStream(stream, value, error) {
|
||||||
if (!absorbStream(stream, value, false) && !absorbStream(stream, error, true)) {
|
updateState(stream, value, error)
|
||||||
updateState(stream, value, error)
|
for (var id in stream._state.deps) updateDependency(stream._state.deps[id], false)
|
||||||
for (var id in stream._state.deps) updateDependency(stream._state.deps[id], false)
|
finalize(stream)
|
||||||
finalize(stream)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
function updateState(stream, value, error) {
|
function updateState(stream, value, error) {
|
||||||
|
error = unwrapError(value, error)
|
||||||
if (error !== undefined && typeof stream._state.recover === "function") {
|
if (error !== undefined && typeof stream._state.recover === "function") {
|
||||||
try {updateValues(stream, stream._state.recover(), undefined)}
|
try {
|
||||||
|
var recovered = stream._state.recover()
|
||||||
|
if (recovered === HALT) return
|
||||||
|
updateValues(stream, recovered, undefined)
|
||||||
|
}
|
||||||
catch (e) {updateValues(stream, undefined, e)}
|
catch (e) {updateValues(stream, undefined, e)}
|
||||||
}
|
}
|
||||||
else updateValues(stream, value, error)
|
else updateValues(stream, value, error)
|
||||||
|
|
@ -73,7 +76,8 @@ function updateDependency(stream, mustSync) {
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
var value = state.derive()
|
var value = state.derive()
|
||||||
if (!absorbStream(stream, value)) updateState(stream, value, undefined)
|
if (value === HALT) return
|
||||||
|
updateState(stream, value, undefined)
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
updateState(stream, undefined, e)
|
updateState(stream, undefined, e)
|
||||||
|
|
@ -81,29 +85,28 @@ function updateDependency(stream, mustSync) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function absorbStream(stream, value, isError) {
|
function unwrapError(value, error) {
|
||||||
if (value != null && value.constructor === createStream) {
|
if (value != null && value.constructor === createStream) {
|
||||||
if (value._state.state === 2) {
|
if (value._state.error !== undefined) error = value._state.error
|
||||||
stream.end(true)
|
else error = unwrapError(value._state.value, value._state.error)
|
||||||
stream(value())
|
|
||||||
}
|
|
||||||
else if (value._state.error) stream.error(value.error())
|
|
||||||
else if (value._state.state === 0) return true
|
|
||||||
else if (!isError) stream(value())
|
|
||||||
else stream.error(value())
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
return error
|
||||||
}
|
}
|
||||||
function finalize(stream) {
|
function finalize(stream) {
|
||||||
stream._state.changed = false
|
stream._state.changed = false
|
||||||
for (var id in stream._state.deps) stream._state.deps[id]._state.changed = false
|
for (var id in stream._state.deps) stream._state.deps[id]._state.changed = false
|
||||||
}
|
}
|
||||||
|
function run(fn) {
|
||||||
|
var self = createStream(), stream = this
|
||||||
|
return initDependency(self, [stream], function() {
|
||||||
|
return absorb(self, fn(stream()))
|
||||||
|
}, undefined)
|
||||||
|
}
|
||||||
function doCatch(fn) {
|
function doCatch(fn) {
|
||||||
var stream = this
|
var self = createStream(), stream = this
|
||||||
var derive = function() {return stream._state.value}
|
var derive = function() {return stream._state.value}
|
||||||
var recover = function() {return fn(stream._state.error)}
|
var recover = function() {return absorb(self, fn(stream._state.error))}
|
||||||
return initDependency(createStream(), [stream], derive, recover)
|
return initDependency(self, [stream], derive, recover)
|
||||||
}
|
}
|
||||||
function combine(fn, streams) {
|
function combine(fn, streams) {
|
||||||
return initDependency(createStream(), streams, function() {
|
return initDependency(createStream(), streams, function() {
|
||||||
|
|
@ -112,6 +115,16 @@ function combine(fn, streams) {
|
||||||
return fn.apply(this, streams.concat([streams.filter(changed)]))
|
return fn.apply(this, streams.concat([streams.filter(changed)]))
|
||||||
}, undefined)
|
}, undefined)
|
||||||
}
|
}
|
||||||
|
function absorb(stream, value) {
|
||||||
|
if (value != null && value.constructor === createStream) {
|
||||||
|
value.error.map(stream.error)
|
||||||
|
value.map(stream)
|
||||||
|
if (value._state.state === 0) return HALT
|
||||||
|
if (value._state.error) throw value._state.error
|
||||||
|
value = value._state.value
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
function initDependency(dep, streams, derive, recover) {
|
function initDependency(dep, streams, derive, recover) {
|
||||||
var state = dep._state
|
var state = dep._state
|
||||||
state.derive = derive
|
state.derive = derive
|
||||||
|
|
@ -145,6 +158,7 @@ function unregisterStream(stream) {
|
||||||
function map(fn) {return combine(function(stream) {return fn(stream())}, [this])}
|
function map(fn) {return combine(function(stream) {return fn(stream())}, [this])}
|
||||||
function ap(stream) {return combine(function(s1, s2) {return s1()(s2())}, [this, stream])}
|
function ap(stream) {return combine(function(s1, s2) {return s1()(s2())}, [this, stream])}
|
||||||
function valueOf() {return this._state.value}
|
function valueOf() {return this._state.value}
|
||||||
|
function toJSON() {return JSON.stringify(this._state.value)}
|
||||||
function active(stream) {return stream._state.state === 1}
|
function active(stream) {return stream._state.state === 1}
|
||||||
function changed(stream) {return stream._state.changed}
|
function changed(stream) {return stream._state.changed}
|
||||||
function notEnded(stream) {return stream._state.state !== 2}
|
function notEnded(stream) {return stream._state.state !== 2}
|
||||||
|
|
@ -154,7 +168,7 @@ function reject(e) {
|
||||||
stream.error(e)
|
stream.error(e)
|
||||||
return stream
|
return stream
|
||||||
}
|
}
|
||||||
var Stream = {stream: createStream, combine: combine, reject: reject}
|
var Stream = {stream: createStream, combine: combine, reject: reject, HALT: HALT}
|
||||||
function Node(tag, key, attrs, children, text, dom) {
|
function Node(tag, key, attrs, children, text, dom) {
|
||||||
return {tag: tag, key: key, attrs: attrs, children: children, text: text, dom: dom, domSize: undefined, state: {}, events: undefined, instance: undefined}
|
return {tag: tag, key: key, attrs: attrs, children: children, text: text, dom: dom, domSize: undefined, state: {}, events: undefined, instance: undefined}
|
||||||
}
|
}
|
||||||
|
|
@ -782,7 +796,11 @@ var requestService = function($window) {
|
||||||
|
|
||||||
stream(response)
|
stream(response)
|
||||||
}
|
}
|
||||||
else stream.error(new Error(xhr.responseText))
|
else {
|
||||||
|
var error = new Error(xhr.responseText)
|
||||||
|
for (var key in response) error[key] = response[key]
|
||||||
|
stream.error(error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
stream.error(e)
|
stream.error(e)
|
||||||
|
|
@ -892,6 +910,7 @@ var parseQueryString = function(string) {
|
||||||
}
|
}
|
||||||
var coreRouter = function($window) {
|
var coreRouter = function($window) {
|
||||||
var supportsPushState = typeof $window.history.pushState === "function" && $window.location.protocol !== "file:"
|
var supportsPushState = typeof $window.history.pushState === "function" && $window.location.protocol !== "file:"
|
||||||
|
var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout
|
||||||
var prefix = "#!"
|
var prefix = "#!"
|
||||||
function setPrefix(value) {prefix = value}
|
function setPrefix(value) {prefix = value}
|
||||||
function normalize(fragment) {
|
function normalize(fragment) {
|
||||||
|
|
@ -939,7 +958,7 @@ var coreRouter = function($window) {
|
||||||
if (supportsPushState) {
|
if (supportsPushState) {
|
||||||
if (options && options.replace) $window.history.replaceState(null, null, prefix + path)
|
if (options && options.replace) $window.history.replaceState(null, null, prefix + path)
|
||||||
else $window.history.pushState(null, null, prefix + path)
|
else $window.history.pushState(null, null, prefix + path)
|
||||||
$window.onpopstate()
|
callAsync($window.onpopstate)
|
||||||
}
|
}
|
||||||
else $window.location.href = prefix + path
|
else $window.location.href = prefix + path
|
||||||
}
|
}
|
||||||
|
|
@ -991,7 +1010,7 @@ var throttle = function(callback) {
|
||||||
}
|
}
|
||||||
else if (pending === null) {
|
else if (pending === null) {
|
||||||
pending = timeout(function() {
|
pending = timeout(function() {
|
||||||
pending = 0
|
pending = null
|
||||||
callback()
|
callback()
|
||||||
last = new Date().getTime()
|
last = new Date().getTime()
|
||||||
}, time - (now - last))
|
}, time - (now - last))
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ var parseQueryString = require("../querystring/parse")
|
||||||
|
|
||||||
module.exports = function($window) {
|
module.exports = function($window) {
|
||||||
var supportsPushState = typeof $window.history.pushState === "function" && $window.location.protocol !== "file:"
|
var supportsPushState = typeof $window.history.pushState === "function" && $window.location.protocol !== "file:"
|
||||||
|
var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout
|
||||||
|
|
||||||
var prefix = "#!"
|
var prefix = "#!"
|
||||||
function setPrefix(value) {prefix = value}
|
function setPrefix(value) {prefix = value}
|
||||||
|
|
@ -60,7 +61,7 @@ module.exports = function($window) {
|
||||||
if (supportsPushState) {
|
if (supportsPushState) {
|
||||||
if (options && options.replace) $window.history.replaceState(null, null, prefix + path)
|
if (options && options.replace) $window.history.replaceState(null, null, prefix + path)
|
||||||
else $window.history.pushState(null, null, prefix + path)
|
else $window.history.pushState(null, null, prefix + path)
|
||||||
$window.onpopstate()
|
callAsync($window.onpopstate)
|
||||||
}
|
}
|
||||||
else $window.location.href = prefix + path
|
else $window.location.href = prefix + path
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
<body>
|
<body>
|
||||||
<script src="../../module/module.js"></script>
|
<script src="../../module/module.js"></script>
|
||||||
<script src="../../ospec/ospec.js"></script>
|
<script src="../../ospec/ospec.js"></script>
|
||||||
|
<script src="../../test-utils/callAsync.js"></script>
|
||||||
<script src="../../test-utils/parseURL.js"></script>
|
<script src="../../test-utils/parseURL.js"></script>
|
||||||
<script src="../../test-utils/pushStateMock.js"></script>
|
<script src="../../test-utils/pushStateMock.js"></script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,13 @@ o.spec("Router.defineRoutes", function() {
|
||||||
onFail = o.spy()
|
onFail = o.spy()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
o("calls onRouteChange on init", function() {
|
||||||
|
$window.location.href = prefix + "/a"
|
||||||
|
router.defineRoutes({"/a": {data: 1}}, onRouteChange, onFail)
|
||||||
|
|
||||||
|
o(onRouteChange.callCount).equals(1)
|
||||||
|
})
|
||||||
|
|
||||||
o("resolves to route", function() {
|
o("resolves to route", function() {
|
||||||
$window.location.href = prefix + "/test"
|
$window.location.href = prefix + "/test"
|
||||||
router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail)
|
router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
"use strict"
|
"use strict"
|
||||||
|
|
||||||
var o = require("../../ospec/ospec")
|
var o = require("../../ospec/ospec")
|
||||||
|
var callAsync = require("../../test-utils/callAsync")
|
||||||
var pushStateMock = require("../../test-utils/pushStateMock")
|
var pushStateMock = require("../../test-utils/pushStateMock")
|
||||||
var Router = require("../../router/router")
|
var Router = require("../../router/router")
|
||||||
|
|
||||||
|
|
@ -17,6 +18,28 @@ o.spec("Router.setPath", function() {
|
||||||
onFail = o.spy()
|
onFail = o.spy()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
o("setPath calls onRouteChange asynchronously", function(done) {
|
||||||
|
$window.location.href = prefix + "/a"
|
||||||
|
router.defineRoutes({"/a": {data: 1}, "/b": {data: 2}}, onRouteChange, onFail)
|
||||||
|
router.setPath("/b")
|
||||||
|
|
||||||
|
o(onRouteChange.callCount).equals(1)
|
||||||
|
callAsync(function() {
|
||||||
|
o(onRouteChange.callCount).equals(2)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
o("setPath calls onFail asynchronously", function(done) {
|
||||||
|
$window.location.href = prefix + "/a"
|
||||||
|
router.defineRoutes({"/a": {data: 1}, "/b": {data: 2}}, onRouteChange, onFail)
|
||||||
|
router.setPath("/c")
|
||||||
|
|
||||||
|
o(onFail.callCount).equals(0)
|
||||||
|
callAsync(function() {
|
||||||
|
o(onFail.callCount).equals(1)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
o("sets route via API", function() {
|
o("sets route via API", function() {
|
||||||
$window.location.href = prefix + "/test"
|
$window.location.href = prefix + "/test"
|
||||||
router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail)
|
router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
<script src="../../test-utils/pushStateMock.js"></script>
|
<script src="../../test-utils/pushStateMock.js"></script>
|
||||||
<script src="../../test-utils/xhrMock.js"></script>
|
<script src="../../test-utils/xhrMock.js"></script>
|
||||||
<script src="../../test-utils/domMock.js"></script>
|
<script src="../../test-utils/domMock.js"></script>
|
||||||
|
<script src="test-callAsync.js"></script>
|
||||||
<script src="test-parseURL.js"></script>
|
<script src="test-parseURL.js"></script>
|
||||||
<script src="test-pushStateMock.js"></script>
|
<script src="test-pushStateMock.js"></script>
|
||||||
<script src="test-xhrMock.js"></script>
|
<script src="test-xhrMock.js"></script>
|
||||||
|
|
|
||||||
25
test-utils/tests/test-callAsync.js
Normal file
25
test-utils/tests/test-callAsync.js
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
"use strict"
|
||||||
|
|
||||||
|
var o = require("../../ospec/ospec")
|
||||||
|
var callAsync = require("../../test-utils/callAsync")
|
||||||
|
|
||||||
|
o.spec("callAsync", function() {
|
||||||
|
o("works", function(done) {
|
||||||
|
var count = 0
|
||||||
|
callAsync(function() {
|
||||||
|
o(count).equals(1)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
count++
|
||||||
|
})
|
||||||
|
o("gets called before setTimeout", function(done) {
|
||||||
|
var timeout
|
||||||
|
callAsync(function() {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
timeout = setTimeout(function() {
|
||||||
|
throw new Error("callAsync was called too slow")
|
||||||
|
}, 0)
|
||||||
|
})
|
||||||
|
})
|
||||||
Loading…
Add table
Add a link
Reference in a new issue