From e342805bfbf161573479ffc8e9fcd315beac2108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Yves=20G=C3=A9rardy?= Date: Sat, 26 May 2018 13:42:43 +0200 Subject: [PATCH] [ospec] Add o.defaultTimeout() --- ospec/ospec.js | 36 +++++++----- ospec/tests/test-ospec.js | 114 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 13 deletions(-) diff --git a/ospec/ospec.js b/ospec/ospec.js index eadb4150..56003566 100644 --- a/ospec/ospec.js +++ b/ospec/ospec.js @@ -11,7 +11,8 @@ else window.o = m() __before: true, __beforeEach: true, __after: true, - __afterEach: true + __afterEach: true, + __defaultTimeout: true } if (name != null) spec[name] = ctx = {} @@ -28,6 +29,12 @@ else window.o = m() o.after = hook("__after") o.beforeEach = hook("__beforeEach") o.afterEach = hook("__afterEach") + o.defaultTimeout = function (t) { + if (isRunning()) throw new Error("o.defaultTimeout() can only be called before o.run()") + if (hasOwn.call(ctx, "__defaultTimeout")) throw new Error("A default timeout has already been defined in this context") + if (typeof t !== "number") throw new Error("o.defaultTimeout() expects a number as argument") + ctx.__defaultTimeout = t + } o.new = init o.spec = function(subject, predicate) { var parent = ctx @@ -91,9 +98,10 @@ else window.o = m() if (hasProcess && errCount !== 0) process.exit(1) } }) - }, null)) + }, null), 200 /*default timeout delay*/) - function test(spec, pre, post, finalize) { + function test(spec, pre, post, finalize, defaultDelay) { + if (hasOwn.call(spec, "__defaultTimeout")) defaultDelay = spec.__defaultTimeout pre = [].concat(pre, spec["__beforeEach"] || []) post = [].concat(spec["__afterEach"] || [], post) series([].concat(spec["__before"] || [], Object.keys(spec).reduce(function(tasks, key) { @@ -108,16 +116,16 @@ else window.o = m() done() }, null) - if (spec[key] instanceof Task) series([].concat(pre, spec[key], post, pop)) - else test(spec[key], pre, post, pop) + if (spec[key] instanceof Task) series([].concat(pre, spec[key], post, pop), defaultDelay) + else test(spec[key], pre, post, pop, defaultDelay) }, null)) } return tasks - }, []), spec["__after"] || [], finalize)) + }, []), spec["__after"] || [], finalize), defaultDelay) } - function series(tasks) { + function series(tasks, defaultDelay) { var cursor = 0 next() @@ -127,7 +135,7 @@ else window.o = m() var task = tasks[cursor++] var current = cursor var fn = task.fn - var timeout = 0, delay = 200, s = new Date + var timeout = 0, delay = defaultDelay, s = new Date var arg globalTimeout = setDelay @@ -137,7 +145,6 @@ else window.o = m() function done(err) { 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) } @@ -153,12 +160,13 @@ else window.o = m() function startTimer() { timeout = setTimeout(function() { timeout = undefined - finalizeAsync("async test timed out") + finalizeAsync("async test timed out after " + delay + "ms") }, Math.min(delay, 2147483647)) } - - function setDelay (t) {delay = t} - + 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() arg = (body.match(/\(([\w$]+)/) || body.match(/([\w$]+)\s*=>/) || []).pop() @@ -168,6 +176,7 @@ else window.o = m() } 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 } if (timeout === 0) { @@ -251,6 +260,7 @@ else window.o = m() this.value = value } function Task(fn, err) { + // Tasks defined internally don't have an `err`, and may be created at run-time. if (err != null && isRunning()) throw new Error("Test definitions and hooks shouldn't be nested. To group tests use `o.spec()`") this.fn = fn this.err = err diff --git a/ospec/tests/test-ospec.js b/ospec/tests/test-ospec.js index 2d949a8a..f220d214 100644 --- a/ospec/tests/test-ospec.js +++ b/ospec/tests/test-ospec.js @@ -327,6 +327,120 @@ o.spec("ospec", function() { }) }) }) + o.spec("o.defaultTimeout", function() { + o("throws when called inside of test definitions", function(done) { + var err + var oo = o.new() + oo("", function() { + try { oo.defaultTimeout(5) } catch (e) {err = e} + return {then: function(f) {setTimeout(f)}} + }) + oo.run(function(){ + o(err instanceof Error).equals(true) + + done() + }) + }) + o("works", function(done) { + var oo = o.new() + var t + + oo.defaultTimeout(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("scoped when nested", function(done) { + var oo = o.new() + var t + + oo.defaultTimeout(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.spec("nested 1", function () { + var t + + oo.defaultTimeout(30) + oo.beforeEach(function () { + t = new Date + }) + oo.afterEach(function () { + var diff = new Date - t + o(diff >= 30).equals(true) + o(diff < 200).equals(true) + }) + + oo("", function() { + oo(true).equals(true) + + return {then: function() {}} + }) + }) + + oo("", function() { + oo(true).equals(true) + + return {then: function() {}} + }) + + oo.spec("nested 2", function () { + oo.spec("deeply", function() { + var t + + oo.defaultTimeout(20) + oo.beforeEach(function () { + t = new Date + }) + oo.afterEach(function () { + var diff = new Date - t + o(diff >= 20).equals(true) + o(diff < 200).equals(true) + }) + + oo("", function() { + oo(true).equals(true) + + return {then: function() {}} + }) + }) + }) + oo.run(function(results) { + o(results.length).equals(6) + o(results[0].pass).equals(true) + o(results[1].pass).equals(false) + o(results[2].pass).equals(true) + o(results[3].pass).equals(false) + o(results[4].pass).equals(true) + o(results[5].pass).equals(false) + done() + }) + }) + }) o.spec("calling done() twice throws", function () { o("two successes", function(done) { var oo = o.new()