Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ospec

Package Overview
Dependencies
Maintainers
3
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ospec - npm Package Compare versions

Comparing version 2.1.0 to 3.0.0

25

change-log.md

@@ -5,5 +5,28 @@ # Change Log for ospec

## Upcoming...
_2018-xx-yy_
<!-- Add new lines here. Version number will be decided later -->
## 3.0.0
_2018-06-20_
### Breaking
- Better input checking to prevent misuses of the library. Misues of the library will now throw errors, rather than report failures. This may uncover bugs in your test suites. Since it is potentially a disruptive update this change triggers a semver major bump. ([#2167](https://github.com/MithrilJS/mithril.js/pull/2167))
- Change the reserved character for hooks and test suite meta-information from `"__"` to `"\x01"`. Tests whose name start with `"\0x01"` will be rejected ([#2167](https://github.com/MithrilJS/mithril.js/pull/2167))
### Features
>>>>>>> [ospec/bin] Back to ES5 (and complimentary cleanup), fix #2160
- Give async timeout a stack trace that points to the problematic test ([#2154](https://github.com/MithrilJS/mithril.js/pull/2154) [@gilbert](github.com/gilbert), [#2167](https://github.com/MithrilJS/mithril.js/pull/2167))
- deprecate the `timeout` parameter in async tests in favour of `o.timeout()` for setting the timeout delay. The `timeout` parameter still works for v3, and will be removed in v4 ([#2167](https://github.com/MithrilJS/mithril.js/pull/2167))
- add `o.defaultTimeout()` for setting the the timeout delay for the current spec and its children ([#2167](https://github.com/MithrilJS/mithril.js/pull/2167))
- adds the possibility to select more than one test with o.only ([#2171](https://github.com/MithrilJS/mithril.js/pull/2171))
### Bug fixes
- Detect duplicate calls to `done()` properly [#2162](https://github.com/MithrilJS/mithril.js/issues/2162) ([#2167](https://github.com/MithrilJS/mithril.js/pull/2167))
- Don't try to report internal errors as assertion failures, throw them instead ([#2167](https://github.com/MithrilJS/mithril.js/pull/2167))
- Don't ignore, silently, tests whose name start with the test suite meta-information sequence (was `"__"` up to this version) ([#2167](https://github.com/MithrilJS/mithril.js/pull/2167))
- Fix the `done()` call detection logic [#2158](https://github.com/MithrilJS/mithril.js/issues/2158) and assorted fixes (accept non-English names, tolerate comments) ([#2167](https://github.com/MithrilJS/mithril.js/pull/2167))
- Catch exceptions thrown in synchronous tests and report them as assertion failures ([#2171](https://github.com/MithrilJS/mithril.js/pull/2171))
- Fix a stack overflow when using `o.only()` with a large test suite ([#2171](https://github.com/MithrilJS/mithril.js/pull/2171))
## 2.1.0
_2018-05-25_
### Features
- Pinpoint the `o.only()` call site ([#2157](https://github.com/MithrilJS/mithril.js/pull/2157))

@@ -10,0 +33,0 @@ - Improved wording, spacing and color-coding of report messages and errors ([#2147](https://github.com/MithrilJS/mithril.js/pull/2147), [@maranomynet](https://github.com/maranomynet))

248

ospec.js

@@ -1,2 +0,1 @@

/* eslint-disable global-require, no-bitwise, no-process-exit */
"use strict"

@@ -7,24 +6,29 @@ ;(function(m) {

})(function init(name) {
var spec = {}, subjects = [], results, only = null, ctx = spec, start, stack = 0, nextTickish, hasProcess = typeof process === "object", hasOwn = ({}).hasOwnProperty
var spec = {}, subjects = [], results, only = [], ctx = spec, start, stack = 0, nextTickish, hasProcess = typeof process === "object", hasOwn = ({}).hasOwnProperty
var ospecFileName = getStackName(ensureStackTrace(new Error), /[\/\\](.*?):\d+:\d+/), timeoutStackName
var globalTimeout = noTimeoutRightNow
var currentTestError = null
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) {
if (predicate === undefined) {
if (results == null) throw new Error("Assertions should not occur outside test definitions")
if (!isRunning()) throw new Error("Assertions should not occur outside test definitions")
return new Assert(subject)
}
else if (results == null) {
ctx[unique(subject)] = predicate
} else {
throw new Error("Test definition shouldn't be nested. To group tests use `o.spec()`")
if (isRunning()) throw new Error("Test definitions and hooks shouldn't be nested. To group tests use `o.spec()`")
subject = String(subject)
if (subject.charCodeAt(0) === 1) throw new Error("test names starting with '\\x01' are reserved for internal use")
ctx[unique(subject)] = new Task(predicate, ensureStackTrace(new Error))
}
}
o.before = hook("__before")
o.after = hook("__after")
o.beforeEach = hook("__beforeEach")
o.afterEach = hook("__afterEach")
o.before = hook("\x01before")
o.after = hook("\x01after")
o.beforeEach = hook("\x01beforeEach")
o.afterEach = hook("\x01afterEach")
o.specTimeout = function (t) {
if (isRunning()) throw new Error("o.specTimeout() can only be called before o.run()")
if (hasOwn.call(ctx, "\x01specTimeout")) throw new Error("A default timeout has already been defined in this context")
if (typeof t !== "number") throw new Error("o.specTimeout() expects a number as argument")
ctx["\x01specTimeout"] = t
}
o.new = init

@@ -38,9 +42,8 @@ o.spec = function(subject, predicate) {

o.only = function(subject, predicate, silent) {
if (!silent) {
console.log(highlight("/!\\ WARNING /!\\ o.only() mode"))
try {throw new Error} catch (e) {
console.log(this.cleanStackTrace(e) + "\n")
}
}
o(subject, only = predicate)
if (!silent) console.log(
highlight("/!\\ WARNING /!\\ o.only() mode") + "\n" + o.cleanStackTrace(ensureStackTrace(new Error)) + "\n",
cStyle("red"), ""
)
only.push(predicate)
o(subject, predicate)
}

@@ -77,42 +80,42 @@ o.spy = function(fn) {

// skip ospec-related entries on the stack
while (stack[i].indexOf(ospecFileName) !== -1) i++
// now we're in user code
while (stack[i] != null && stack[i].indexOf(ospecFileName) !== -1) i++
// now we're in user code (or past the stack end)
return stack[i]
}
o.timeout = function(n) {
globalTimeout(n)
}
o.run = function(reporter) {
results = []
start = new Date
test(spec, [], [], function() {
test(spec, [], [], new Task(function() {
setTimeout(function () {
timeoutStackName = getStackName({stack: o.cleanStackTrace(ensureStackTrace(new Error))}, /([\w \.]+?:\d+:\d+)/)
if (typeof reporter === "function") reporter(results)
else {
var errCount = o.report(results)
if (hasProcess && errCount !== 0) process.exit(1)
if (hasProcess && errCount !== 0) process.exit(1) // eslint-disable-line no-process-exit
}
})
})
}, null), 200 /*default timeout delay*/)
function test(spec, pre, post, finalize) {
pre = [].concat(pre, spec["__beforeEach"] || [])
post = [].concat(spec["__afterEach"] || [], post)
series([].concat(spec["__before"] || [], Object.keys(spec).map(function(key) {
return function(done, timeout) {
timeout(Infinity)
if (key.slice(0, 2) === "__") return done()
if (only !== null && spec[key] !== only && typeof only === typeof spec[key]) 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.pop()
done()
}
function test(spec, pre, post, finalize, defaultDelay) {
if (hasOwn.call(spec, "\x01specTimeout")) defaultDelay = spec["\x01specTimeout"]
pre = [].concat(pre, spec["\x01beforeEach"] || [])
post = [].concat(spec["\x01afterEach"] || [], post)
series([].concat(spec["\x01before"] || [], Object.keys(spec).reduce(function(tasks, key) {
if (key.charCodeAt(0) !== 1 && (only.length === 0 || only.indexOf(spec[key].fn) !== -1 || !(spec[key] instanceof Task))) {
tasks.push(new Task(function(done) {
o.timeout(Infinity)
subjects.push(key)
var pop = new Task(function pop() {subjects.pop(), done()}, null)
if (spec[key] instanceof Task) series([].concat(pre, spec[key], post, pop), defaultDelay)
else test(spec[key], pre, post, pop, defaultDelay)
}, null))
}
}), spec["__after"] || [], finalize))
return tasks
}, []), spec["\x01after"] || [], finalize), defaultDelay)
}
function series(fns) {
function series(tasks, defaultDelay) {
var cursor = 0

@@ -122,42 +125,57 @@ next()

function next() {
if (cursor === fns.length) return
if (cursor === tasks.length) return
var fn = fns[cursor++]
var timeout = 0, delay = 200, s = new Date
var task = tasks[cursor++]
var fn = task.fn
currentTestError = task.err
var timeout = 0, delay = defaultDelay, s = new Date
var current = cursor
var arg
globalTimeout = setDelay
var isDone = false
// public API, may only be called once from use code (or after returned Promise resolution)
function done(err) {
if (err) {
if (err instanceof Error) record(err.message, err)
else record(String(err))
subjects.pop()
next()
if (!isDone) isDone = true
else throw new Error("`" + arg + "()` should only be called once")
if (timeout === undefined) console.warn("# elapsed: " + Math.round(new Date - s) + "ms, expected under " + delay + "ms\n" + o.cleanStackTrace(task.err))
finalizeAsync(err)
}
// for internal use only
function finalizeAsync(err) {
if (err == null) {
if (task.err != null) succeed(new Assert)
} else {
if (err instanceof Error) fail(new Assert, err.message, err)
else fail(new Assert, String(err), null)
}
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")
if (timeout !== undefined) timeout = clearTimeout(timeout)
if (current === cursor) next()
}
function startTimer() {
timeout = setTimeout(function() {
timeout = undefined
record("async test timed out")
next()
finalizeAsync("async test timed out after " + delay + "ms")
}, Math.min(delay, 2147483647))
}
function setDelay (t) {
if (typeof t !== "number") throw new Error("timeout() and o.timeout() expect a number as argument")
delay = t
}
if (fn.length > 0) {
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")
arg = (body.match(/^(.+?)(?:\s|\/\*[\s\S]*?\*\/|\/\/.*?\n)*=>/) || body.match(/\((?:\s|\/\*[\s\S]*?\*\/|\/\/.*?\n)*(.+?)(?:\s|\/\*[\s\S]*?\*\/|\/\/.*?\n)*[,\)]/) || []).pop()
if (body.indexOf(arg) === body.lastIndexOf(arg)) {
var e = new Error
e.stack = "`" + arg + "()` should be called at least once\n" + o.cleanStackTrace(task.err)
throw e
}
try {
fn(done, function(t) {delay = t})
fn(done, setDelay)
}
catch (e) {
done(e)
if (task.err != null) finalizeAsync(e)
// The errors of internal tasks (which don't have an Err) are ospec bugs and must be rethrown.
else throw e
}

@@ -167,12 +185,18 @@ if (timeout === 0) {

}
}
else {
var p = fn()
if (p && p.then) {
startTimer()
p.then(function() { done() }, done)
} else {
nextTickish(next)
} else {
try{
var p = fn()
if (p && p.then) {
startTimer()
p.then(function() { done() }, done)
} else {
nextTickish(next)
}
} catch (e) {
if (task.err != null) finalizeAsync(e)
// The errors of internal tasks (which don't have an Err) are ospec bugs and must be rethrown.
else throw e
}
}
globalTimeout = noTimeoutRightNow
}

@@ -191,3 +215,3 @@ }

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))
}

@@ -209,3 +233,3 @@ }

if (a === b) return true
if (a === null ^ b === null || a === undefined ^ b === undefined) return false
if (a === null ^ b === null || a === undefined ^ b === undefined) return false // eslint-disable-line no-bitwise
if (typeof a === "object" && typeof b === "object") {

@@ -242,29 +266,33 @@ var aIsArgs = isArguments(a), bIsArgs = isArguments(b)

function Assert(value) {this.value = value}
function isRunning() {return results != null}
function Assert(value) {
this.value = value
this.i = results.length
results.push({pass: null, context: "", message: "Incomplete assertion in the test definition starting at...", error: currentTestError, testError: currentTestError})
}
function Task(fn, err) {
this.fn = fn
this.err = err
}
function define(name, verb, compare) {
Assert.prototype[name] = function assert(value) {
if (compare(this.value, value)) record(null)
else record(serialize(this.value) + "\n " + verb + "\n" + serialize(value))
if (compare(this.value, value)) succeed(this)
else fail(this, serialize(this.value) + "\n " + verb + "\n" + serialize(value))
var self = this
return function(message) {
var result = results[results.length - 1]
result.message = message + "\n\n" + result.message
if (!self.pass) self.message = message + "\n\n" + self.message
}
}
}
function record(message, error) {
var result = {pass: message === null}
if (result.pass === false) {
if (error == null) {
error = new Error
if (error.stack === undefined) new function() {try {throw error} catch (e) {error = e}}
}
result.context = subjects.join(" > ")
result.message = message
result.error = error
}
results.push(result)
function succeed(assertion) {
results[assertion.i].pass = true
}
function fail(assertion, message, error) {
results[assertion.i].pass = false
results[assertion.i].context = subjects.join(" > ")
results[assertion.i].message = message
results[assertion.i].error = error != null ? error : ensureStackTrace(new Error)
}
function serialize(value) {
if (hasProcess) return require("util").inspect(value)
if (hasProcess) return require("util").inspect(value) // eslint-disable-line global-require
if (value === null || (typeof value === "object" && !(value instanceof Array)) || typeof value === "number") return String(value)

@@ -274,2 +302,5 @@ else if (typeof value === "function") return value.name || "<anonymous function>"

}
function noTimeoutRightNow() {
throw new Error("o.timeout must be called snchronously from within a test definition or a hook")
}
var colorCodes = {

@@ -287,2 +318,10 @@ red: "31m",

}
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
}
function getStackName(e, exp) {
return e.stack && exp.test(e.stack) ? e.stack.match(exp)[1] : null
}

@@ -292,4 +331,11 @@ o.report = function (results) {

for (var i = 0, r; r = results[i]; i++) {
if (r.pass == null) {
r.testError.stack = r.message + "\n" + o.cleanStackTrace(r.testError)
r.testError.message = r.message
throw r.testError
}
if (!r.pass) {
var stackTrace = o.cleanStackTrace(r.error)
var couldHaveABetterStackTrace = !stackTrace || timeoutStackName != null && stackTrace.indexOf(timeoutStackName) !== -1
if (couldHaveABetterStackTrace) stackTrace = r.testError != null ? o.cleanStackTrace(r.testError) : r.error.stack || ""
console.error(

@@ -296,0 +342,0 @@ (hasProcess ? "\n" : "") +

{
"name": "ospec",
"version": "2.1.0",
"version": "3.0.0",
"description": "Noiseless testing framework",

@@ -5,0 +5,0 @@ "main": "ospec.js",

@@ -167,18 +167,43 @@ ospec [![NPM Version](https://img.shields.io/npm/v/ospec.svg)](https://www.npmjs.com/package/ospec) [![NPM License](https://img.shields.io/npm/l/ospec.svg)](https://www.npmjs.com/package/ospec)

By default, asynchronous tests time out after 20ms. This can be changed on a per-test basis using the `timeout` argument:
#### Timeout delays
By default, asynchronous tests time out after 200ms. You can change that default for the current test suite and
its children by using the `o.specTimeout(delay)` function.
```javascript
o.spec("a spec that must timeout quickly", function(done, timeout) {
// wait 20ms before bailing out of the tests of this suite and
// its descendants
o.specTimeout(20)
o("some test", function(done) {
setTimeout(done, 10) // this will pass
})
o.spec("a child suite where the delay also applies", function () {
o("some test", function(done) {
setTimeout(done, 30) // this will time out.
})
})
})
o.spec("a spec that uses the default delay", function() {
// ...
})
```
This can also be changed on a per-test basis using the `o.timeout(delay)` function from within a test:
```javascript
o("setTimeout calls callback", function(done, timeout) {
timeout(50) //wait 50ms before bailing out of the test
o.timeout(500) //wait 500ms before bailing out of the test
setTimeout(done, 30)
setTimeout(done, 300)
})
```
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:
Note that the `o.timeout` function call must be the first statement in its test. It also works with Promise-returning tests:
```javascript
o("promise test", function(done, timeout) {
timeout(1000)
someOtherAsyncFunctionThatTakes900ms().then(done)
o("promise test", function() {
o.timeout(1000)
return someOtherAsyncFunctionThatTakes900ms()
})

@@ -188,6 +213,5 @@ ```

```javascript
o("promise test", async function(done, timeout) {
timeout(1000)
o("promise test", async function() {
o.timeout(1000)
await someOtherAsyncFunctionThatTakes900ms()
done()
})

@@ -252,8 +276,9 @@ ```

### Running only one test
### Running only some tests
A test can be temporarily made to run exclusively by calling `o.only()` instead of `o`. This is useful when troubleshooting regressions, to zero-in on a failing test, and to avoid saturating console log w/ irrelevant debug information.
One or more tests can be temporarily made to run exclusively by calling `o.only()` instead of `o`. This is useful when troubleshooting regressions, to zero-in on a failing test, and to avoid saturating console log w/ irrelevant debug information.
```javascript
o.spec("math", function() {
// will not run
o("addition", function() {

@@ -263,6 +288,16 @@ o(1 + 1).equals(2)

//only this test will be run, regardless of how many groups there are
// this test will be run, regardless of how many groups there are
o.only("subtraction", function() {
o(1 - 1).notEquals(2)
})
// will not run
o("multiplication", function() {
o(2 * 2).equals(4)
})
// this test will be run, regardless of how many groups there are
o.only("division", function() {
o(6 / 2).notEquals(2)
})
})

@@ -542,5 +577,7 @@ ```

### Boolean result.pass
### Boolean|Null result.pass
True if the test passed. **No other keys will exist on the result if this value is true.**
- `true` if the assertion passed.
- `false` if the assertion failed.
- `null` if the assertion was incomplete (`o("partial assertion) // and that's it`).

@@ -551,6 +588,12 @@ ---

The `Error` object explaining the reason behind a failure.
The `Error` object explaining the reason behind a failure. If the assertion failed, the stack will point to the actuall error. If the assertion did pass or was incomplete, this field is identical to `result.testError`.
---
### Error result.testError
An `Error` object whose stack points to the test definition that wraps the assertion. Useful as a fallback because in some async cases the main may not point to test code.
---
### String result.message

@@ -580,3 +623,3 @@

A `>`-separated string showing the structure of the test specification.
In case of failure, a `>`-separated string showing the structure of the test specification.
In the below example, `result.context` would be `testing > rocks`.

@@ -583,0 +626,0 @@

@@ -6,91 +6,138 @@ "use strict"

new function(o) {
o = o.new()
o.spec("ospec", function() {
o("skipped", function() {
o(true).equals(false)
// this throws an async error that can't be caught in browsers
if (typeof process !== "undefined") {
o("incomplete assertion", function(done) {
var stackMatcher = /([\w\.\\\/\-]+):(\d+):/
// /!\ this test relies on the `new Error` expression being six lines
// above the `oo("test", function(){...})` call.
var matches = (new Error).stack.match(stackMatcher)
if (matches != null) {
var name = matches[1]
var num = Number(matches[2])
}
var oo = o.new()
oo("test", function() {
oo("incomplete")
})
o.only(".only()", function() {
o(2).equals(2)
}, true)
oo.run(function(results) {
o(results.length).equals(1)
o(results[0].message).equals("Incomplete assertion in the test definition starting at...")
o(results[0].pass).equals(null)
var stack = o.cleanStackTrace(results[0].testError)
var matches2 = stack && stack.match(stackMatcher)
if (matches != null && matches2 != null) {
o(matches[1]).equals(name)
o(Number(matches2[2])).equals(num + 6)
}
done()
})
})
}
o.run()
}(o)
o("o.only", function(done) {
var oo = o.new()
new function(o) {
var clone = o.new()
clone.spec("clone", function() {
clone("fail", function() {
clone(true).equals(false)
oo.spec("won't run", function() {
oo("nope, skipped", function() {
o(true).equals(false)
})
})
clone("pass", function() {
clone(true).equals(true)
oo.spec("ospec", function() {
oo("skipped as well", function() {
oo(true).equals(false)
})
oo.only(".only()", function() {
oo(2).equals(2)
}, true)
oo.only("another .only()", function(done) {
done("that fails")
}, true)
})
// Predicate test passing on clone results
o.spec("reporting", function() {
o("reports per instance", function(done, timeout) {
timeout(100) // Waiting on clone
oo.run(function(results){
o(results.length).equals(2)
o(results[0].pass).equals(true)
o(results[1].pass).equals(false)
clone.run(function(results) {
o(typeof results).equals("object")
o("length" in results).equals(true)
o(results.length).equals(2)("Two results")
done()
})
})
o("error" in results[0] && "pass" in results[0]).equals(true)("error and pass keys present in failing result")
o(!("error" in results[1]) && "pass" in results[1]).equals(true)("only pass key present in passing result")
o(results[0].pass).equals(false)("Test meant to fail has failed")
o(results[1].pass).equals(true)("Test meant to pass has passed")
// Predicate test passing on clone results
o.spec("reporting", function() {
var oo
o.beforeEach(function(){
oo = o.new()
done()
oo.spec("clone", function() {
oo("fail", function() {
oo(true).equals(false)
})
oo("pass", function() {
oo(true).equals(true)
})
})
o("o.report() returns the number of failures", function () {
var log = console.log, error = console.error
console.log = o.spy()
console.error = o.spy()
})
o("reports per instance", function(done, timeout) {
timeout(100) // Waiting on clone
function makeError(msg) {try{throw msg ? new Error(msg) : new Error} catch(e){return e}}
try {
var errCount = o.report([{pass: true}, {pass: true}])
oo.run(function(results) {
o(typeof results).equals("object")
o("length" in results).equals(true)
o(results.length).equals(2)("Two results")
o(errCount).equals(0)
o(console.log.callCount).equals(1)
o(console.error.callCount).equals(0)
o("error" in results[0] && "pass" in results[0]).equals(true)("error and pass keys present in failing result")
o(results[0].pass).equals(false)("Test meant to fail has failed")
o(results[1].pass).equals(true)("Test meant to pass has passed")
errCount = o.report([
{pass: false, error: makeError("hey"), message: "hey"}
])
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()
o(errCount).equals(1)
o(console.log.callCount).equals(2)
o(console.error.callCount).equals(1)
function makeError(msg) {try{throw msg ? new Error(msg) : new Error} catch(e){return e}}
try {
var errCount = o.report([{pass: true}, {pass: true}])
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")
}
o(errCount).equals(0)
o(console.log.callCount).equals(1)
o(console.error.callCount).equals(0)
console.log = log
console.error = error
})
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.spec("ospec", function() {
o.spec("sync", function() {
var a = 0, b = 0, illegalAssertionThrows = false
var reservedTestNameTrows = false

@@ -104,2 +151,3 @@ o.before(function() {a = 1})

try {o("illegal assertion")} catch (e) {illegalAssertionThrows = true}
try {o("\x01reserved test name", function(){})} catch (e) {reservedTestNameTrows = true}

@@ -112,2 +160,3 @@ o("assertions", function() {

o(nestedTestDeclarationThrows).equals(true)
o(reservedTestNameTrows).equals(true)

@@ -186,42 +235,361 @@ var spy = o.spy()

var a = 0, b = 0
o.after(function() {
o(a).equals(0)
o(b).equals(0)
})
o.spec("", function(){
o.before(function(done) {
callAsync(function() {
a = 1
done()
})
})
o.after(function(done) {
callAsync(function() {
a = 0
done()
})
})
o.before(function(done) {
callAsync(function() {
a = 1
o.beforeEach(function(done) {
o(b).equals(0)
callAsync(function() {
b = 1
done()
})
})
o.afterEach(function(done) {
callAsync(function() {
b = 0
done()
})
})
o("hooks work as intended the first time", function(done) {
callAsync(function() {
var spy = o.spy()
spy(a)
o(a).equals(1)
o(b).equals(1)
done()
})
})
o("hooks work as intended the second time", function(done) {
callAsync(function() {
var spy = o.spy()
spy(a)
o(a).equals(1)
o(b).equals(1)
done()
})
})
})
})
o.spec("throwing in test context is recoreded as a failure", function() {
var oo
o.beforeEach(function(){oo = o.new()})
o.afterEach(function() {
oo.run(function(results) {
o(results.length).equals(1)
o(results[0].pass).equals(false)
})
})
o("sync test", function() {
oo("throw in sync test", function() {throw new Error})
})
o("async test", function() {
oo("throw in async test", function(done) {
throw new Error
done() // eslint-disable-line no-unreachable
})
})
})
o.spec("timeout", function () {
o("when using done()", function(done) {
var oo = o.new()
var err
// the success of this test is dependent on having the
// oo() call three linew below this one
try {throw new Error} catch(e) {err = e}
if (err.stack) {
var line = Number(err.stack.match(/:(\d+):/)[1])
oo("", function(oodone, timeout) {
// oodone() keep this line for now
timeout(1)
})
oo.run((function(results) {
o(results.length).equals(1)
o(results[0].pass).equals(false)
// todo test cleaned up results[0].error stack trace for the presence
// of the timeout stack entry
o(results[0].testError instanceof Error).equals(true)
o(o.cleanStackTrace(results[0].testError).indexOf("test-ospec.js:" + (line + 3) + ":")).notEquals(-1)
done()
}))
} else {
done()
}
})
o("when using a thenable", function(done) {
var oo = o.new()
var err
// the success of this test is dependent on having the
// oo() call three linew below this one
try {throw new Error} catch(e) {err = e}
if (err.stack) {
var line = Number(err.stack.match(/:(\d+):/)[1])
oo("", function() {
oo.timeout(1)
return {then: function(){}}
})
oo.run((function(results) {
o(results.length).equals(1)
o(results[0].pass).equals(false)
o(results[0].testError instanceof Error).equals(true)
o(o.cleanStackTrace(results[0].testError).indexOf("test-ospec.js:" + (line + 3) + ":")).notEquals(-1)
done()
}))
} else {
done()
}
})
})
o.spec("o.timeout", function() {
o("throws when called out of test definitions", function(done) {
var oo = o.new()
var count = 0
try { oo.timeout(1) } catch (e) { count++ }
oo.spec("a spec", function() {
try { oo.timeout(1) } catch (e) { count++ }
})
oo("", function() {
oo.timeout(30)
return {then: function(f) {setTimeout(f)}}
})
oo.run(function(){
o(count).equals(2)
done()
})
})
o.after(function(done) {
callAsync(function() {
a = 0
o("works", function(done) {
var oo = o.new()
var t = new Date
oo("", function() {
oo.timeout(10)
return {then: function() {}}
})
oo.run(function(){
o(new Date - t >= 10).equals(true)
o(200 > new Date - t).equals(true)
done()
})
})
})
o.spec("o.specTimeout", function() {
o("throws when called inside of test definitions", function(done) {
var err
var oo = o.new()
oo("", function() {
try { oo.specTimeout(5) } catch (e) {err = e}
return {then: function(f) {setTimeout(f)}}
})
oo.run(function(){
o(err instanceof Error).equals(true)
o.beforeEach(function(done) {
callAsync(function() {
b = 1
done()
})
})
o.afterEach(function(done) {
callAsync(function() {
b = 0
o("works", function(done) {
var oo = o.new()
var t
oo.specTimeout(10)
oo.beforeEach(function () {
t = new Date
})
oo.afterEach(function () {
var diff = new Date - t
o(diff >= 10).equals(true)
o(diff < 200).equals(true)
})
oo("", function() {
oo(true).equals(true)
return {then: function() {}}
})
oo.run(function(results) {
o(results.length).equals(2)
o(results[0].pass).equals(true)
o(results[1].pass).equals(false)
done()
})
})
o("The parent and sibling suites are not affected by the specTimeout", function(done) {
var oo = o.new()
var t
o("async hooks", function(done) {
callAsync(function() {
var spy = o.spy()
spy(a)
oo.specTimeout(50)
oo.beforeEach(function () {
t = new Date
})
oo.afterEach(function () {
var diff = new Date - t
o(diff >= 50).equals(true)
o(diff < 80).equals(true)
})
o(a).equals(b)
o(a).equals(1)("a and b should be initialized")
oo.spec("nested 1", function () {
oo.specTimeout(80)
})
oo("", function() {
oo(true).equals(true)
return {then: function() {}}
})
oo.spec("nested 2", function () {
oo.specTimeout(80)
})
oo.spec("nested 3", function () {
oo("", function() {
oo(true).equals(true)
return {then: function() {}}
})
})
oo.run(function(results) {
o(results.length).equals(4)
o(results[0].pass).equals(true)
o(results[1].pass).equals(false)
o(results[2].pass).equals(true)
o(results[3].pass).equals(false)
done()
})
})
o("nested suites inherit the specTimeout", function(done) {
var oo = o.new()
oo.specTimeout(50)
oo.spec("nested", function () {
oo.spec("deeply", function() {
var t
oo.beforeEach(function () {
t = new Date
})
oo.afterEach(function () {
var diff = new Date - t
o(diff >= 50).equals(true)
o(diff < 80).equals(true)
})
oo("", function() {
oo(true).equals(true)
return {then: function() {}}
})
})
})
oo.run(function(results) {
o(results.length).equals(2)
o(results[0].pass).equals(true)
o(results[1].pass).equals(false)
done()
})
})
})
o.spec("calling done() twice throws", function () {
o("two successes", function(done) {
var oo = o.new()
var err = null
oo("foo", function(oodone) {
try {
oodone()
oodone()
} catch (e) {
err = e
}
o(err instanceof Error).equals(true)
o(err.message).equals("`oodone()` should only be called once")
})
oo.run(function(results) {
o(results.length).equals(1)
o(results[0].pass).equals(true)
done()
})
})
o("a success followed by an error", function(done) {
var oo = o.new()
var err = null
oo("foo", function(oodone) {
try {
oodone()
oodone("error")
} catch (e) {
err = e
}
o(err instanceof Error).equals(true)
o(err.message).equals("`oodone()` should only be called once")
})
oo.run(function(results) {
o(results.length).equals(1)
o(results[0].pass).equals(true)
done()
})
})
o("two errors", function(done) {
var oo = o.new()
var err = null
oo("foo", function(oodone) {
try {
oodone("bar")
oodone("baz")
} catch (e) {
err = e
}
o(err instanceof Error).equals(true)
o(err.message).equals("`oodone()` should only be called once")
})
oo.run(function(results) {
o(results.length).equals(1)
o(results[0].pass).equals(false)
o(results[0].message).equals("bar")
done()
})
})
o("an error followed by a success", function(done) {
var oo = o.new()
var err = null
oo("foo", function(oodone) {
try {
oodone("bar")
oodone()
} catch (e) {
err = e
}
o(err instanceof Error).equals(true)
o(err.message).equals("`oodone()` should only be called once")
})
oo.run(function(results) {
o(results.length).equals(1)
o(results[0].pass).equals(false)
o(results[0].message).equals("bar")
done()
})
})
})
o.spec("stack trace cleaner", function() {

@@ -234,3 +602,3 @@ o("handles line breaks", function() {

o(trace).notEquals("break")
o(trace.includes("test-ospec.js")).equals(true)
o(trace.indexOf("test-ospec.js") !== -1).equals(true)
}

@@ -287,1 +655,77 @@ })

})
o.spec("the done parser", function() {
o("accepts non-English names", function() {
var oo = o.new()
var threw = false
oo("test", function(完了) {
oo(true).equals(true)
完了()
})
try {oo.run(function(){})} catch(e) {threw = true}
o(threw).equals(false)
})
o("tolerates comments", function() {
var oo = o.new()
var threw = false
oo("test", function(/*hey
*/ /**/ //ho
done /*hey
*/ /**/ //huuu
, timeout
) {
timeout(5)
oo(true).equals(true)
done()
})
try {oo.run(function(){})} catch(e) {threw = true}
o(threw).equals(false)
})
/*eslint-disable no-eval*/
try {eval("(()=>{})()"); o.spec("with ES6 arrow functions", function() {
function getCommentContent(f) {
f = f.toString()
return f.slice(f.indexOf("/*") + 2, f.lastIndexOf("*/"))
}
o("has no false positives 1", function(){
var oo = o.new()
var threw = false
eval(getCommentContent(function(){/*
oo(
'Async test parser mistakenly identified 1st token after a parens to be `done` reference',
done => {
oo(threw).equals(false)
done()
}
)
*/}))
try {oo.run(function(){})} catch(e) {threw = true}
o(threw).equals(false)
})
o("has no false negatives", function(){
var oo = o.new()
var threw = false
eval(getCommentContent(function(){/*
oo(
"Multiple references to the wrong thing doesn't fool the checker",
done => {
oo(threw).equals(false)
oo(threw).equals(false)
}
)
*/}))
try {oo.run(function(){})} catch(e) {threw = true}
o(threw).equals(true)
})
o("isn't fooled by comments", function(){
var oo = o.new()
var threw = false
oo(
"comments won't throw the parser off",
eval("done /*hey*/ /**/ => {oo(threw).equals(false);done()}")
)
try {oo.run(function(){})} catch(e) {threw = true}
o(threw).equals(false)
})
})} catch (e) {/*ES5 env, or no eval, ignore*/}
/*eslint-enable no-eval*/
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc