UNPKG

2.83 kBJavaScriptView Raw
1'use strict';
2
3var config = require('./config');
4var EventEmitter = require('events').EventEmitter;
5
6function TestNode(description, fn) {
7 EventEmitter.call(this);
8
9 this.description = description;
10 this.fn = fn;
11}
12
13TestNode.prototype = Object.create(EventEmitter.prototype);
14TestNode.prototype.constructor = TestNode;
15
16TestNode.prototype.hasRun = false;
17
18function verifyCanAssert(node) {
19 if (node.hasRun)
20 node.emit('error', 'TestNode has already completed ' +
21 'execution and cannot emit more assertions. Did you ' +
22 'forget a call to `t.cb(...)`?');
23
24 return !node.hasRun;
25}
26
27TestNode.prototype._assertOk = function (args) {
28 if (verifyCanAssert(this))
29 this.emit('assertOk', args);
30};
31
32TestNode.prototype._assertNotOk = function (args) {
33 if (verifyCanAssert(this))
34 this.emit('assertNotOk', args);
35};
36
37TestNode.prototype.run = function () {
38 var self = this;
39
40 var done = false, pending = 0;
41
42 function queueCallback(fn) {
43 pending++;
44 return function () {
45 if (fn)
46 runFn.call(this, fn, arguments);
47
48 if (--pending === 0 && done)
49 onNodeDone();
50 }
51 }
52
53 function runFn(fn, args) {
54 try {
55 var result = fn.apply(this, args);
56
57 if (result && typeof result.then === 'function' && !config.disablePromises) {
58 pending++;
59
60 result.then(function () {
61 if (--pending === 0 && done)
62 onNodeDone();
63 }, function (err) {
64 self._assertNotOk(err);
65
66 if (--pending === 0 && done)
67 onNodeDone();
68 });
69 }
70
71 } catch (err) {
72 self._assertNotOk(err);
73 }
74 }
75
76 var queue = [];
77
78 function runQueue() {
79 if (queue.length === 0) {
80 self.emit('treeDone');
81 self.removeAllListeners();
82 } else {
83 var node = queue.shift();
84
85 node.once('treeDone', runQueue);
86 self.emit('childTest', node);
87 node.run();
88 }
89 }
90
91 function onNodeDone() {
92 self.emit('nodeDone');
93 runQueue();
94 }
95
96 var t = config.createAssertionWrapper(this._assertOk.bind(this), this._assertNotOk.bind(this));
97
98 t.test = function (description, fn) { queue.push(new TestNode(description, fn)); };
99 t.xtest = function (description) { queue.push(new SkipTestNode(description)); };
100 t.comment = function () { self.emit('comment', arguments); };
101
102 t.cb = queueCallback;
103
104 this.emit('run');
105 runFn(this.fn, [t]);
106
107 done = true;
108 if (pending === 0)
109 onNodeDone();
110};
111
112function SkipTestNode(description) {
113 TestNode.call(this, description);
114}
115
116SkipTestNode.prototype = Object.create(TestNode.prototype);
117SkipTestNode.prototype.constructor = SkipTestNode;
118
119SkipTestNode.prototype.skip = true;
120
121SkipTestNode.prototype.run = function () {
122 this.emit('run');
123 this.hasRun = true;
124 this.emit('nodeDone');
125 this.emit('treeDone');
126};
127
128module.exports = TestNode;
\No newline at end of file