-
Notifications
You must be signed in to change notification settings - Fork 370
/
types.js
179 lines (160 loc) · 5.24 KB
/
types.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*!
* Nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*/
/**
* Module dependencies
*/
var assert = require('assert'),
sys = require('sys');
/**
* Creates assertion objects representing the result of an assert call.
* Accepts an object or AssertionError as its argument.
*
* @param {object} obj
* @api public
*/
exports.assertion = function (obj) {
return {
method: obj.method || '',
message: obj.message || (obj.error && obj.error.message) || '',
error: obj.error,
passed: function () { return !this.error; },
failed: function () { return Boolean(this.error); }
};
};
/**
* Creates an assertion list object representing a group of assertions.
* Accepts an array of assertion objects.
*
* @param {Array} arr
* @param {Number} duration
* @api public
*/
exports.assertionList = function (arr, duration) {
var that = arr || [];
that.__defineGetter__('failures', function () {
return this.reduce(function (a,x) {
return x.failed() ? a+1 : a;
}, 0);
});
that.duration = duration || 0;
return that;
};
/**
* Create a wrapper function for assert module methods. Executes a callback
* after the it's complete with an assertion object representing the result.
*
* @param {Function} callback
* @api private
*/
var assertWrapper = function (callback) {
return function (new_method, assert_method) {
return function () {
try {
assert[assert_method].apply(global, arguments);
var message = arguments[arguments.length-1];
var a = exports.assertion({method:new_method, message:message});
}
catch (e) {
// deepEqual error message is a bit sucky, lets improve it!
// e.actual and e.expected could be null or undefined, so
// using getOwnPropertyDescriptor to see if they exist:
if (Object.getOwnPropertyDescriptor(e,'actual')
&& Object.getOwnPropertyDescriptor(e,'expected')) {
var actual = sys.inspect(e.actual).replace(/\n$/,'');
var expected = sys.inspect(e.expected).replace(/\n$/,'');
var multiline = (
actual.indexOf('\n') != -1 ||
expected.indexOf('\n') != -1
);
var spacing = (multiline ? '\n' : ' ');
e._message = e.message;
e.stack = (
e.name + ':' + spacing +
actual + spacing + e.operator + spacing +
expected + '\n' +
e.stack.split('\n').slice(1).join('\n')
);
}
var a = exports.assertion({method:new_method, error:e});
}
callback(a);
};
};
};
/**
* Creates the 'test' object that gets passed to every test function.
* Accepts the name of the test function as its first argument, followed by
* the start time in ms, the options object and a callback function.
*
* @param {String} name
* @param {Number} start
* @param {Object} options
* @param {Function} callback
* @api public
*/
exports.test = function (name, start, options, callback) {
var expecting;
var a_list = [];
var wrapAssert = assertWrapper(function (a) {
a_list.push(a);
process.nextTick(function () { options.log(a) });
});
var test = {
done: function (err) {
if (expecting !== undefined && expecting != a_list.length) {
var e = new Error(
'Expected ' + expecting + ' assertions, ' +
a_list.length + ' ran'
);
var a1 = exports.assertion({method:'expect', error: e});
a_list.push(a1);
process.nextTick(function () { options.log(a1); });
}
if(err) {
var a2 = exports.assertion({error: err});
a_list.push(a2);
process.nextTick(function () { options.log(a2); });
}
var end = new Date().getTime();
process.nextTick(function () {
var assertion_list = exports.assertionList(a_list, end-start);
options.testDone(name, assertion_list);
callback(null, a_list);
});
},
ok: wrapAssert('ok', 'ok'),
same: wrapAssert('same', 'deepEqual'),
equals: wrapAssert('equals', 'equal'),
expect: function (num) {
expecting = num;
}
};
// add all functions from the assert module
for (var k in assert) {
test[k] = wrapAssert(k, k);
}
return test;
};
/**
* Ensures an options object has all callbacks, adding empty callback functions
* if any are missing.
*
* @param {Object} opt
* @return {Object}
* @api public
*/
exports.options = function (opt) {
var optionalCallback = function (name) {
opt[name] = opt[name] || function () {};
};
optionalCallback('moduleStart');
optionalCallback('moduleDone');
optionalCallback('testStart');
optionalCallback('testDone');
optionalCallback('log');
// 'done' callback is not optional.
return opt;
};