1 | 'use strict';
|
2 |
|
3 | var defined = require('defined');
|
4 | var createDefaultStream = require('./lib/default_stream');
|
5 | var Test = require('./lib/test');
|
6 | var createResult = require('./lib/results');
|
7 | var through = require('through');
|
8 |
|
9 | var canEmitExit = typeof process !== 'undefined' && process
|
10 | && typeof process.on === 'function' && process.browser !== true;
|
11 | var canExit = typeof process !== 'undefined' && process
|
12 | && typeof process.exit === 'function';
|
13 |
|
14 | module.exports = (function () {
|
15 | var wait = false;
|
16 | var harness;
|
17 |
|
18 | function getHarness(opts) {
|
19 | if (!opts) { opts = {}; }
|
20 | opts.autoclose = !canEmitExit;
|
21 |
|
22 |
|
23 | if (!harness) { harness = createExitHarness(opts, wait); }
|
24 | return harness;
|
25 | }
|
26 |
|
27 | function lazyLoad() {
|
28 |
|
29 | return getHarness().apply(this, arguments);
|
30 | }
|
31 |
|
32 | lazyLoad.wait = function () {
|
33 | wait = true;
|
34 | };
|
35 |
|
36 | lazyLoad.run = function () {
|
37 | var run = getHarness().run;
|
38 |
|
39 | if (run) { run(); }
|
40 | };
|
41 |
|
42 | lazyLoad.only = function () {
|
43 | return getHarness().only.apply(this, arguments);
|
44 | };
|
45 |
|
46 | lazyLoad.createStream = function (opts) {
|
47 | var options = opts || {};
|
48 | if (!harness) {
|
49 | var output = through();
|
50 | getHarness({ stream: output, objectMode: options.objectMode });
|
51 | return output;
|
52 | }
|
53 | return harness.createStream(options);
|
54 | };
|
55 |
|
56 | lazyLoad.onFinish = function () {
|
57 | return getHarness().onFinish.apply(this, arguments);
|
58 | };
|
59 |
|
60 | lazyLoad.onFailure = function () {
|
61 | return getHarness().onFailure.apply(this, arguments);
|
62 | };
|
63 |
|
64 | lazyLoad.getHarness = getHarness;
|
65 |
|
66 | return lazyLoad;
|
67 | }());
|
68 |
|
69 | function createHarness(conf_) {
|
70 | var results = createResult();
|
71 | if (!conf_ || conf_.autoclose !== false) {
|
72 | results.once('done', function () { results.close(); });
|
73 | }
|
74 |
|
75 | function test(name, conf, cb) {
|
76 | var t = new Test(name, conf, cb);
|
77 | test._tests.push(t);
|
78 |
|
79 | (function inspectCode(st) {
|
80 | st.on('test', function sub(st_) {
|
81 | inspectCode(st_);
|
82 | });
|
83 | st.on('result', function (r) {
|
84 | if (!r.todo && !r.ok && typeof r !== 'string') { test._exitCode = 1; }
|
85 | });
|
86 | }(t));
|
87 |
|
88 | results.push(t);
|
89 | return t;
|
90 | }
|
91 | test._results = results;
|
92 |
|
93 | test._tests = [];
|
94 |
|
95 | test.createStream = function (opts) {
|
96 | return results.createStream(opts);
|
97 | };
|
98 |
|
99 | test.onFinish = function (cb) {
|
100 | results.on('done', cb);
|
101 | };
|
102 |
|
103 | test.onFailure = function (cb) {
|
104 | results.on('fail', cb);
|
105 | };
|
106 |
|
107 | var only = false;
|
108 | test.only = function () {
|
109 | if (only) { throw new Error('there can only be one only test'); }
|
110 | if (conf_.noOnly) { throw new Error('`only` tests are prohibited'); }
|
111 | only = true;
|
112 | var t = test.apply(null, arguments);
|
113 | results.only(t);
|
114 | return t;
|
115 | };
|
116 | test._exitCode = 0;
|
117 |
|
118 | test.close = function () { results.close(); };
|
119 |
|
120 | return test;
|
121 | }
|
122 |
|
123 | function createExitHarness(conf, wait) {
|
124 | var config = conf || {};
|
125 | var harness = createHarness({
|
126 | autoclose: defined(config.autoclose, false),
|
127 | noOnly: defined(conf.noOnly, defined(process.env.NODE_TAPE_NO_ONLY_TEST, false))
|
128 | });
|
129 | var running = false;
|
130 | var ended = false;
|
131 |
|
132 | function run() {
|
133 | if (running) { return; }
|
134 | running = true;
|
135 | var stream = harness.createStream({ objectMode: config.objectMode });
|
136 | var es = stream.pipe(config.stream || createDefaultStream());
|
137 | if (canEmitExit && es) {
|
138 |
|
139 |
|
140 | es.on('error', function (err) { harness._exitCode = 1; });
|
141 | }
|
142 | stream.on('end', function () { ended = true; });
|
143 | }
|
144 |
|
145 | if (wait) {
|
146 | harness.run = run;
|
147 | } else {
|
148 | run();
|
149 | }
|
150 |
|
151 | if (config.exit === false) { return harness; }
|
152 | if (!canEmitExit || !canExit) { return harness; }
|
153 |
|
154 | process.on('exit', function (code) {
|
155 |
|
156 | if (typeof code === 'number' && code !== 0) {
|
157 | return;
|
158 | }
|
159 |
|
160 | if (!ended) {
|
161 | var only = harness._results._only;
|
162 | for (var i = 0; i < harness._tests.length; i++) {
|
163 | var t = harness._tests[i];
|
164 | if (!only || t === only) {
|
165 | t._exit();
|
166 | }
|
167 | }
|
168 | }
|
169 | harness.close();
|
170 |
|
171 | process.removeAllListeners('exit');
|
172 | process.exit(code || harness._exitCode);
|
173 | });
|
174 |
|
175 | return harness;
|
176 | }
|
177 |
|
178 | module.exports.createHarness = createHarness;
|
179 | module.exports.Test = Test;
|
180 | module.exports.test = module.exports;
|
181 | module.exports.test.skip = Test.skip;
|