ickyrr-gagarin
Version:
A current updated fork of gagarin
364 lines (287 loc) • 10.6 kB
JavaScript
/**
* Module dependencies.
*/
var Promise = require('es6-promise').Promise;
var Closure = require('../tools/closure');
var helpers = require('../browser/helpers');
var Meteor = require('../meteor');
var tools = require('../tools');
var Mocha = require('mocha');
var Fiber = require('fibers');
var Future = require('fibers/future');
var url = require('url');
var logs = require('../logs');
/**
* Custom Mocha interface.
*/
Mocha.interfaces['gagarin'] = module.exports = function (suite) {
"use strict";
// use the original bdd intrface
Mocha.interfaces.bdd.apply(this, arguments);
var gagarinOptions = this.options;
var gagarinSettings = tools.getSettings(this.options.settings) || {}; // make sure it's not undefined
suite.on('pre-require', function (context) {
var chai = require('chai');
var before = context.before;
var after = context.after;
var stack = [];
// adding Fiber support
context.Fiber = Fiber;
var originalIt = context.it;
context.it = runInsideFiber(context.it);
context.it.skip = runInsideFiber(originalIt.skip);
context.it.only = runInsideFiber(originalIt.only);
context.specify = context.it;
context.xspecify = context.xit = context.it.skip;
context.before = runInsideFiber(context.before);
context.beforeEach = runInsideFiber(context.beforeEach);
context.after = runInsideFiber(context.after);
context.afterEach = runInsideFiber(context.afterEach);
// TODO: allow users to configure the default asserters
chai.use(require('chai-things'));
context.expect = chai.expect;
context.meteor = function (options, onStart) {
var myHelpers = {};
options = options || {};
options.flavor = options.flavor || gagarinOptions.flavor || "promise";
if (typeof options === 'function') {
onStart = options; options = {};
}
if (typeof options === 'string') {
options = { pathToApp: options };
}
tools.mergeHelpers(myHelpers, options.helpers);
var meteor = new Meteor({
pathToApp : options.pathToApp || gagarinOptions.pathToApp,
helpers : myHelpers,
settings : tools.getSettings(options.settings) || gagarinSettings,
verbose : options.verbose !== undefined ? options.verbose : gagarinOptions.verbose,
remoteServer : options.remoteServer || gagarinOptions.remoteServer,
skipBuild : options.skipBuild !== undefined ? options.skipBuild : gagarinOptions.skipBuild,
startupTimeout : options.startupTimeout !== undefined ? options.startupTimeout : gagarinOptions.startupTimeout,
startupTimeout2 : options.startupTimeout2, // this one is only used for internal tests
});
meteor.useClosure(function () {
return stack[stack.length-1];
});
if (!options.noAutoStart) {
before(function () {
logs.test("starting meteor instance");
return meteor.init().startup(onStart).then(function () {
logs.test("meteor instance ready");
});
});
after(function () {
logs.test("stopping meteor instance");
return meteor.stop().then(function () {
logs.test("meteor instance terminated");
});
});
} else {
if (onStart) {
console.warn('onStart will not work with noAutoStart option set to true');
}
}
if (options.flavor == "fiber") {
var proxy = wrapPromisesForFiber(meteor, meteor.methods);
proxy.getDDPSetup = meteor.getDDPSetup;
return proxy;
} else {
return meteor;
}
}
context.browser = function (location, options, initialize) {
var createBrowser = require('../browser');
var myHelpers = {};
if (arguments.length === 2) {
if (typeof options === 'function') {
initialize = options; options = location; location = undefined;
}
}
if (arguments.length === 1) {
if (typeof location === 'function') {
initialize = location; options = {}; location = undefined;
} else {
options = location; location = undefined;
}
}
if (arguments.length === 0) {
options = {};
}
if (location && typeof options !== 'object') {
throw new Error("if 'location' is provided, argument 'options' must be an object");
}
if (!options || (typeof options !== 'object' && typeof options !== 'string')) {
throw new Error("argument 'options' must be an object or a string");
}
if (location && typeof location !== 'string' && location.getDDPSetup === undefined) {
throw new TypeError("argument 'location' must be a string or an instance of meteor server");
}
if (location && options.getDDPSetup) {
throw new TypeError("if 'location' is provided, argument 'options' must not be an instance of meteor server");
}
if (location) {
options.location = location;
}
if (typeof options === 'string') {
options = { location: options };
}
if (options && options.getDDPSetup) {
options = { location: options };
}
if (!options.location) {
options.location = 'http://gagarin.meteor.com';
}
options.flavor = options.flavor || gagarinOptions.flavor || "promise";
tools.mergeHelpers(myHelpers, options.helpers);
var browser = createBrowser({
helpers : myHelpers,
verbose : options.verbose !== undefined ? options.verbose : gagarinOptions.verbose,
location : options.location,
webdriver : options.webdriver || gagarinOptions.webdriver,
windowSize : options.windowSize,
capabilities : options.capabilities,
dontWaitForMeteor : options.dontWaitForMeteor !== undefined ? options.dontWaitForMeteor : gagarinOptions.dontWaitForMeteor,
meteorLoadTimeout : options.meteorLoadTimeout !== undefined ? options.meteorLoadTimeout : gagarinOptions.meteorLoadTimeout,
});
browser.useClosure(function () {
return stack[stack.length-1];
});
before(function () {
logs.test("starting browser instance");
return browser.init().then(function () {
logs.test("browser instance ready");
if (typeof initialize === 'function') {
return initialize.length ? browser.promise(initialize) : browser.execute(initialize);
}
});
});
after(function () {
logs.test("stopping browser instance");
return browser.close().quit().then(function () {
logs.test("browser instance terminated");
});
});
return (options.flavor == "fiber")? wrapPromisesForFiber(browser, browser.methods) : browser;
}
context.ddp = function (server, options) {
var makeDDPClient = require('../ddp');
var getDDPSetup = null;
options = options || {};
options.flavor = options.flavor || gagarinOptions.flavor || "promise";
if (server.getDDPSetup) {
getDDPSetup = server.getDDPSetup;
}
if (typeof server === 'string') {
getDDPSetup = function () {
var parsed = url.parse(server);
return Promise.resolve({
host: parsed.hostname,
port: parsed.port || 443,
});
};
}
if (!getDDPSetup) {
throw new Error('DDP: no server connection provided');
}
var ddp = makeDDPClient(getDDPSetup, options.helpers);
return (options.flavor === 'fiber') ? wrapPromisesForFiber(ddp, ddp.methods) : ddp;
}
context.mongo = function (options) {
var makeMongoDB = require('../mongo');
options = options || {};
options.flavor = options.flavor || gagarinOptions.flavor || "promise";
if (typeof options === 'function') {
initialize = options; options = {};
}
if (typeof options === 'string') {
options = { pathToApp: options };
}
var mongo = makeMongoDB({
pathToApp : options.pathToApp || gagarinOptions.pathToApp,
dbPath : options.dbPath,
dbName : options.dbName,
mongoUrl : options.mongoUrl,
}, options.helpers);
before(function () {
return mongo.start();
});
after(function () {
return mongo.stop();
});
return mongo;
}
context.closure = function (listOfKeys, runInContext) {
var accessor = runInContext.length >= 2 ? runInContext : function (key, value) {
return runInContext(key + (arguments.length > 1 ? '=' + stringify(value) : ''));
}
before(function () {
stack.push(new Closure(stack[stack.length-1], listOfKeys, accessor));
});
after(function () {
stack.pop();
});
};
context.settings = JSON.parse(JSON.stringify(gagarinSettings)); // deep copy :P
});
}
function stringify(value) {
if (typeof value === 'function') {
throw new Error('cannot use function as a closure variable');
}
return value !== undefined ? JSON.stringify(value) : "undefined";
}
function wrapPromisesForFiber(obj, methodList) {
var proxy = {};
methodList.forEach(function(method) {
var original = obj[method];
proxy[method] = function() {
var f = new Future();
var promise = original.apply(obj, arguments);
promiseAsThunk(promise)(function(error, value) {
if (error) {
f.throw(error);
} else {
f.return(value);
}
});
return f.wait();
};
});
return proxy;
}
function promiseAsThunk(promise, done) {
return function(done) {
promise.then(function(value) {
done(null, value);
}).catch(function(error) {
done(error);
});
};
}
function runInsideFiber (originalFunction) {
var fiberizeFunction = function(name, fn) {
if (typeof name == "function") {
fn = name;
name = null;
}
if (fn) {
return originalFunction(name, function(done) {
new Fiber(function() {
if (fn.length > 0) {
fn(done);
} else {
var promise = fn();
if (promise) {
promiseAsThunk(promise)(done);
} else {
done();
}
}
}).run();
});
}
return originalFunction(name);
};
return fiberizeFunction;
}