Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' of git://github.com/hpychan/vows

Conflicts:
	package.json
  • Loading branch information...
commit 858ed583fbd695776a65b622e8ff8d60cec4f789 2 parents 30c6acc + e9094fe
Henry Chan authored
View
7 README.md
@@ -37,3 +37,10 @@ documentation
Head over to <http://vowsjs.org>
+authors
+-------
+
+Alexis Sellier <<alexis@cloudhead.io>>, Charlie Robbins,
+
+*...and many others*
+
View
157 bin/vows
@@ -39,7 +39,7 @@ var vows = require('../lib/vows');
var cutils = require('../lib/vows/console');
var stylize = require('../lib/vows/console').stylize;
var _reporter = require('../lib/vows/reporters/dot-matrix'), reporter = {
- name: _reporter.name,
+ name: _reporter.name
};
var _coverage;
@@ -50,6 +50,7 @@ var help = [
" -v, --verbose Enable verbose output",
" -w, --watch Watch mode",
" -s, --silent Don't report",
+ " -i, --isolate Run each test in it's own vows process",
" -m PATTERN Only run tests matching the PATTERN string",
" -r PATTERN Only run tests matching the PATTERN regexp",
" --json Use JSON reporter",
@@ -58,6 +59,8 @@ var help = [
" --xunit Use xUnit reporter",
" --cover-plain Print plain coverage map if detected",
" --cover-html Write coverage map to \"coverage.html\"",
+ " --cover-json Write unified coverage map to \"coverage.json\"",
+ " --cover-emma Write unified coverage map to \"coverage.emma\"",
//" --no-color Don't use terminal colors",
" --version Show version",
" -h, --help You're staring at it"
@@ -67,7 +70,8 @@ var options = {
reporter: reporter,
matcher: /.*/,
watch: false,
- coverage: false
+ coverage: false,
+ isolate: false
};
var files = [];
@@ -103,15 +107,13 @@ while (arg = argv.shift()) {
options[arg] = true;
} else {
switch (arg) {
- case 'i':
- case 'I':
- case 'include':
- if (arg = argv.shift()) {
- require.paths.unshift(arg);
- } else {
- throw new Error('--include requires a path');
- }
- break;
+ case 'include':
+ if (arg = argv.shift()) {
+ require.paths.unshift(arg);
+ } else {
+ throw new Error('--include requires a path');
+ }
+ break;
case 'json':
_reporter = require('../lib/vows/reporters/json');
break;
@@ -136,6 +138,14 @@ while (arg = argv.shift()) {
options.coverage = true;
_coverage = require('../lib/vows/coverage/report-html');
break;
+ case 'cover-json':
+ options.coverage = true;
+ _coverage = require('../lib/vows/coverage/report-json');
+ break;
+ case 'cover-emma':
+ options.coverage = true;
+ _coverage = require('../lib/vows/coverage/report-emma');
+ break;
case 'verbose':
case 'v':
options.verbose = true;
@@ -144,6 +154,13 @@ while (arg = argv.shift()) {
case 'w':
options.watch = true;
break;
+ case 'supress-stdout':
+ options.supressStdout = true;
+ break;
+ case 'isolate':
+ case 'i':
+ options.isolate = true;
+ break;
case 'no-color':
options.nocolor = true;
break;
@@ -163,6 +180,11 @@ while (arg = argv.shift()) {
}
}
+if (options.supressStdout) {
+ _reporter.setStream && _reporter.setStream(process.stdout);
+ process.stdout = fs.createWriteStream('/dev/null');
+}
+
if (options.watch) {
options.reporter = reporter = require('../lib/vows/reporters/watch');
}
@@ -205,10 +227,14 @@ if (! options.watch) {
_reporter.report(data, filename);
break;
case 'end':
- (options.verbose || _reporter.name === 'json') && _reporter.report(data);
+ (options.verbose || _reporter.name === 'json') &&
+ _reporter.report(data);
break;
case 'finish':
- options.verbose ? _reporter.print('\n') : _reporter.print(' ');
+ options.verbose ?
+ _reporter.print('\n')
+ :
+ _reporter.print(' ');
break;
}
};
@@ -216,23 +242,33 @@ if (! options.watch) {
reporter.print = _reporter.print;
files = args.map(function (a) {
- return path.join(process.cwd(), a.replace(fileExt, ''));
+ return (!a.match(/^\//))
+ ? path.join(process.cwd(), a.replace(fileExt, ''))
+ : a.replace(fileExt, '');
});
var allTests = function() {
- runSuites(importSuites(files), function (results) {
- var status = results.errored ? 2 : (results.broken ? 1 : 0);
+ runSuites(importSuites(files), function (results) {
+ var status = results.errored ? 2 : (results.broken ? 1 : 0);
- !options.verbose && _reporter.print('\n');
- msg('runner', 'finish');
- _reporter.report(['finish', results], {
- write: function (str) {
- util.print(str.replace(/^\n\n/, '\n'));
- }
- });
+ !options.verbose && _reporter.print('\n');
+ msg('runner', 'finish');
+ _reporter.report(['finish', results], {
+ write: function (str) {
+ util.print(str.replace(/^\n\n/, '\n'));
+ }
+ });
+ try {
+ if (options.coverage === true && _$jscoverage !== undefined) {
+ _coverage.report(_$jscoverage);
+ }
+ } catch (err) {
+ // ignore the undefined jscoverage
+ }
+ if (process.stdout.write('')) { // Check if stdout is drained
if (options.coverage === true && _$jscoverage !== undefined) {
- _coverage.report(_$jscoverage);
+ _coverage.report(_$jscoverage);
}
if (process.stdout.write('')) { // Check if stdout is drained
process.exit(status);
@@ -241,18 +277,19 @@ if (! options.watch) {
process.exit(status);
});
}
- });
+ }
+ });
};
- if (options.coverage === true ) {
- childProcess.exec('rm -fr lib-cov && jscoverage lib lib-cov', function(err){
- if (err) throw err;
- require.paths.unshift('lib-cov');
- allTests();
- })
- } else {
+ if (options.coverage === true ) {
+ childProcess.exec('rm -fr lib-cov && jscoverage lib lib-cov', function(err){
+ if (err) throw err;
+ require.paths.unshift('lib-cov');
allTests();
+ })
+ } else {
+ allTests();
}
} else {
//
@@ -402,10 +439,62 @@ function runSuites(suites, callback) {
function importSuites(files) {
msg(options.watcher ? 'watcher' : 'runner', 'loading', files);
- return files.reduce(function (suites, f) {
+ var spawn = require('child_process').spawn;
+
+ function cwdname(f) {
+ return f.replace(process.cwd() + '/', '') + '.js';
+ }
+
+ function wrapSpawn(f) {
+ f = cwdname(f);
+ return function (options, callback) {
+ var args = [process.argv[1], '--json', '--supress-stdout', f],
+ p = spawn(process.argv[0], args),
+ result;
+
+ p.on('exit', function (code) {
+ callback(
+ !result ?
+ {errored: 1, total: 1}
+ :
+ result
+ );
+ });
+
+ var buffer = [];
+ p.stdout.on('data', function (data) {
+ data = data.toString().split(/\n/g);
+ if (data.length == 1) {
+ buffer.push(data[0]);
+ } else {
+ data[0] = buffer.concat(data[0]).join('');
+ buffer = [data.pop()];
+
+ data.forEach(function (data) {
+ if (data) {
+ data = JSON.parse(data);
+ if (data && data[0] === 'finish') {
+ result = data[1];
+ } else {
+ reporter.report(data);
+ }
+ }
+ });
+ }
+ });
+
+ p.stderr.pipe(process.stderr);
+ }
+ }
+
+ return files.reduce(options.isolate ? function (suites, f) {
+ return suites.concat({
+ run: wrapSpawn(f)
+ });
+ } : function (suites, f) {
var obj = require(f);
return suites.concat(Object.keys(obj).map(function (s) {
- obj[s]._filename = f.replace(process.cwd() + '/', '') + '.js';
+ obj[s]._filename = cwdname(f);
return obj[s];
}));
}, [])
View
10 lib/assert/macros.js
@@ -104,6 +104,11 @@ assert.isEmpty = function (actual, message) {
assert.fail(actual, 0, message || "expected {actual} to be empty", "length", assert.isEmpty);
}
};
+assert.isNotEmpty = function (actual, message) {
+ if ((isObject(actual) && Object.keys(actual).length === 0) || actual.length === 0) {
+ assert.fail(actual, 0, message || "expected {actual} to be not empty", "length", assert.isNotEmpty);
+ }
+};
assert.length = function (actual, expected, message) {
if (actual.length !== expected) {
@@ -152,6 +157,11 @@ assert.isUndefined = function (actual, message) {
assert.fail(actual, undefined, message || "expected {actual} to be {expected}", "===", assert.isUndefined);
}
};
+assert.isDefined = function (actual, message) {
+ if(actual === undefined) {
+ assert.fail(actual, 0, message || "expected {actual} to be defined", "===", assert.isDefined);
+ }
+};
assert.isString = function (actual, message) {
assertTypeOf(actual, 'string', message || "expected {actual} to be a String", assert.isString);
};
View
2  lib/vows.js
@@ -73,7 +73,7 @@ function addVow(vow) {
}).on("error", function (err) {
if (vow.callback.length >= 2 || !batch.suite.options.error) {
- runTest([err], this.ctx);
+ runTest(arguments, this.ctx);
} else {
output('errored', { type: 'promise', error: err.stack || err.message || JSON.stringify(err) });
}
View
50 lib/vows/console.js
@@ -32,12 +32,18 @@ var $ = this.$ = function (str) {
this.puts = function (options) {
var stylize = exports.stylize;
+ options.stream || (options.stream = process.stdout);
+ options.tail = options.tail || '';
+
return function (args) {
- args = Array.prototype.slice.call(arguments).map(function (a) {
- return a.replace(/`([^`]+)`/g, function (_, capture) { return stylize(capture, 'italic') })
- .replace(/\*([^*]+)\*/g, function (_, capture) { return stylize(capture, 'bold') });
- });
- return options.stream.write(args.join('\n') + '\n');
+ args = Array.prototype.slice.call(arguments);
+ if (!options.raw) {
+ args = args.map(function (a) {
+ return a.replace(/`([^`]+)`/g, function (_, capture) { return stylize(capture, 'italic') })
+ .replace(/\*([^*]+)\*/g, function (_, capture) { return stylize(capture, 'bold') });
+ });
+ }
+ return options.stream.write(args.join('\n') + options.tail);
};
};
@@ -73,7 +79,7 @@ this.result = function (event) {
time = ' (' + event.time.toFixed(3) + 's)';
time = this.stylize(time, 'grey');
}
- buffer.push(header + result + time);
+ buffer.push(header + result + time + '\n');
return buffer;
};
@@ -91,3 +97,35 @@ this.error = function (obj) {
return string;
};
+
+this.contextText = function (event) {
+ return ' ' + event;
+};
+
+this.vowText = function (event) {
+ var buffer = [];
+
+ buffer.push(' ' + {
+ honored: '',
+ broken: '',
+ errored: '',
+ pending: ' - '
+ }[event.status] + this.stylize(event.title, ({
+ honored: 'green',
+ broken: 'yellow',
+ errored: 'red',
+ pending: 'cyan'
+ })[event.status]));
+
+ if (event.status === 'broken') {
+ buffer.push(' » ' + event.exception);
+ } else if (event.status === 'errored') {
+ if (event.exception.type === 'promise') {
+ buffer.push(' » ' + this.stylize("An unexpected error was caught: " +
+ this.stylize(event.exception.error, 'bold'), 'red'));
+ } else {
+ buffer.push(' ' + this.stylize(event.exception, 'red'));
+ }
+ }
+ return buffer.join('\n');
+};
View
2  lib/vows/context.js
@@ -28,7 +28,7 @@ this.Context = function (vow, ctx, env) {
if (typeof(e) === 'boolean' && args.length === 0) {
that.emitter.emit.call(that.emitter, 'success', e);
} else {
- if (e) { that.emitter.emit.call(that.emitter, 'error', e) }
+ if (e) { that.emitter.emit.apply(that.emitter, ['error', e].concat(args)) }
else { that.emitter.emit.apply(that.emitter, ['success'].concat(args)) }
}
};
View
147 lib/vows/coverage/report-emma.js
@@ -0,0 +1,147 @@
+var sys = require('sys'),
+ fs = require('fs'),
+ file = require('./file');
+
+this.name = 'coverage-report-emma';
+
+function xmlEnc(value) {
+ return !value ? value : String(value).replace(/&/g, "&amp;")
+ .replace(/>/g, "&gt;")
+ .replace(/</g, "&lt;")
+ .replace(/"/g, "&quot;")
+ .replace(/\u001b\[\d{1,2}m/g, '');
+}
+
+function tag(name, attribs, single, content) {
+ var strAttr = [], t, end = '>';
+ for (var attr in attribs) {
+ if (attribs.hasOwnProperty(attr)) {
+ strAttr.push(attr + '="' + xmlEnc(attribs[attr]) + '"');
+ }
+ }
+ if (single) {
+ end = ' />';
+ }
+ if (strAttr.length) {
+ t = '<' + name + ' ' + strAttr.join(' ') + end;
+ } else {
+ t = '<' + name + end;
+ }
+ if (typeof content !== 'undefined') {
+ return t + content + '</' + name + end;
+ }
+ return t;
+}
+
+function end(name) {
+ return '</' + name + '>';
+}
+
+function cdata(data) {
+ return '<![CDATA[' + xmlEnc(data) + ']]>';
+}
+
+/**
+ * coverageMap coverage info for each file
+ */
+this.report = function (coverageMap) {
+ var output = {
+ meta: {
+ "generator": "vowsjs",
+ "generated": new Date().toString(),
+ "instrumentation": "node-jscoverage",
+ "file-version": "1.0"
+ },
+ files: [ ],
+ coverage: [ ]
+ };
+
+ for (var filename in coverageMap) {
+ if (coverageMap.hasOwnProperty(filename)) {
+ // get data for the file
+ var data = file.coverage(filename, coverageMap[filename]);
+
+ var coverage = {
+ file: filename,
+ coverage: data.coverage.toFixed(2),
+ hits: data.hits,
+ misses: data.misses,
+ sloc: data.sloc,
+ source: { }
+ };
+
+ for (var i = 0; i < data.source.length; i++) {
+ coverage.source[i + 1] = {
+ line: data.source[i].line,
+ coverage: data.source[i].coverage
+ };
+ }
+
+ output.coverage.push(coverage);
+
+ output.files.push(filename);
+ }
+ }
+ var totalsloc = 0;
+ var totalhits = 0;
+ for ( var i = 0; i < output.coverage.length; i++) {
+ totalsloc += output.coverage[i].sloc;
+ totalhits += output.coverage[i].hits;
+ }
+
+ var buffer = [];
+ buffer.push(tag('report', {}, false));
+ buffer.push(tag('stats', {}, false));
+ buffer.push(tag('packages', { value: 1 }, true));
+ buffer.push(tag('classes', { value: 1 }, true));
+ buffer.push(tag('srcfiles', { value: output.files.length }, true));
+ buffer.push(tag('srclines', { value: totalsloc }, true));
+ buffer.push(end('stats'));
+
+ buffer.push(tag('data', {}, false));
+ // all
+ buffer.push(tag('all', { name : 'all classes'}, false));
+ buffer.push(tag('coverage', { type : 'class, %', value : '100% (1/1)'}, true) );
+ buffer.push(tag('coverage', { type : 'method, %', value : '100% (1/1)'}, true) );
+ buffer.push(tag('coverage', { type : 'block, %', value : '100% (1/1)'}, true) );
+ buffer.push(tag('coverage', { type : 'line, %', value : (totalhits*1.0/totalsloc * 100.0).toFixed(2) + '% ('+totalhits+'/'+totalsloc+')'}, true) );
+
+ // package
+ buffer.push(tag('package', {name: '{root}'}, false));
+ buffer.push(tag('coverage', { type : 'class, %', value : '100% (1/1)'}, true) );
+ buffer.push(tag('coverage', { type : 'method, %', value : '100% (1/1)'}, true) );
+ buffer.push(tag('coverage', { type : 'block, %', value : '100% (1/1)'}, true) );
+ buffer.push(tag('coverage', { type : 'line, %', value : (totalhits*1.0/totalsloc * 100.0).toFixed(2) + '% ('+totalhits+'/'+totalsloc+')'}, true) );
+
+ for ( var i = 0; i < output.coverage.length; i++) {
+ var sloc = output.coverage[i].sloc;
+ var hits = output.coverage[i].hits;
+ var filename = output.coverage[i].file;
+
+ buffer.push(tag('srcfile', { name : filename }, false) );
+ buffer.push(tag('coverage', { type : 'class, %', value : '100% (1/1)'}, true) );
+ buffer.push(tag('coverage', { type : 'method, %', value : '100% (1/1)'}, true) );
+ buffer.push(tag('coverage', { type : 'block, %', value : '100% (1/1)'}, true) );
+ buffer.push(tag('coverage', { type : 'line, %', value : (hits*1.0/sloc * 100.0).toFixed(2) + '% ('+hits+'/'+sloc+')'}, true) );
+ buffer.push(end('srcfile'));
+ }
+
+ buffer.push(end('package'));
+
+ buffer.push(end('all'));
+ buffer.push(end('data'));
+
+
+ buffer.push(end('report'));
+
+ buffer.unshift('<!-- EMMA v2.0.4015 (stable) report, generated '+ output.meta.generated + ' by ' + output.meta.generator + ' -->');
+
+ try {
+ out = fs.openSync("coverage.emma", "w");
+ fs.writeSync(out, buffer.join('\n'));
+ fs.close(out);
+ } catch (error) {
+ sys.print("Error: Unable to write to file coverage.emma\n");
+ return;
+ }
+};
View
54 lib/vows/coverage/report-json.js
@@ -0,0 +1,54 @@
+var sys = require('sys'),
+ fs = require('fs'),
+ file = require('./file');
+
+this.name = 'coverage-report-json';
+
+this.report = function (coverageMap) {
+ var output = {
+ meta: {
+ "generator": "vowsjs",
+ "generated": new Date().toString(),
+ "instrumentation": "node-jscoverage",
+ "file-version": "1.0"
+ },
+ files: [ ],
+ coverage: [ ]
+ };
+
+
+ for (var filename in coverageMap) {
+ if (coverageMap.hasOwnProperty(filename)) {
+ var data = file.coverage(filename, coverageMap[filename]);
+
+ var coverage = {
+ file: filename,
+ coverage: data.coverage.toFixed(2),
+ hits: data.hits,
+ misses: data.misses,
+ sloc: data.sloc,
+ source: { }
+ };
+
+ for (var i = 0; i < data.source.length; i++) {
+ coverage.source[i + 1] = {
+ line: data.source[i].line,
+ coverage: data.source[i].coverage
+ };
+ }
+
+ output.coverage.push(coverage);
+
+ output.files.push(filename);
+ }
+ }
+
+ try {
+ out = fs.openSync("coverage.json", "w");
+ fs.writeSync(out, JSON.stringify(output));
+ fs.close(out);
+ } catch (error) {
+ sys.print("Error: Unable to write to file coverage.json\n");
+ return;
+ }
+};
View
2  lib/vows/extras.js
@@ -13,7 +13,7 @@ this.prepare = function (obj, targets) {
args.push(function (err /* [, data] */) {
var args = Array.prototype.slice.call(arguments, 1);
- if (err) { ee.emit('error', err) }
+ if (err) { ee.emit.apply(ee, ['error', err].concat(args)) }
else { ee.emit.apply(ee, ['success'].concat(args)) }
});
fun.apply(obj, args);
View
40 lib/vows/reporters/dot-matrix.js
@@ -1,26 +1,24 @@
-
-var sys = require('sys');
-
-var options = {};
-var console = require('../../vows/console');
-var spec = require('./spec');
-var stylize = console.stylize,
+var options = { tail: '' },
+ console = require('../../vows/console'),
+ stylize = console.stylize,
puts = console.puts(options);
//
// Console reporter
//
-var stream, messages = [], lastContext;
+var messages = [], lastContext;
this.name = 'dot-matrix';
+this.setStream = function (s) {
+ options.stream = s;
+};
+
this.reset = function () {
messages = [];
lastContext = null;
};
-this.report = function (data, s) {
+this.report = function (data) {
var event = data[1];
- options.stream = typeof(s) === 'object' ? s : process.stdout;
-
switch (data[0]) {
case 'subject':
// messages.push(stylize(event, 'underline') + '\n');
@@ -29,32 +27,32 @@ this.report = function (data, s) {
break;
case 'vow':
if (event.status === 'honored') {
- sys.print(stylize('·', 'green'));
+ puts(stylize('·', 'green'));
} else if (event.status === 'pending') {
- sys.print(stylize('-', 'cyan'));
+ puts(stylize('-', 'cyan'));
} else {
if (lastContext !== event.context) {
lastContext = event.context;
- messages.push(spec.contextText(event.context));
+ messages.push(' ' + event.context);
}
if (event.status === 'broken') {
- sys.print(stylize('', 'yellow'));
- messages.push(spec.vowText(event));
+ puts(stylize('', 'yellow'));
+ messages.push(console.vowText(event));
} else if (event.status === 'errored') {
- sys.print(stylize('', 'red'));
- messages.push(spec.vowText(event));
+ puts(stylize('', 'red'));
+ messages.push(console.vowText(event));
}
messages.push('');
}
break;
case 'end':
- sys.print(' ');
+ puts(' ');
break;
case 'finish':
if (messages.length) {
puts('\n\n' + messages.join('\n'));
} else {
- sys.print('\n');
+ puts('');
}
puts(console.result(event).join('\n'));
break;
@@ -65,5 +63,5 @@ this.report = function (data, s) {
};
this.print = function (str) {
- sys.print(str);
+ puts(str);
};
View
10 lib/vows/reporters/json.js
@@ -1,10 +1,16 @@
-var sys = require('sys');
+var options = { tail: '\n', raw: true };
+var console = require('../../vows/console');
+var puts = console.puts(options);
+
//
// Console JSON reporter
//
this.name = 'json';
+this.setStream = function (s) {
+ options.stream = s;
+};
this.report = function (obj) {
- sys.puts(JSON.stringify(obj));
+ puts(JSON.stringify(obj));
};
this.print = function (str) {};
View
44 lib/vows/reporters/spec.js
@@ -1,6 +1,6 @@
var sys = require('sys');
-var options = {};
+var options = { tail: '\n' };
var console = require('../../vows/console');
var stylize = console.stylize,
puts = console.puts(options);
@@ -9,10 +9,12 @@ var stylize = console.stylize,
//
this.name = 'spec';
-this.report = function (data, s) {
+this.setStream = function (s) {
+ options.stream = s;
+};
+this.report = function (data) {
var event = data[1];
- options.stream = typeof(s) === 'object' ? s : process.stdout;
buffer = [];
switch (data[0]) {
@@ -20,10 +22,10 @@ this.report = function (data, s) {
puts('\n' + stylize(event, 'bold') + '\n');
break;
case 'context':
- puts(this.contextText(event));
+ puts(console.contextText(event));
break;
case 'vow':
- puts(this.vowText(event));
+ puts(console.vowText(event));
break;
case 'end':
sys.print('\n');
@@ -37,38 +39,6 @@ this.report = function (data, s) {
}
};
-this.contextText = function (event) {
- return ' ' + event;
-};
-
-this.vowText = function (event) {
- var buffer = [];
-
- buffer.push(' ' + {
- honored: '',
- broken: '',
- errored: '',
- pending: ' - '
- }[event.status] + stylize(event.title, ({
- honored: 'green',
- broken: 'yellow',
- errored: 'red',
- pending: 'cyan'
- })[event.status]));
-
- if (event.status === 'broken') {
- buffer.push(' » ' + event.exception);
- } else if (event.status === 'errored') {
- if (event.exception.type === 'promise') {
- buffer.push(' » ' + stylize("An unexpected error was caught: " +
- stylize(event.exception.error, 'bold'), 'red'));
- } else {
- buffer.push(' ' + stylize(event.exception, 'red'));
- }
- }
- return buffer.join('\n');
-};
-
this.print = function (str) {
sys.print(str);
};
View
9 lib/vows/reporters/watch.js
@@ -11,22 +11,23 @@ var stylize = console.stylize,
var lastContext;
this.name = 'watch';
+this.setStream = function (s) {
+ options.stream = s;
+};
this.reset = function () {
lastContext = null;
};
this.report = function (data) {
var event = data[1];
- options.stream = process.stdout;
-
switch (data[0]) {
case 'vow':
if (['honored', 'pending'].indexOf(event.status) === -1) {
if (lastContext !== event.context) {
lastContext = event.context;
- puts(spec.contextText(event.context));
+ puts(console.contextText(event.context));
}
- puts(spec.vowText(event));
+ puts(console.vowText(event));
puts('');
}
break;
View
2  lib/vows/suite.js
@@ -142,7 +142,7 @@ this.Suite.prototype = new(function () {
// If the topic doesn't return an event emitter (such as a promise),
// we create it ourselves, and emit the value on the next tick.
- if (! (topic instanceof events.EventEmitter)) {
+ if (! (topic && topic.constructor === events.EventEmitter)) {
ctx.emitter = new(events.EventEmitter);
if (! ctx._callback) {
View
16 test/assert-test.js
@@ -16,6 +16,10 @@ vows.describe('vows/assert').addBatch({
assert.length("hello world", 11);
assert.length([1, 2, 3], 3);
},
+ "`isDefined`": function (assert) {
+ assert.isDefined(null);
+ assertError(assert.isDefined, undefined);
+ },
"`include`": function (assert) {
assert.include("hello world", "world");
assert.include([0, 42, 0], 42);
@@ -78,6 +82,10 @@ vows.describe('vows/assert').addBatch({
assert.isUndefined(undefined);
assertError(assert.isUndefined, null);
},
+ "`isDefined`": function (assert) {
+ assert.isDefined(null);
+ assertError(assert.isDefined, undefined);
+ },
"`isNull`": function (assert) {
assert.isNull(null);
assertError(assert.isNull, 0);
@@ -101,6 +109,14 @@ vows.describe('vows/assert').addBatch({
assert.isEmpty({});
assert.isEmpty([]);
assert.isEmpty("");
+ },
+ "`isNotEmpty`": function (assert) {
+ assert.isNotEmpty({goo:true});
+ assert.isNotEmpty([1]);
+ assert.isNotEmpty(" ");
+ assertError(assert.isNotEmpty, {});
+ assertError(assert.isNotEmpty, []);
+ assertError(assert.isNotEmpty, "");
}
}
}).export(module);
View
18 test/fixtures/isolate/failing.js
@@ -0,0 +1,18 @@
+var vows = require('../../../lib/vows'),
+ assert = require('assert');
+
+var obvious;
+vows.describe('failing').addBatch({
+ 'Obvious test': obvious = {
+ topic: function () {
+ this.callback(null, false);
+ },
+ 'should work': function (result) {
+ assert.ok(result);
+ }
+ // but it won't
+ },
+ 'Obvious test #2': obvious,
+ 'Obvious test #3': obvious,
+ 'Obvious test #4': obvious
+}).export(module);
View
18 test/fixtures/isolate/log.js
@@ -0,0 +1,18 @@
+var vows = require('../../../lib/vows'),
+ assert = require('assert');
+
+var obvious;
+vows.describe('stderr').addBatch({
+ 'Obvious test': obvious = {
+ topic: function () {
+ this.callback(null, true);
+ },
+ 'should work': function (result) {
+ console.log('oh no!');
+ assert.ok(result);
+ }
+ },
+ 'Obvious test #2': obvious,
+ 'Obvious test #3': obvious,
+ 'Obvious test #4': obvious
+}).export(module);
View
17 test/fixtures/isolate/passing.js
@@ -0,0 +1,17 @@
+var vows = require('../../../lib/vows'),
+ assert = require('assert');
+
+var obvious;
+vows.describe('passing').addBatch({
+ 'Obvious test': obvious = {
+ topic: function () {
+ this.callback(null, true);
+ },
+ 'should work': function (result) {
+ assert.ok(result);
+ }
+ },
+ 'Obvious test #2': obvious,
+ 'Obvious test #3': obvious,
+ 'Obvious test #4': obvious
+}).export(module);
View
18 test/fixtures/isolate/stderr.js
@@ -0,0 +1,18 @@
+var vows = require('../../../lib/vows'),
+ assert = require('assert');
+
+var obvious;
+vows.describe('stderr').addBatch({
+ 'Obvious test': obvious = {
+ topic: function () {
+ this.callback(null, true);
+ },
+ 'should work': function (result) {
+ console.error('oh no!');
+ assert.ok(result);
+ }
+ },
+ 'Obvious test #2': obvious,
+ 'Obvious test #3': obvious,
+ 'Obvious test #4': obvious
+}).export(module);
View
140 test/isolate-test.js
@@ -0,0 +1,140 @@
+var vows = require('../lib/vows'),
+ assert = require('assert'),
+ path = require('path'),
+ exec = require('child_process').exec;
+
+function generateTopic(args, file) {
+ return function () {
+ var cmd = './bin/vows' + ' -i ' + (args || '') +
+ ' ./test/fixtures/isolate/' + file,
+ options = {cwd: path.resolve(__dirname + '/../')},
+ callback = this.callback;
+
+ exec(cmd, options, function (err, stdout, stderr) {
+ callback(null, {
+ err: err,
+ stdout: stdout,
+ stderr: stderr
+ });
+ });
+ }
+};
+
+function assertExecOk(r) {
+ assert.isNull(r.err);
+}
+
+function assertExecNotOk(r) {
+ assert.isNotNull(r.err);
+}
+
+function parseResults(stdout) {
+ return stdout.split(/\n/g).map(function (s) {
+ if (!s) return;
+ return JSON.parse(s);
+ }).filter(function (s) {return s});
+}
+
+function assertResultTypePresent(results, type) {
+ assert.ok(results.some(function (result) {
+ return result[0] == type;
+ }));
+}
+
+function assertResultsFinish(results, expected) {
+ var finish = results[results.length - 1];
+ assert.equal(finish[0], 'finish');
+
+ finish = finish[1];
+
+ Object.keys(expected).forEach(function (key) {
+ assert.equal(finish[key], expected[key]);
+ });
+}
+
+vows.describe('vows/isolate').addBatch({
+ 'Running vows with -i flag for test/fixtures/isolate/': {
+ 'passing.js': {
+ 'with default reporter': {
+ topic: generateTopic(null, 'passing.js'),
+ 'should be ok': assertExecOk
+ },
+ 'with json reporter': {
+ topic: generateTopic('--json', 'passing.js'),
+ 'should be ok': assertExecOk,
+ 'should have correct output': function (r) {
+ var results = parseResults(r.stdout)
+
+ assertResultTypePresent(results, 'subject');
+ assertResultTypePresent(results, 'end');
+
+ assertResultsFinish(results, {
+ total: 4,
+ honored: 4
+ });
+ }
+ }
+ },
+ 'failing.js': {
+ 'with json reporter': {
+ topic: generateTopic('--json', 'failing.js'),
+ 'should be not ok': assertExecNotOk,
+ 'should have correct output though': function (r) {
+ var results = parseResults(r.stdout);
+
+ assertResultsFinish(results, {
+ total: 4,
+ broken: 4
+ });
+ }
+ }
+ },
+ 'stderr.js': {
+ 'with json reporter': {
+ topic: generateTopic('--json', 'stderr.js'),
+ 'should be ok': assertExecOk,
+ 'should have stderr': function (r) {
+ assert.equal(r.stderr,
+ ['oh no!', 'oh no!', 'oh no!', 'oh no!', ''].join('\n'));
+ },
+ 'should have correct output': function (r) {
+ var results= parseResults(r.stdout);
+
+ assertResultsFinish(results, {
+ total: 4,
+ honored: 4
+ });
+ }
+ }
+ },
+ 'log.js': {
+ 'with json reporter': {
+ topic: generateTopic('--json', 'log.js'),
+ 'should be ok': assertExecOk,
+ 'should have correct output': function (r) {
+ var results= parseResults(r.stdout);
+
+ assertResultsFinish(results, {
+ total: 4,
+ honored: 4
+ });
+ }
+ }
+ },
+ 'all tests (*)': {
+ 'with json reporter': {
+ topic: generateTopic('--json', '*'),
+ 'should be not ok': assertExecNotOk,
+ 'should have correct output': function (r) {
+ var results= parseResults(r.stdout);
+
+ assertResultsFinish(results, {
+ total: 16,
+ broken: 4,
+ honored: 12
+ });
+ }
+ }
+ }
+ }
+}).export(module);
View
51 test/vows-error-test.js
@@ -0,0 +1,51 @@
+var path = require('path'),
+ events = require('events'),
+ assert = require('assert'),
+ fs = require('fs'),
+ vows = require('../lib/vows');
+
+function doSomethingAsync(callback) {
+ var err = null;
+ var testValue = 'a';
+
+ process.nextTick(function() {
+ callback(err, testValue);
+ });
+}
+
+function doSomethingAsyncWithError(callback) {
+ var err = true;
+ var testValue = 'a';
+
+ process.nextTick(function() {
+ callback(err, testValue);
+ });
+}
+
+
+vows.describe('vows/error').addBatch({
+ 'Generate success response to async function': {
+ topic: function() {
+ doSomethingAsync(this.callback)
+ },
+ 'Validate success': function(err, testValue) {
+ assert.ok(!err);
+ },
+ 'Validate testValue': function(err, testValue) {
+ assert.equal(testValue, 'a');
+ }
+ },
+
+ 'Generate error response to async function': {
+ topic: function() {
+ doSomethingAsyncWithError(this.callback)
+ },
+ 'Validate error': function(err, testValue) {
+ assert.ok(err);
+ },
+ 'Validate testValue': function(err, testValue) {
+ // This assertion fails. It shouldn't.
+ assert.equal(testValue, 'a');
+ }
+ }
+}).export(module)
View
5 test/vows-test.js
@@ -350,6 +350,11 @@ vows.describe("Vows with teardowns").addBatch({
"And a final vow": function (topic) {
assert.isTrue(topic.flag);
},
+ 'subcontext': {
+ 'nested': function (_, topic) {
+ assert.isTrue(topic.flag);
+ }
+ },
teardown: function (topic) {
topic.flag = false;
},
Please sign in to comment.
Something went wrong with that request. Please try again.