diff --git a/index.js b/index.js index 7a7211e8..288ce9a8 100644 --- a/index.js +++ b/index.js @@ -1,181 +1,3 @@ 'use strict'; -var defined = require('defined'); -var createDefaultStream = require('./lib/default_stream'); -var Test = require('./lib/test'); -var createResult = require('./lib/results'); -var through = require('@ljharb/through'); - -var canEmitExit = typeof process !== 'undefined' && process - && typeof process.on === 'function' && process.browser !== true; -var canExit = typeof process !== 'undefined' && process - && typeof process.exit === 'function'; - -module.exports = (function () { - var wait = false; - var harness; - - function getHarness(opts) { - if (!opts) { opts = {}; } - opts.autoclose = !canEmitExit; - // this override is here since tests fail via nyc if createHarness is moved upwards - // eslint-disable-next-line no-use-before-define - if (!harness) { harness = createExitHarness(opts, wait); } - return harness; - } - - function lazyLoad() { - // eslint-disable-next-line no-invalid-this - return getHarness().apply(this, arguments); - } - - lazyLoad.wait = function () { - wait = true; - }; - - lazyLoad.run = function () { - var run = getHarness().run; - - if (run) { run(); } - }; - - lazyLoad.only = function () { - return getHarness().only.apply(this, arguments); - }; - - lazyLoad.createStream = function (opts) { - var options = opts || {}; - if (!harness) { - var output = through(); - getHarness({ stream: output, objectMode: options.objectMode }); - return output; - } - return harness.createStream(options); - }; - - lazyLoad.onFinish = function () { - return getHarness().onFinish.apply(this, arguments); - }; - - lazyLoad.onFailure = function () { - return getHarness().onFailure.apply(this, arguments); - }; - - lazyLoad.getHarness = getHarness; - - return lazyLoad; -}()); - -function createHarness(conf_) { - var results = createResult(); - if (!conf_ || conf_.autoclose !== false) { - results.once('done', function () { results.close(); }); - } - - function test(name, conf, cb) { - var t = new Test(name, conf, cb); - test._tests.push(t); - - (function inspectCode(st) { - st.on('test', function sub(st_) { - inspectCode(st_); - }); - st.on('result', function (r) { - if (!r.todo && !r.ok && typeof r !== 'string') { test._exitCode = 1; } - }); - }(t)); - - results.push(t); - return t; - } - test._results = results; - - test._tests = []; - - test.createStream = function (opts) { - return results.createStream(opts); - }; - - test.onFinish = function (cb) { - results.on('done', cb); - }; - - test.onFailure = function (cb) { - results.on('fail', cb); - }; - - var only = false; - test.only = function () { - if (only) { throw new Error('there can only be one only test'); } - if (conf_.noOnly) { throw new Error('`only` tests are prohibited'); } - only = true; - var t = test.apply(null, arguments); - results.only(t); - return t; - }; - test._exitCode = 0; - - test.close = function () { results.close(); }; - - return test; -} - -function createExitHarness(conf, wait) { - var config = conf || {}; - var harness = createHarness({ - autoclose: defined(config.autoclose, false), - noOnly: defined(conf.noOnly, defined(process.env.NODE_TAPE_NO_ONLY_TEST, false)) - }); - var running = false; - var ended = false; - - function run() { - if (running) { return; } - running = true; - var stream = harness.createStream({ objectMode: config.objectMode }); - var es = stream.pipe(config.stream || createDefaultStream()); - if (canEmitExit && es) { // in node v0.4, `es` is `undefined` - // TODO: use `err` arg? - // eslint-disable-next-line no-unused-vars - es.on('error', function (err) { harness._exitCode = 1; }); - } - stream.on('end', function () { ended = true; }); - } - - if (wait) { - harness.run = run; - } else { - run(); - } - - if (config.exit === false) { return harness; } - if (!canEmitExit || !canExit) { return harness; } - - process.on('exit', function (code) { - // let the process exit cleanly. - if (typeof code === 'number' && code !== 0) { - return; - } - - if (!ended) { - var only = harness._results._only; - for (var i = 0; i < harness._tests.length; i++) { - var t = harness._tests[i]; - if (!only || t === only) { - t._exit(); - } - } - } - harness.close(); - - process.removeAllListeners('exit'); // necessary for node v0.6 - process.exit(code || harness._exitCode); // eslint-disable-line no-process-exit - }); - - return harness; -} - -module.exports.createHarness = createHarness; -module.exports.Test = Test; -module.exports.test = module.exports; // tap compat -module.exports.test.skip = Test.skip; +module.exports = require('./lib'); diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 00000000..7a7211e8 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,181 @@ +'use strict'; + +var defined = require('defined'); +var createDefaultStream = require('./lib/default_stream'); +var Test = require('./lib/test'); +var createResult = require('./lib/results'); +var through = require('@ljharb/through'); + +var canEmitExit = typeof process !== 'undefined' && process + && typeof process.on === 'function' && process.browser !== true; +var canExit = typeof process !== 'undefined' && process + && typeof process.exit === 'function'; + +module.exports = (function () { + var wait = false; + var harness; + + function getHarness(opts) { + if (!opts) { opts = {}; } + opts.autoclose = !canEmitExit; + // this override is here since tests fail via nyc if createHarness is moved upwards + // eslint-disable-next-line no-use-before-define + if (!harness) { harness = createExitHarness(opts, wait); } + return harness; + } + + function lazyLoad() { + // eslint-disable-next-line no-invalid-this + return getHarness().apply(this, arguments); + } + + lazyLoad.wait = function () { + wait = true; + }; + + lazyLoad.run = function () { + var run = getHarness().run; + + if (run) { run(); } + }; + + lazyLoad.only = function () { + return getHarness().only.apply(this, arguments); + }; + + lazyLoad.createStream = function (opts) { + var options = opts || {}; + if (!harness) { + var output = through(); + getHarness({ stream: output, objectMode: options.objectMode }); + return output; + } + return harness.createStream(options); + }; + + lazyLoad.onFinish = function () { + return getHarness().onFinish.apply(this, arguments); + }; + + lazyLoad.onFailure = function () { + return getHarness().onFailure.apply(this, arguments); + }; + + lazyLoad.getHarness = getHarness; + + return lazyLoad; +}()); + +function createHarness(conf_) { + var results = createResult(); + if (!conf_ || conf_.autoclose !== false) { + results.once('done', function () { results.close(); }); + } + + function test(name, conf, cb) { + var t = new Test(name, conf, cb); + test._tests.push(t); + + (function inspectCode(st) { + st.on('test', function sub(st_) { + inspectCode(st_); + }); + st.on('result', function (r) { + if (!r.todo && !r.ok && typeof r !== 'string') { test._exitCode = 1; } + }); + }(t)); + + results.push(t); + return t; + } + test._results = results; + + test._tests = []; + + test.createStream = function (opts) { + return results.createStream(opts); + }; + + test.onFinish = function (cb) { + results.on('done', cb); + }; + + test.onFailure = function (cb) { + results.on('fail', cb); + }; + + var only = false; + test.only = function () { + if (only) { throw new Error('there can only be one only test'); } + if (conf_.noOnly) { throw new Error('`only` tests are prohibited'); } + only = true; + var t = test.apply(null, arguments); + results.only(t); + return t; + }; + test._exitCode = 0; + + test.close = function () { results.close(); }; + + return test; +} + +function createExitHarness(conf, wait) { + var config = conf || {}; + var harness = createHarness({ + autoclose: defined(config.autoclose, false), + noOnly: defined(conf.noOnly, defined(process.env.NODE_TAPE_NO_ONLY_TEST, false)) + }); + var running = false; + var ended = false; + + function run() { + if (running) { return; } + running = true; + var stream = harness.createStream({ objectMode: config.objectMode }); + var es = stream.pipe(config.stream || createDefaultStream()); + if (canEmitExit && es) { // in node v0.4, `es` is `undefined` + // TODO: use `err` arg? + // eslint-disable-next-line no-unused-vars + es.on('error', function (err) { harness._exitCode = 1; }); + } + stream.on('end', function () { ended = true; }); + } + + if (wait) { + harness.run = run; + } else { + run(); + } + + if (config.exit === false) { return harness; } + if (!canEmitExit || !canExit) { return harness; } + + process.on('exit', function (code) { + // let the process exit cleanly. + if (typeof code === 'number' && code !== 0) { + return; + } + + if (!ended) { + var only = harness._results._only; + for (var i = 0; i < harness._tests.length; i++) { + var t = harness._tests[i]; + if (!only || t === only) { + t._exit(); + } + } + } + harness.close(); + + process.removeAllListeners('exit'); // necessary for node v0.6 + process.exit(code || harness._exitCode); // eslint-disable-line no-process-exit + }); + + return harness; +} + +module.exports.createHarness = createHarness; +module.exports.Test = Test; +module.exports.test = module.exports; // tap compat +module.exports.test.skip = Test.skip; diff --git a/lib/test.js b/lib/test.js index 59f62d5c..377e68ec 100644 --- a/lib/test.js +++ b/lib/test.js @@ -483,6 +483,7 @@ Test.prototype._assert = function assert(ok, opts) { var e = new Error('exception'); var err = $split(e.stack || '', '\n'); var tapeDir = __dirname + path.sep; + var index = path.sep + 'index.js'; for (var i = 0; i < err.length; i++) { /* @@ -549,7 +550,10 @@ Test.prototype._assert = function assert(ok, opts) { '' ); - if ($strSlice(filePath, 0, tapeDir.length) === tapeDir) { + if ( + $strSlice(filePath, 0, tapeDir.length) === tapeDir + && $strSlice(filePath, -index.length) !== index // index.js is inside lib/ + ) { continue; } diff --git a/package.json b/package.json index 62ea4a7e..0aca5f05 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,7 @@ "fs": false }, "exports": { - ".": [ - { - "default": "./index.js" - }, - "./index.js" - ], + ".": "./index.js", "./lib/default_stream": "./lib/default_stream.js", "./lib/results": "./lib/results.js", "./lib/test": "./lib/test.js", diff --git a/test/exit.js b/test/exit.js index 8ed986ad..5afc3dab 100644 --- a/test/exit.js +++ b/test/exit.js @@ -98,7 +98,7 @@ tap.test('too few exit', function (t) { ' operator: fail', ' expected: 6', ' actual: 5', - ' at: process. ($TAPE/index.js:$LINE:$COL)', + ' at: process. ($TAPE/lib/index.js:$LINE:$COL)', ' stack: |-', ' Error: plan != count', ' [... stack stripped ...]', @@ -135,7 +135,7 @@ tap.test('more planned in a second test', function (t) { ' operator: fail', ' expected: 2', ' actual: 1', - ' at: process. ($TAPE/index.js:$LINE:$COL)', + ' at: process. ($TAPE/lib/index.js:$LINE:$COL)', ' stack: |-', ' Error: plan != count', ' [... stack stripped ...]', @@ -228,7 +228,7 @@ tap.test('forgot to call t.end()', function (t) { 'not ok 3 test exited without ending: oops forgot end', ' ---', ' operator: fail', - ' at: process. ($TAPE/index.js:$LINE:$COL)', + ' at: process. ($TAPE/lib/index.js:$LINE:$COL)', ' stack: |-', ' Error: test exited without ending: oops forgot end', ' [... stack stripped ...]',