Name: js-handler/node_modules/nodeunit/lib/core.js 
1:
/*!
2:
 * Nodeunit
3:
 * Copyright (c) 2010 Caolan McMahon
4:
 * MIT Licensed
5:
 *
6:
 * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
7:
 * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build.
8:
 * Only code on that line will be removed, it's mostly to avoid requiring code
9:
 * that is node specific
10:
 */
11:
 
12:
/**
13:
 * Module dependencies
14:
 */
15:
 
16:
var async    = require('../deps/async'), //@REMOVE_LINE_FOR_BROWSER
17:
    nodeunit = require('./nodeunit'),    //@REMOVE_LINE_FOR_BROWSER
18:
    types    = require('./types');       //@REMOVE_LINE_FOR_BROWSER
19:
 
20:
 
21:
/**
22:
 * Added for browser compatibility
23:
 */
24:
 
25:
var _keys = function (obj) {
26:
    if (Object.keys) {
27:
        return Object.keys(obj);
28:
    }
29:
    var keys = [];
30:
    for (var k in obj) {
31:
        if (obj.hasOwnProperty(k)) {
32:
            keys.push(k);
33:
        }
34:
    }
35:
    return keys;
36:
};
37:
 
38:
 
39:
var _copy = function (obj) {
40:
    var nobj = {};
41:
    var keys = _keys(obj);
42:
    for (var i = 0; i <  keys.length; i += 1) {
43:
        nobj[keys[i]] = obj[keys[i]];
44:
    }
45:
    return nobj;
46:
};
47:
 
48:
 
49:
/**
50:
 * Runs a test function (fn) from a loaded module. After the test function
51:
 * calls test.done(), the callback is executed with an assertionList as its
52:
 * second argument.
53:
 *
54:
 * @param {String} name
55:
 * @param {Function} fn
56:
 * @param {Object} opt
57:
 * @param {Function} callback
58:
 * @api public
59:
 */
60:
 
61:
exports.runTest = function (name, fn, opt, callback) {
62:
    var options = types.options(opt);
63:
 
64:
    options.testStart(name);
65:
    var start = new Date().getTime();
66:
    var test = types.test(name, start, options, callback);
67:
 
68:
    try {
69:
        fn(test);
70:
    }
71:
    catch (e) {
72:
        test.done(e);
73:
    }
74:
};
75:
 
76:
/**
77:
 * Takes an object containing test functions or other test suites as properties
78:
 * and runs each in series. After all tests have completed, the callback is
79:
 * called with a list of all assertions as the second argument.
80:
 *
81:
 * If a name is passed to this function it is prepended to all test and suite
82:
 * names that run within it.
83:
 *
84:
 * @param {String} name
85:
 * @param {Object} suite
86:
 * @param {Object} opt
87:
 * @param {Function} callback
88:
 * @api public
89:
 */
90:
 
91:
exports.runSuite = function (name, suite, opt, callback) {
92:
    suite = wrapGroup(suite);
93:
    var keys = _keys(suite);
94:
 
95:
    async.concatSeries(keys, function (k, cb) {
96:
        var prop = suite[k], _name;
97:
 
98:
        _name = name ? [].concat(name, k) : [k];
99:
        _name.toString = function () {
100:
            // fallback for old one
101:
            return this.join(' - ');
102:
        };
103:
 
104:
        if (typeof prop === 'function') {
105:
            var in_name = false,
106:
                in_specific_test = (_name.toString() === opt.testFullSpec) ? true : false;
107:
            for (var i = 0; i < _name.length; i += 1) {
108:
                if (_name[i] === opt.testspec) {
109:
                    in_name = true;
110:
                }
111:
            }
112:
 
113:
            if ((!opt.testFullSpec || in_specific_test) && (!opt.testspec || in_name)) {
114:
                if (opt.moduleStart) {
115:
                    opt.moduleStart();
116:
                }
117:
                exports.runTest(_name, suite[k], opt, cb);
118:
            }
119:
            else {
120:
                return cb();
121:
            }
122:
        }
123:
        else {
124:
            exports.runSuite(_name, suite[k], opt, cb);
125:
        }
126:
    }, callback);
127:
};
128:
 
129:
/**
130:
 * Run each exported test function or test suite from a loaded module.
131:
 *
132:
 * @param {String} name
133:
 * @param {Object} mod
134:
 * @param {Object} opt
135:
 * @param {Function} callback
136:
 * @api public
137:
 */
138:
 
139:
exports.runModule = function (name, mod, opt, callback) {
140:
    var options = _copy(types.options(opt));
141:
 
142:
    var _run = false;
143:
    var _moduleStart = options.moduleStart;
144:
 
145:
    mod = wrapGroup(mod);
146:
 
147:
    function run_once() {
148:
        if (!_run) {
149:
            _run = true;
150:
            _moduleStart(name);
151:
        }
152:
    }
153:
    options.moduleStart = run_once;
154:
 
155:
    var start = new Date().getTime();
156:
 
157:
    exports.runSuite(null, mod, options, function (err, a_list) {
158:
        var end = new Date().getTime();
159:
        var assertion_list = types.assertionList(a_list, end - start);
160:
        options.moduleDone(name, assertion_list);
161:
        if (nodeunit.complete) {
162:
            nodeunit.complete(name, assertion_list);
163:
        }
164:
        callback(null, a_list);
165:
    });
166:
};
167:
 
