Merge pull request #1928 from StephanHoyer/ospec-promise-support

support promise return in ospec
This commit is contained in:
Isiah Meadows 2017-08-31 14:52:55 -04:00 committed by GitHub
commit 57b6b516c8
5 changed files with 124 additions and 25 deletions

View file

@ -23,6 +23,11 @@
- API: Introduction of `m.redraw.sync()` ([#1592](https://github.com/MithrilJS/mithril.js/pull/1592))
#### Ospec improvements:
- Added support for async functions and promises in tests - ([#1928](https://github.com/MithrilJS/mithril.js/pull/1928))
- Error handling for async tests with `done` callbacks supports error as first argument
#### Bug fixes
- API: `m.route.set()` causes all mount points to be redrawn ([#1592](https://github.com/MithrilJS/mithril.js/pull/1592))

View file

@ -148,6 +148,22 @@ o("setTimeout calls callback", function(done) {
})
```
Alternativly you can return a promise or even use an async function in tests:
```javascript
o("promise test", function() {
return new Promise(function(resolve) {
setTimeout(resolve, 10)
})
})
```
```javascript
o("promise test", async function() {
await someOtherAsyncFunction()
})
```
By default, asynchronous tests time out after 20ms. This can be changed on a per-test basis using the `timeout` argument:
```javascript
@ -158,7 +174,22 @@ o("setTimeout calls callback", function(done, timeout) {
})
```
Note that the `timeout` function call must be the first statement in its test.
Note that the `timeout` function call must be the first statement in its test. This currently does not work for promise tests. You can combine both methods to do this:
```javascript
o("promise test", function(done, timeout) {
timeout(1000)
someOtherAsyncFunctionThatTakes900ms().then(done)
})
```
```javascript
o("promise test", async function(done, timeout) {
timeout(1000)
await someOtherAsyncFunctionThatTakes900ms()
done()
})
```
Asynchronous tests generate an assertion that succeeds upon calling `done` or fails on timeout with the error message `async test timed out`.

View file

@ -84,40 +84,56 @@ module.exports = new function init(name) {
if (cursor === fns.length) return
var fn = fns[cursor++]
var timeout = 0, delay = 200, s = new Date
var isDone = false
function done(err) {
if (err) {
if (err.message) record(err.message, err)
else record(err)
subjects.pop()
next()
}
if (timeout !== undefined) {
timeout = clearTimeout(timeout)
if (delay !== Infinity) record(null)
if (!isDone) next()
else throw new Error("`" + arg + "()` should only be called once")
isDone = true
}
else console.log("# elapsed: " + Math.round(new Date - s) + "ms, expected under " + delay + "ms")
}
function startTimer() {
timeout = setTimeout(function() {
timeout = undefined
record("async test timed out")
next()
}, Math.min(delay, 2147483647))
}
if (fn.length > 0) {
var timeout = 0, delay = 200, s = new Date
var isDone = false
var body = fn.toString()
var arg = (body.match(/\(([\w$]+)/) || body.match(/([\w$]+)\s*=>/) || []).pop()
if (body.indexOf(arg) === body.lastIndexOf(arg)) throw new Error("`" + arg + "()` should be called at least once")
try {
fn(function done() {
if (timeout !== undefined) {
timeout = clearTimeout(timeout)
if (delay !== Infinity) record(null)
if (!isDone) next()
else throw new Error("`" + arg + "()` should only be called once")
isDone = true
}
else console.log("# elapsed: " + Math.round(new Date - s) + "ms, expected under " + delay + "ms")
}, function(t) {delay = t})
fn(done, function(t) {delay = t})
}
catch (e) {
record(e.message, e)
subjects.pop()
next()
done(e)
}
if (timeout === 0) {
timeout = setTimeout(function() {
timeout = undefined
record("async test timed out")
next()
}, Math.min(delay, 2147483647))
startTimer()
}
}
else {
fn()
nextTickish(next)
var p = fn()
if (p && p.then) {
startTimer()
p.then(function() { done() }, done)
} else {
nextTickish(next)
}
}
}
}

View file

@ -107,7 +107,7 @@ o.spec("ospec", function() {
o(output).deepEquals({tag: "div", children: children})
})
})
o.spec("async", function() {
o.spec("async callback", function() {
var a = 0, b = 0
o.before(function(done) {
@ -148,4 +148,51 @@ o.spec("ospec", function() {
})
})
})
o.spec("async promise", function() {
var a = 0, b = 0
function wrapPromise(fn) {
return new Promise((resolve, reject) => {
callAsync(() => {
try {
fn()
resolve()
} catch(e) {
reject(e)
}
})
})
}
o.before(function() {
return wrapPromise(() => {
a = 1
})
})
o.after(function() {
return wrapPromise(function() {
a = 0
})
})
o.beforeEach(function() {
return wrapPromise(function() {
b = 1
})
})
o.afterEach(function() {
return wrapPromise(function() {
b = 0
})
})
o("promise functions", async function() {
await wrapPromise(function() {
o(a).equals(b)
o(a).equals(1)("a and b should be initialized")
})
})
})
})

View file

@ -131,7 +131,7 @@ o.spec("promise", function() {
callAsync(function() {resolve(promise)})
})
promise.then(null, done)
promise.then(null, () => done())
})
o("non-function onFulfilled is ignored", function(done) {
var promise = Promise.resolve(1)