Merge pull request #2034 from pygy/ospec-umdish
Make Ospec Flems-friendly
This commit is contained in:
commit
956bdc5797
4 changed files with 93 additions and 22 deletions
|
|
@ -56,6 +56,7 @@
|
||||||
- Added support for custom reporters ([#2009](https://github.com/MithrilJS/mithril.js/pull/2020))
|
- Added support for custom reporters ([#2009](https://github.com/MithrilJS/mithril.js/pull/2020))
|
||||||
- Error handling for async tests with `done` callbacks supports error as first argument
|
- Error handling for async tests with `done` callbacks supports error as first argument
|
||||||
- Error messages which include newline characters do not swallow the stack trace [#1495](https://github.com/MithrilJS/mithril.js/issues/1495) ([#1984](https://github.com/MithrilJS/mithril.js/pull/1984), [@ RodericDay](https://github.com/RodericDay))
|
- Error messages which include newline characters do not swallow the stack trace [#1495](https://github.com/MithrilJS/mithril.js/issues/1495) ([#1984](https://github.com/MithrilJS/mithril.js/pull/1984), [@ RodericDay](https://github.com/RodericDay))
|
||||||
|
- Make Ospec more [Flems](https://flems.io)-friendly (#2034)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ Noiseless testing framework
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
- ~180 LOC
|
- ~330 LOC including the CLI runner
|
||||||
- terser and faster test code than with mocha, jasmine or tape
|
- terser and faster test code than with mocha, jasmine or tape
|
||||||
- test code reads like bullet points
|
- test code reads like bullet points
|
||||||
- assertion code follows [SVO](https://en.wikipedia.org/wiki/Subject–verb–object) structure in present tense for terseness and readability
|
- assertion code follows [SVO](https://en.wikipedia.org/wiki/Subject–verb–object) structure in present tense for terseness and readability
|
||||||
|
|
@ -311,7 +311,9 @@ ospec will automatically evaluate all `*.js` files in any folder named `/tests`.
|
||||||
|
|
||||||
Ospec doesn't work when installed globally. Using global scripts is generally a bad idea since you can end up with different, incompatible versions of the same package installed locally and globally.
|
Ospec doesn't work when installed globally. Using global scripts is generally a bad idea since you can end up with different, incompatible versions of the same package installed locally and globally.
|
||||||
|
|
||||||
To work around this limitation, you can use [`npm-run`](https://www.npmjs.com/package/npm-run) which enables one to run the binaries of locally installed packages.
|
If you're using a recent version of npm (v5+), you can use run `npx ospec` from your project folder.
|
||||||
|
|
||||||
|
Otherwise, to work around this limitation, you can use [`npm-run`](https://www.npmjs.com/package/npm-run) which enables one to run the binaries of locally installed packages.
|
||||||
|
|
||||||
```
|
```
|
||||||
npm install npm-run -g
|
npm install npm-run -g
|
||||||
|
|
@ -449,6 +451,13 @@ If running in Node.js, ospec will call `process.exit` after reporting
|
||||||
results by default. If you specify a reporter, ospec will not do this
|
results by default. If you specify a reporter, ospec will not do this
|
||||||
and allow your reporter to respond to results in its own way.
|
and allow your reporter to respond to results in its own way.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Number o.report(results)
|
||||||
|
|
||||||
|
The default reporter used by `o.run()` when none are provided. Returns the number of failures, doesn't exit Node.js by itself. It expects an array of [test result data](#result-data) as argument.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Function o.new()
|
### Function o.new()
|
||||||
|
|
@ -490,7 +499,7 @@ True if the test passed. **No other keys will exist on the result if this value
|
||||||
|
|
||||||
### Error result.error
|
### Error result.error
|
||||||
|
|
||||||
The value of the stack property from the `Error` object explaining the reason behind a failure.
|
The `Error` object explaining the reason behind a failure.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
/* eslint-disable global-require, no-bitwise, no-process-exit */
|
/* eslint-disable global-require, no-bitwise, no-process-exit */
|
||||||
"use strict"
|
"use strict"
|
||||||
|
;(function(m) {
|
||||||
module.exports = new function init(name) {
|
if (typeof module !== "undefined") module["exports"] = m()
|
||||||
var spec = {}, subjects = [], results, only = null, ctx = spec, start, stack = 0, nextTickish, hasProcess = typeof process === "object", reporter, hasOwn = ({}).hasOwnProperty
|
else window.o = m()
|
||||||
|
})(function init(name) {
|
||||||
|
var spec = {}, subjects = [], results, only = null, ctx = spec, start, stack = 0, nextTickish, hasProcess = typeof process === "object", hasOwn = ({}).hasOwnProperty
|
||||||
|
|
||||||
if (name != null) spec[name] = ctx = {}
|
if (name != null) spec[name] = ctx = {}
|
||||||
|
|
||||||
|
try {throw new Error} catch (e) {
|
||||||
|
var ospecFileName = e.stack && (/[\/\\](.*?):\d+:\d+/).test(e.stack) ? e.stack.match(/[\/\\](.*?):\d+:\d+/)[1] : null
|
||||||
|
}
|
||||||
function o(subject, predicate) {
|
function o(subject, predicate) {
|
||||||
if (predicate === undefined) {
|
if (predicate === undefined) {
|
||||||
if (results == null) throw new Error("Assertions should not occur outside test definitions")
|
if (results == null) throw new Error("Assertions should not occur outside test definitions")
|
||||||
|
|
@ -49,14 +54,35 @@ module.exports = new function init(name) {
|
||||||
spy.callCount = 0
|
spy.callCount = 0
|
||||||
return spy
|
return spy
|
||||||
}
|
}
|
||||||
o.cleanStackTrace = function(stack) {
|
o.cleanStackTrace = function(error) {
|
||||||
return stack.match(/^(?:(?!Error|[\/\\]ospec[\/\\]ospec\.js).)*$/gm).pop()
|
// For IE 10+ in quirks mode, and IE 9- in any mode, errors don't have a stack
|
||||||
|
if (error.stack == null) return ""
|
||||||
|
var i = 0, header = error.message ? error.name + ": " + error.message : error.name, stack
|
||||||
|
// some environments add the name and message to the stack trace
|
||||||
|
if (error.stack.indexOf(header) === 0) {
|
||||||
|
stack = error.stack.slice(header.length).split(/\r?\n/)
|
||||||
|
stack.shift() // drop the initial empty string
|
||||||
|
} else {
|
||||||
|
stack = error.stack.split(/\r?\n/)
|
||||||
|
}
|
||||||
|
if (ospecFileName == null) return stack.join("\n")
|
||||||
|
// skip ospec-related entries on the stack
|
||||||
|
while (stack[i].indexOf(ospecFileName) !== -1) i++
|
||||||
|
// now we're in user code
|
||||||
|
return stack[i]
|
||||||
}
|
}
|
||||||
o.run = function(_reporter) {
|
o.run = function(reporter) {
|
||||||
results = []
|
results = []
|
||||||
start = new Date
|
start = new Date
|
||||||
reporter = _reporter
|
test(spec, [], [], function() {
|
||||||
test(spec, [], [], report)
|
setTimeout(function () {
|
||||||
|
if (typeof reporter === "function") reporter(results)
|
||||||
|
else {
|
||||||
|
var errCount = o.report(results)
|
||||||
|
if (hasProcess && errCount !== 0) process.exit(1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
function test(spec, pre, post, finalize) {
|
function test(spec, pre, post, finalize) {
|
||||||
pre = [].concat(pre, spec["__beforeEach"] || [])
|
pre = [].concat(pre, spec["__beforeEach"] || [])
|
||||||
|
|
@ -221,7 +247,8 @@ module.exports = new function init(name) {
|
||||||
}
|
}
|
||||||
result.context = subjects.join(" > ")
|
result.context = subjects.join(" > ")
|
||||||
result.message = message
|
result.message = message
|
||||||
result.error = error.stack
|
result.error = error
|
||||||
|
|
||||||
}
|
}
|
||||||
results.push(result)
|
results.push(result)
|
||||||
}
|
}
|
||||||
|
|
@ -235,16 +262,13 @@ module.exports = new function init(name) {
|
||||||
return hasProcess ? "\x1b[31m" + message + "\x1b[0m" : "%c" + message + "%c "
|
return hasProcess ? "\x1b[31m" + message + "\x1b[0m" : "%c" + message + "%c "
|
||||||
}
|
}
|
||||||
|
|
||||||
function report() {
|
o.report = function (results) {
|
||||||
var status = 0
|
var errCount = 0
|
||||||
|
|
||||||
if (typeof reporter === "function") return reporter(results)
|
|
||||||
|
|
||||||
for (var i = 0, r; r = results[i]; i++) {
|
for (var i = 0, r; r = results[i]; i++) {
|
||||||
if (!r.pass) {
|
if (!r.pass) {
|
||||||
var stackTrace = o.cleanStackTrace(r.error)
|
var stackTrace = o.cleanStackTrace(r.error)
|
||||||
console.error(r.context + ":\n" + highlight(r.message) + (stackTrace ? "\n\n" + stackTrace + "\n\n" : ""), hasProcess ? "" : "color:red", hasProcess ? "" : "color:black")
|
console.error(r.context + ":\n" + highlight(r.message) + (stackTrace ? "\n\n" + stackTrace + "\n\n" : ""), hasProcess ? "" : "color:red", hasProcess ? "" : "color:black")
|
||||||
status = 1
|
errCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(
|
console.log(
|
||||||
|
|
@ -252,10 +276,10 @@ module.exports = new function init(name) {
|
||||||
results.length + " assertions completed in " + Math.round(new Date - start) + "ms, " +
|
results.length + " assertions completed in " + Math.round(new Date - start) + "ms, " +
|
||||||
"of which " + results.filter(function(result){return result.error}).length + " failed"
|
"of which " + results.filter(function(result){return result.error}).length + " failed"
|
||||||
)
|
)
|
||||||
if (hasProcess && status === 1) process.exit(1)
|
return errCount
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hasProcess) {
|
if (hasProcess) {
|
||||||
nextTickish = process.nextTick
|
nextTickish = process.nextTick
|
||||||
} else {
|
} else {
|
||||||
nextTickish = function fakeFastNextTick(next) {
|
nextTickish = function fakeFastNextTick(next) {
|
||||||
|
|
@ -265,4 +289,4 @@ module.exports = new function init(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return o
|
return o
|
||||||
}
|
})
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,43 @@ new function(o) {
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
o("o.report() returns the number of failures", function () {
|
||||||
|
var log = console.log, error = console.error
|
||||||
|
console.log = o.spy()
|
||||||
|
console.error = o.spy()
|
||||||
|
|
||||||
|
function makeError(msg) {try{throw msg ? new Error(msg) : new Error} catch(e){return e}}
|
||||||
|
try {
|
||||||
|
var errCount = o.report([{pass: true}, {pass: true}])
|
||||||
|
|
||||||
|
o(errCount).equals(0)
|
||||||
|
o(console.log.callCount).equals(1)
|
||||||
|
o(console.error.callCount).equals(0)
|
||||||
|
|
||||||
|
errCount = o.report([
|
||||||
|
{pass: false, error: makeError("hey"), message: "hey"}
|
||||||
|
])
|
||||||
|
|
||||||
|
o(errCount).equals(1)
|
||||||
|
o(console.log.callCount).equals(2)
|
||||||
|
o(console.error.callCount).equals(1)
|
||||||
|
|
||||||
|
errCount = o.report([
|
||||||
|
{pass: false, error: makeError("hey"), message: "hey"},
|
||||||
|
{pass: true},
|
||||||
|
{pass: false, error: makeError("ho"), message: "ho"}
|
||||||
|
])
|
||||||
|
|
||||||
|
o(errCount).equals(2)
|
||||||
|
o(console.log.callCount).equals(3)
|
||||||
|
o(console.error.callCount).equals(3)
|
||||||
|
} catch (e) {
|
||||||
|
o(1).equals(0)("Error while testing the reporter")
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log = log
|
||||||
|
console.error = error
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}(o)
|
}(o)
|
||||||
|
|
||||||
|
|
@ -188,7 +225,7 @@ o.spec("ospec", function() {
|
||||||
try {
|
try {
|
||||||
throw new Error("line\nbreak")
|
throw new Error("line\nbreak")
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
var trace = o.cleanStackTrace(error.stack)
|
var trace = o.cleanStackTrace(error)
|
||||||
o(trace).notEquals("break")
|
o(trace).notEquals("break")
|
||||||
o(trace.includes("test-ospec.js")).equals(true)
|
o(trace.includes("test-ospec.js")).equals(true)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue