[ospec] give async timeouts a proper stack trace
This commit is contained in:
parent
da0c5c9b9a
commit
ff1a07df1b
1 changed files with 27 additions and 24 deletions
|
|
@ -17,7 +17,7 @@ else window.o = m()
|
||||||
return new Assert(subject)
|
return new Assert(subject)
|
||||||
}
|
}
|
||||||
else if (results == null) {
|
else if (results == null) {
|
||||||
ctx[unique(subject)] = predicate
|
ctx[unique(subject)] = new Task(predicate, ensureStackTrace(new Error))
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Test definition shouldn't be nested. To group tests use `o.spec()`")
|
throw new Error("Test definition shouldn't be nested. To group tests use `o.spec()`")
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +37,7 @@ else window.o = m()
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
console.log(highlight("/!\\ WARNING /!\\ o.only() mode"))
|
console.log(highlight("/!\\ WARNING /!\\ o.only() mode"))
|
||||||
try {throw new Error} catch (e) {
|
try {throw new Error} catch (e) {
|
||||||
console.log(this.cleanStackTrace(e) + "\n")
|
console.log(o.cleanStackTrace(e) + "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
o(subject, only = predicate)
|
o(subject, only = predicate)
|
||||||
|
|
@ -79,7 +79,7 @@ else window.o = m()
|
||||||
o.run = function(reporter) {
|
o.run = function(reporter) {
|
||||||
results = []
|
results = []
|
||||||
start = new Date
|
start = new Date
|
||||||
test(spec, [], [], function() {
|
test(spec, [], [], new Task(function() {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
if (typeof reporter === "function") reporter(results)
|
if (typeof reporter === "function") reporter(results)
|
||||||
else {
|
else {
|
||||||
|
|
@ -87,38 +87,39 @@ else window.o = m()
|
||||||
if (hasProcess && errCount !== 0) process.exit(1)
|
if (hasProcess && errCount !== 0) process.exit(1)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
}, null))
|
||||||
|
|
||||||
function test(spec, pre, post, finalize) {
|
function test(spec, pre, post, finalize) {
|
||||||
pre = [].concat(pre, spec["__beforeEach"] || [])
|
pre = [].concat(pre, spec["__beforeEach"] || [])
|
||||||
post = [].concat(spec["__afterEach"] || [], post)
|
post = [].concat(spec["__afterEach"] || [], post)
|
||||||
series([].concat(spec["__before"] || [], Object.keys(spec).map(function(key) {
|
series([].concat(spec["__before"] || [], Object.keys(spec).map(function(key) {
|
||||||
return function(done, timeout) {
|
return new Task(function(done, timeout) {
|
||||||
timeout(Infinity)
|
timeout(Infinity)
|
||||||
|
|
||||||
if (key.slice(0, 2) === "__") return done()
|
if (key.slice(0, 2) === "__") return done()
|
||||||
if (only !== null && spec[key] !== only && typeof only === typeof spec[key]) return done()
|
if (only !== null && spec[key].fn !== only && spec[key] instanceof Task) return done()
|
||||||
subjects.push(key)
|
|
||||||
var type = typeof spec[key]
|
|
||||||
if (type === "object") test(spec[key], pre, post, pop)
|
|
||||||
if (type === "function") series([].concat(pre, spec[key], post, pop))
|
|
||||||
|
|
||||||
function pop() {
|
subjects.push(key)
|
||||||
|
var pop = new Task(function pop() {
|
||||||
subjects.pop()
|
subjects.pop()
|
||||||
done()
|
done()
|
||||||
}
|
}, null)
|
||||||
}
|
|
||||||
|
if (spec[key] instanceof Task) series([].concat(pre, spec[key], post, pop))
|
||||||
|
else test(spec[key], pre, post, pop)
|
||||||
|
|
||||||
|
}, null)
|
||||||
}), spec["__after"] || [], finalize))
|
}), spec["__after"] || [], finalize))
|
||||||
}
|
}
|
||||||
|
|
||||||
function series(fns) {
|
function series(tasks) {
|
||||||
var cursor = 0
|
var cursor = 0
|
||||||
next()
|
next()
|
||||||
|
|
||||||
function next() {
|
function next() {
|
||||||
if (cursor === fns.length) return
|
if (cursor === tasks.length) return
|
||||||
|
|
||||||
var fn = fns[cursor++]
|
var task = tasks[cursor++]
|
||||||
|
var fn = task.fn
|
||||||
var timeout = 0, delay = 200, s = new Date
|
var timeout = 0, delay = 200, s = new Date
|
||||||
var isDone = false
|
var isDone = false
|
||||||
|
|
||||||
|
|
@ -142,7 +143,7 @@ else window.o = m()
|
||||||
function startTimer() {
|
function startTimer() {
|
||||||
timeout = setTimeout(function() {
|
timeout = setTimeout(function() {
|
||||||
timeout = undefined
|
timeout = undefined
|
||||||
record("async test timed out")
|
record("async test timed out", task.err)
|
||||||
next()
|
next()
|
||||||
}, Math.min(delay, 2147483647))
|
}, Math.min(delay, 2147483647))
|
||||||
}
|
}
|
||||||
|
|
@ -183,7 +184,7 @@ else window.o = m()
|
||||||
function hook(name) {
|
function hook(name) {
|
||||||
return function(predicate) {
|
return function(predicate) {
|
||||||
if (ctx[name]) throw new Error("This hook should be defined outside of a loop or inside a nested test group:\n" + predicate)
|
if (ctx[name]) throw new Error("This hook should be defined outside of a loop or inside a nested test group:\n" + predicate)
|
||||||
ctx[name] = predicate
|
ctx[name] = new Task(predicate, ensureStackTrace(new Error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,6 +234,7 @@ else window.o = m()
|
||||||
}
|
}
|
||||||
|
|
||||||
function Assert(value) {this.value = value}
|
function Assert(value) {this.value = value}
|
||||||
|
function Task(fn, err) {this.fn = fn, this.err = err}
|
||||||
function define(name, verb, compare) {
|
function define(name, verb, compare) {
|
||||||
Assert.prototype[name] = function assert(value) {
|
Assert.prototype[name] = function assert(value) {
|
||||||
if (compare(this.value, value)) record(null)
|
if (compare(this.value, value)) record(null)
|
||||||
|
|
@ -246,10 +248,7 @@ else window.o = m()
|
||||||
function record(message, error) {
|
function record(message, error) {
|
||||||
var result = {pass: message === null}
|
var result = {pass: message === null}
|
||||||
if (result.pass === false) {
|
if (result.pass === false) {
|
||||||
if (error == null) {
|
if (error == null) error = ensureStackTrace(new Error)
|
||||||
error = new Error
|
|
||||||
if (error.stack === undefined) new function() {try {throw error} catch (e) {error = e}}
|
|
||||||
}
|
|
||||||
result.context = subjects.join(" > ")
|
result.context = subjects.join(" > ")
|
||||||
result.message = message
|
result.message = message
|
||||||
result.error = error
|
result.error = error
|
||||||
|
|
@ -275,7 +274,11 @@ else window.o = m()
|
||||||
function cStyle(color, bold) {
|
function cStyle(color, bold) {
|
||||||
return hasProcess||!color ? "" : "color:"+color+(bold ? ";font-weight:bold" : "")
|
return hasProcess||!color ? "" : "color:"+color+(bold ? ";font-weight:bold" : "")
|
||||||
}
|
}
|
||||||
|
function ensureStackTrace(error) {
|
||||||
|
// mandatory to get a stack in IE 10 and 11 (and maybe other envs?)
|
||||||
|
if (error.stack === undefined) try { throw error } catch(e) {return e}
|
||||||
|
else return error
|
||||||
|
}
|
||||||
o.report = function (results) {
|
o.report = function (results) {
|
||||||
var errCount = 0
|
var errCount = 0
|
||||||
for (var i = 0, r; r = results[i]; i++) {
|
for (var i = 0, r; r = results[i]; i++) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue