UNPKG

@testim/testim-cli

Version:

Command line interface for running Testing on you CI

194 lines (160 loc) 4.84 kB
var fnString = 'function', throwString = 'throw', isObject = Rx.internals.isObject; function toThunk(obj, ctx) { if (Array.isArray(obj)) { return objectToThunk.call(ctx, obj); } if (isGeneratorFunction(obj)) { return observableSpawn(obj.call(ctx)); } if (isGenerator(obj)) { return observableSpawn(obj); } if (isObservable(obj)) { return observableToThunk(obj); } if (isPromise(obj)) { return promiseToThunk(obj); } if (typeof obj === fnString) { return obj; } if (isObject(obj) || Array.isArray(obj)) { return objectToThunk.call(ctx, obj); } return obj; } function objectToThunk(obj) { var ctx = this; return function (done) { var keys = Object.keys(obj), pending = keys.length, results = new obj.constructor(), finished; if (!pending) { timeoutScheduler.schedule(function () { done(null, results); }); return; } for (var i = 0, len = keys.length; i < len; i++) { run(obj[keys[i]], keys[i]); } function run(fn, key) { if (finished) { return; } try { fn = toThunk(fn, ctx); if (typeof fn !== fnString) { results[key] = fn; return --pending || done(null, results); } fn.call(ctx, function(err, res) { if (finished) { return; } if (err) { finished = true; return done(err); } results[key] = res; --pending || done(null, results); }); } catch (e) { finished = true; done(e); } } } } function observableToThunk(observable) { return function (fn) { var value, hasValue = false; observable.subscribe( function (v) { value = v; hasValue = true; }, fn, function () { hasValue && fn(null, value); }); } } function promiseToThunk(promise) { return function(fn) { promise.then(function(res) { fn(null, res); }, fn); } } function isObservable(obj) { return obj && typeof obj.subscribe === fnString; } function isGeneratorFunction(obj) { return obj && obj.constructor && obj.constructor.name === 'GeneratorFunction'; } function isGenerator(obj) { return obj && typeof obj.next === fnString && typeof obj[throwString] === fnString; } /* * Spawns a generator function which allows for Promises, Observable sequences, Arrays, Objects, Generators and functions. * @param {Function} The spawning function. * @returns {Function} a function which has a done continuation. */ var observableSpawn = Rx.spawn = function (fn) { var isGenFun = isGeneratorFunction(fn); return function (done) { var ctx = this, gen = fn; if (isGenFun) { for(var args = [], i = 0, len = arguments.length; i < len; i++) { args.push(arguments[i]); } var len = args.length, hasCallback = len && typeof args[len - 1] === fnString; done = hasCallback ? args.pop() : handleError; gen = fn.apply(this, args); } else { done = done || handleError; } next(); function exit(err, res) { timeoutScheduler.schedule(done.bind(ctx, err, res)); } function next(err, res) { var ret; // multiple args if (arguments.length > 2) { for(var res = [], i = 1, len = arguments.length; i < len; i++) { res.push(arguments[i]); } } if (err) { try { ret = gen[throwString](err); } catch (e) { return exit(e); } } if (!err) { try { ret = gen.next(res); } catch (e) { return exit(e); } } if (ret.done) { return exit(null, ret.value); } ret.value = toThunk(ret.value, ctx); if (typeof ret.value === fnString) { var called = false; try { ret.value.call(ctx, function() { if (called) { return; } called = true; next.apply(ctx, arguments); }); } catch (e) { timeoutScheduler.schedule(function () { if (called) { return; } called = true; next.call(ctx, e); }); } return; } // Not supported next(new TypeError('Rx.spawn only supports a function, Promise, Observable, Object or Array.')); } } }; function handleError(err) { if (!err) { return; } timeoutScheduler.schedule(function() { throw err; }); }