spectacular
Version:
Advanced BDD framework for CoffeeScript and JavaScript
302 lines (283 loc) • 9.25 kB
JavaScript
// Generated by CoffeeScript 1.6.3
var Q, SPECTACULAR_ROOT, colorize, exists, express, findrequire, fs, generateSpecRunner, glob, globPath, globPaths, jade, path, scriptNode, spawn, util, walk,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
fs = require('fs');
Q = require('q');
glob = require('glob');
path = require('path');
express = require('express');
walk = require('walkdir');
util = require('util');
spawn = require('child_process').spawn;
jade = require('jade');
exists = fs.exists || path.exists;
SPECTACULAR_ROOT = path.resolve(__dirname, '..');
colorize = null;
findrequire = function(p, options) {
var defer, res;
defer = Q.defer();
res = [];
exists(p, function(exist) {
var emitter;
if (exist) {
emitter = walk(p);
emitter.on('file', function(p, stat) {
return res.push(path.relative('.', p));
});
return emitter.on('end', function() {
return defer.resolve(res);
});
} else {
return defer.resolve([]);
}
});
return defer.promise;
};
globPath = function(p) {
var defer;
defer = Q.defer();
glob(p, function(err, res) {
if (err) {
return defer.reject(err);
}
return defer.resolve(res);
});
return defer.promise;
};
globPaths = function(globs) {
var p,
_this = this;
return Q.all((function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = globs.length; _i < _len; _i++) {
p = globs[_i];
_results.push(globPath(p));
}
return _results;
})()).then(function(results) {
var paths;
paths = [];
results.forEach(function(a) {
return paths = paths.concat(a);
});
return paths;
});
};
scriptNode = function(path) {
return "<script type='text/javascript' src='" + path + "'></script>";
};
generateSpecRunner = function(options) {
var p, paths, templates;
if (options.verbose) {
console.log(" " + (colorize('options', 'grey')) + " " + (util.inspect(options)));
}
paths = ['assets/js/spectacular.js', 'assets/js/browser_reporter.js'];
templates = {};
return Q.all((function() {
var _i, _len, _ref, _results;
_ref = options.requires;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
p = _ref[_i];
_results.push(findrequire(p, options));
}
return _results;
})()).then(function(requires) {
var collection, f, _i, _j, _len, _len1;
for (_i = 0, _len = requires.length; _i < _len; _i++) {
collection = requires[_i];
for (_j = 0, _len1 = collection.length; _j < _len1; _j++) {
f = collection[_j];
if (/(js|coffee)$/.test(f)) {
paths.push(f);
if (options.verbose) {
console.log(" " + (colorize('requires', 'grey')) + " " + f);
}
}
}
}
return globPaths(options.globs);
}).then(function(specs) {
var f, uniq, v, _i, _j, _len, _len1;
if (options.verbose) {
for (_i = 0, _len = specs.length; _i < _len; _i++) {
f = specs[_i];
console.log(" " + (colorize('spec', 'grey')) + " " + f);
}
}
paths = paths.concat(specs);
uniq = [];
for (_j = 0, _len1 = paths.length; _j < _len1; _j++) {
v = paths[_j];
if (__indexOf.call(uniq, v) < 0) {
uniq.push(v);
}
}
return paths = uniq;
}).then(function() {
return globPaths([path.resolve(SPECTACULAR_ROOT, 'templates/formatters/*.jade')]);
}).then(function(tpls) {
var n, p, _i, _len;
for (_i = 0, _len = tpls.length; _i < _len; _i++) {
p = tpls[_i];
n = p.split('/');
n = n[n.length - 1];
n = n.split('.')[0];
templates[n] = jade.compile(fs.readFileSync(p), {
client: true,
compileDebug: false
}).toString();
templates[n] = "<script type='text/javascript'>\nspectacular.templates['" + n + "'] = " + templates[n] + "\n</script>";
}
return globPaths(options.sources);
}).then(function(sources) {
var f, locals, tpl, tplPath, _i, _len;
if (options.verbose) {
for (_i = 0, _len = sources.length; _i < _len; _i++) {
f = sources[_i];
console.log(" " + (colorize('source', 'grey')) + " " + f);
}
}
options.paths = paths.slice(2);
locals = {
options: util.inspect(options),
paths: paths,
sources: sources,
pretty: true,
sourceMap: options.sourceMap,
templates: templates
};
tplPath = path.resolve(SPECTACULAR_ROOT, 'templates/specs.jade');
if (options.verbose) {
console.log(" " + (colorize('template', 'grey')) + " " + tplPath);
}
return tpl = jade.renderFile(tplPath, locals);
});
};
exports.run = function(options) {
var app, defer, phantom, port;
colorize = function(str, color) {
if (options.colors) {
return str[color];
} else {
return str;
}
};
defer = Q.defer();
app = express();
app.get('/', function(req, res) {
return generateSpecRunner(options).then(function(html) {
console.log(" " + (colorize('200', 'green')) + " " + (colorize('GET', 'cyan')) + " /");
return res.send(html);
}).fail(function(reason) {
var tplPath;
console.log(" " + (colorize('500', 'red')) + " " + (colorize('GET', 'cyan')) + " /");
console.log(reason.stack);
tplPath = path.resolve(SPECTACULAR_ROOT, 'templates/500.jade');
return res.status(500).send(jade.renderFile(tplPath, {
error: reason.stack
}));
});
});
app.use('/assets/js', express["static"](path.resolve(SPECTACULAR_ROOT, 'lib')));
app.use('/vendor', express["static"](path.resolve(SPECTACULAR_ROOT, 'vendor')));
app.use('/assets/css', express["static"](path.resolve(SPECTACULAR_ROOT, 'css')));
app.use('/', function(req, res, next) {
var compile, compiled, content, notFound, reason, serverError;
serverError = function(reason) {
var tplPath;
tplPath = path.resolve(SPECTACULAR_ROOT, 'templates/500.jade');
console.log(" " + (colorize('500', 'red')) + " " + (colorize('GET', 'cyan')) + " " + req.url);
return res.status(500).send(jade.renderFile(tplPath, {
error: reason.stack
}));
};
notFound = function(reason) {
var tplPath;
tplPath = path.resolve(SPECTACULAR_ROOT, 'templates/404.jade');
console.log(" " + (colorize('404', 'red')) + " " + (colorize('GET', 'cyan')) + " " + req.url);
return res.status(404).send(jade.renderFile(tplPath, {
error: reason.stack
}));
};
if (/\.coffee$/.test(req.url) && options.coffee) {
try {
content = fs.readFileSync(path.resolve("." + req.url)).toString();
} catch (_error) {
reason = _error;
return notFound(reason);
}
try {
compile = require('coffee-script').compile;
} catch (_error) {
reason = _error;
return serverError(notFound);
}
content = compile(content);
} else if (/\.coffee\.src$/.test(req.url) && options.coffee) {
try {
content = fs.readFileSync(path.resolve("." + (req.url.replace('.coffee.src', '.coffee')))).toString();
} catch (_error) {
reason = _error;
return notFound(reason);
}
} else if (/\.map$/.test(req.url) && options.coffee) {
try {
content = fs.readFileSync(path.resolve("." + (req.url.replace('.map', '.coffee')))).toString();
} catch (_error) {
reason = _error;
return notFound(reason);
}
try {
compile = require('coffee-script').compile;
compiled = compile(content, {
sourceMap: true
});
content = compiled.v3SourceMap;
} catch (_error) {
reason = _error;
serverError(reason);
}
} else {
try {
content = fs.readFileSync(path.resolve("." + req.url)).toString();
} catch (_error) {
reason = _error;
return notFound(reason);
}
}
console.log(" " + (colorize('200', 'green')) + " " + (colorize('GET', 'cyan')) + " " + req.url);
return res.send(content);
});
port = process.env.PORT || 5000;
app.listen(port);
console.log(" server listening on port " + (port.toString().cyan));
if (options.phantomjs) {
console.log(" running tests on phantomjs");
phantom = spawn(options.phantomjsExecutable, ['./lib/spectacular_phantomjs.js', port]);
phantom.stdout.on('data', function(data) {
return util.print(data.toString());
});
phantom.stderr.on('data', function(data) {
return util.print(data.toString());
});
phantom.on('exit', function(status) {
return process.exit(status);
});
}
if (options.slimerjs) {
console.log(" running tests on slimerjs");
phantom = spawn(options.slimerjsExecutable, ['./src/spectacular_slimerjs.coffee', port]);
phantom.stdout.on('data', function(data) {
return util.print(data.toString());
});
phantom.stderr.on('data', function(data) {
return util.print(data.toString());
});
phantom.on('exit', function(status) {
return process.exit(status);
});
}
return defer.promise;
};