index.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. 'use strict';
  2. var defined = require('defined');
  3. var createDefaultStream = require('./lib/default_stream');
  4. var Test = require('./lib/test');
  5. var createResult = require('./lib/results');
  6. var through = require('through');
  7. var canEmitExit = typeof process !== 'undefined' && process
  8. && typeof process.on === 'function' && process.browser !== true;
  9. var canExit = typeof process !== 'undefined' && process
  10. && typeof process.exit === 'function';
  11. module.exports = (function () {
  12. var harness;
  13. function getHarness(opts) {
  14. if (!opts) { opts = {}; }
  15. opts.autoclose = !canEmitExit;
  16. // this override is here since tests fail via nyc if createHarness is moved upwards
  17. // eslint-disable-next-line no-use-before-define
  18. if (!harness) { harness = createExitHarness(opts); }
  19. return harness;
  20. }
  21. function lazyLoad() {
  22. // eslint-disable-next-line no-invalid-this
  23. return getHarness().apply(this, arguments);
  24. }
  25. lazyLoad.only = function () {
  26. return getHarness().only.apply(this, arguments);
  27. };
  28. lazyLoad.createStream = function (opts) {
  29. var options = opts || {};
  30. if (!harness) {
  31. var output = through();
  32. getHarness({ stream: output, objectMode: options.objectMode });
  33. return output;
  34. }
  35. return harness.createStream(options);
  36. };
  37. lazyLoad.onFinish = function () {
  38. return getHarness().onFinish.apply(this, arguments);
  39. };
  40. lazyLoad.onFailure = function () {
  41. return getHarness().onFailure.apply(this, arguments);
  42. };
  43. lazyLoad.getHarness = getHarness;
  44. return lazyLoad;
  45. }());
  46. function createHarness(conf_) {
  47. var results = createResult();
  48. if (!conf_ || conf_.autoclose !== false) {
  49. results.once('done', function () { results.close(); });
  50. }
  51. function test(name, conf, cb) {
  52. var t = new Test(name, conf, cb);
  53. test._tests.push(t);
  54. (function inspectCode(st) {
  55. st.on('test', function sub(st_) {
  56. inspectCode(st_);
  57. });
  58. st.on('result', function (r) {
  59. if (!r.todo && !r.ok && typeof r !== 'string') { test._exitCode = 1; }
  60. });
  61. }(t));
  62. results.push(t);
  63. return t;
  64. }
  65. test._results = results;
  66. test._tests = [];
  67. test.createStream = function (opts) {
  68. return results.createStream(opts);
  69. };
  70. test.onFinish = function (cb) {
  71. results.on('done', cb);
  72. };
  73. test.onFailure = function (cb) {
  74. results.on('fail', cb);
  75. };
  76. var only = false;
  77. test.only = function () {
  78. if (only) { throw new Error('there can only be one only test'); }
  79. if (conf_.noOnly) { throw new Error('`only` tests are prohibited'); }
  80. only = true;
  81. var t = test.apply(null, arguments);
  82. results.only(t);
  83. return t;
  84. };
  85. test._exitCode = 0;
  86. test.close = function () { results.close(); };
  87. return test;
  88. }
  89. function createExitHarness(conf) {
  90. var config = conf || {};
  91. var harness = createHarness({
  92. autoclose: defined(config.autoclose, false),
  93. noOnly: defined(conf.noOnly, defined(process.env.NODE_TAPE_NO_ONLY_TEST, false))
  94. });
  95. var stream = harness.createStream({ objectMode: conf.objectMode });
  96. var es = stream.pipe(conf.stream || createDefaultStream());
  97. if (canEmitExit) {
  98. // eslint-disable-next-line no-unused-vars
  99. es.on('error', function (err) { harness._exitCode = 1; });
  100. }
  101. var ended = false;
  102. stream.on('end', function () { ended = true; });
  103. if (config.exit === false) { return harness; }
  104. if (!canEmitExit || !canExit) { return harness; }
  105. process.on('exit', function (code) {
  106. // let the process exit cleanly.
  107. if (code !== 0) {
  108. return;
  109. }
  110. if (!ended) {
  111. var only = harness._results._only;
  112. for (var i = 0; i < harness._tests.length; i++) {
  113. var t = harness._tests[i];
  114. if (!only || t === only) {
  115. t._exit();
  116. }
  117. }
  118. }
  119. harness.close();
  120. process.exit(code || harness._exitCode); // eslint-disable-line no-process-exit
  121. });
  122. return harness;
  123. }
  124. module.exports.createHarness = createHarness;
  125. module.exports.Test = Test;
  126. module.exports.test = module.exports; // tap compat
  127. module.exports.test.skip = Test.skip;