168:
/**
169:
 * Treats an object literal as a list of modules keyed by name. Runs each
170:
 * module and finished with calling 'done'. You can think of this as a browser
171:
 * safe alternative to runFiles in the nodeunit module.
172:
 *
173:
 * @param {Object} modules
174:
 * @param {Object} opt
175:
 * @api public
176:
 */
177:
 
178:
// TODO: add proper unit tests for this function
179:
exports.runModules = function (modules, opt) {
180:
    var all_assertions = [];
181:
    var options = types.options(opt);
182:
    var start = new Date().getTime();
183:
 
184:
    async.concatSeries(_keys(modules), function (k, cb) {
185:
        exports.runModule(k, modules[k], options, cb);
186:
    },
187:
    function (err, all_assertions) {
188:
        var end = new Date().getTime();
189:
        options.done(types.assertionList(all_assertions, end - start));
190:
    });
191:
};
192:
 
193:
 
194:
/**
195:
 * Wraps a test function with setUp and tearDown functions.
196:
 * Used by testCase.
197:
 *
198:
 * @param {Function} setUp
199:
 * @param {Function} tearDown
200:
 * @param {Function} fn
201:
 * @api private
202:
 */
203:
 
204:
var wrapTest = function (setUp, tearDown, fn) {
205:
    return function (test) {
206:
        var context = {};
207:
        if (tearDown) {
208:
            var done = test.done;
209:
            test.done = function (err) {
210:
                try {
211:
                    tearDown.call(context, function (err2) {
212:
                        if (err && err2) {
213:
                            test._assertion_list.push(
214:
                                types.assertion({error: err})
215:
                            );
216:
                            return done(err2);
217:
                        }
218:
                        done(err || err2);
219:
                    });
220:
                }
221:
                catch (e) {
222:
                    done(e);
223:
                }
224:
            };
225:
        }
226:
        if (setUp) {
227:
            setUp.call(context, function (err) {
228:
                if (err) {
229:
                    return test.done(err);
230:
                }
231:
                fn.call(context, test);
232:
            });
233:
        }
234:
        else {
235:
            fn.call(context, test);
236:
        }
237:
    };
238:
};
239:
 
240:
 
241:
/**
242:
 * Returns a serial callback from two functions.
243:
 *
244:
 * @param {Function} funcFirst
245:
 * @param {Function} funcSecond
246:
 * @api private
247:
 */
248:
 
249:
var getSerialCallback = function (fns) {
250:
    if (!fns.length) {
251:
        return null;
252:
    }
253:
    return function (callback) {
254:
        var that = this;
255:
        var bound_fns = [];
256:
        for (var i = 0, len = fns.length; i < len; i++) {
257:
            (function (j) {
258:
                bound_fns.push(function () {
259:
                    return fns[j].apply(that, arguments);
260:
                });
261:
            })(i);
262:
        }
263:
        return async.series(bound_fns, callback);
264:
    };
265:
};
266:
 
267:
 
268:
/**
269:
 * Wraps a group of tests with setUp and tearDown functions.
270:
 * Used by testCase.
271:
 *
272:
 * @param {Object} group
273:
 * @param {Array} setUps - parent setUp functions
274:
 * @param {Array} tearDowns - parent tearDown functions
275:
 * @api private
276:
 */
277:
 
278:
var wrapGroup = function (group, setUps, tearDowns) {
279:
    var tests = {};
280:
 
281:
    var setUps = setUps ? setUps.slice(): [];
282:
    var tearDowns = tearDowns ? tearDowns.slice(): [];
283:
 
284:
    if (group.setUp) {
285:
        setUps.push(group.setUp);
286:
        delete group.setUp;
287:
    }
288:
    if (group.tearDown) {
289:
        tearDowns.unshift(group.tearDown);
290:
        delete group.tearDown;
291:
    }
292:
 
293:
    var keys = _keys(group);
294:
 
295:
    for (var i = 0; i < keys.length; i += 1) {
296:
        var k = keys[i];
297:
        if (typeof group[k] === 'function') {
298:
            tests[k] = wrapTest(
299:
                getSerialCallback(setUps),
300:
                getSerialCallback(tearDowns),
301:
                group[k]
302:
            );
303:
        }
304:
        else if (typeof group[k] === 'object') {
305:
            tests[k] = wrapGroup(group[k], setUps, tearDowns);
306:
        }
307:
    }
308:
    return tests;
309:
};
310:
 
311:
 
312:
/**
313:
 * Backwards compatibility for test suites using old testCase API
314:
 */
315:
 
316:
exports.testCase = function (suite) {
317:
    return suite;
318:
};