Skip to content

Handle errors correctly based on suite.options.error and the number of parameters expected by the vow #263

Merged
merged 24 commits into from May 13, 2014
Select commit
+103 −22
View
4 .gitignore
@@ -1,4 +1,8 @@
node_modules
.idea
.nul
+.hgignore
+.hgsubstate
+.hg
+.hgsub
test/npm-debug.log
View
4 lib/vows.js
@@ -64,6 +64,9 @@ function addVow(vow) {
// always set a listener on the event
this.on(event, function () {
+ if(vow.caughtError)
+ return;
+
var args = Array.prototype.slice.call(arguments);
// If the vow is a sub-event then we know it is an
// emitted event. So I don't muck with the arguments
@@ -80,6 +83,7 @@ function addVow(vow) {
if (event !== 'error') {
this.on("error", function (err) {
+ vow.caughtError = true;
if (vow.callback.length >= 2 || !batch.suite.options.error) {
runTest(arguments, this.ctx);
} else {
View
2 lib/vows/extras.js
@@ -1,6 +1,6 @@
var events = require('events');
//
-// Wrap a Node.js style async function into an EventEmmitter
+// Wrap a Node.js style async function into an EventEmitter
//
this.prepare = function (obj, targets) {
targets.forEach(function (target) {
View
7 lib/vows/reporters/xunit.js
@@ -4,7 +4,9 @@
// added, see: http://ant.1045680.n5.nabble.com/schema-for-junit-xml-output-td1375274.html
//
-var puts = require('util').puts;
+var options = { tail: '\n', raw: true };
+var console = require('../../vows/console');
+var puts = console.puts(options);
var buffer = [],
curSubject = null;
@@ -47,6 +49,9 @@ function cdata(data) {
}
this.name = 'xunit';
+this.setStream = function (s) {
+ options.stream = s;
+};
this.report = function (data) {
var event = data[1];
View
23 lib/vows/suite.js
@@ -129,13 +129,14 @@ this.Suite.prototype = new(function () {
}
// Run the topic, passing the previous context topics
- // If topic `throw`s an exception, pass it down as a value
try {
topic = topic.apply(ctx.env, ctx.topics);
}
+ // If an unexpected error occurs in the topic, set the return
+ // value to 'undefined' and call back with the error
catch (ex) {
- if(/ReferenceError/.test(ex)) throw ex;
- topic = ex;
+ ctx.env.callback(ex);
+ topic = undefined;
}
if (typeof(topic) === 'undefined') { ctx._callback = true }
@@ -229,13 +230,17 @@ this.Suite.prototype = new(function () {
if (topic &&
ctx.name !== 'on' &&
(!topic._vowsEmitedEvents || !topic._vowsEmitedEvents.hasOwnProperty(ctx.event))) {
- topic.on(ctx.event, function (ctx) {
- return function (val) {
- return run(new(Context)(vow, ctx, env), lastTopic);
+ var runInnerContext = function(ctx){
+ return function(val){
+ return run(new (Context)(vow, ctx, env), lastTopic);
};
- }(ctx));
- } else {
- run(new(Context)(vow, ctx, env), lastTopic);
+ }(ctx);
+ topic.on(ctx.event, runInnerContext);
+ // Run an inner context if the outer context fails, too.
+ topic.on('error', runInnerContext);
+ }
+ else {
+ run(new (Context)(vow, ctx, env), lastTopic);
}
}
});
View
75 test/vows-error-test.js
@@ -2,7 +2,8 @@ var path = require('path'),
events = require('events'),
assert = require('assert'),
fs = require('fs'),
- vows = require('../lib/vows');
+ vows = require('../lib/vows'),
+ silent = require('../lib/vows/reporters/silent');
function doSomethingAsync(callback) {
var err = null;
@@ -48,4 +49,74 @@ vows.describe('vows/error').addBatch({
assert.equal(testValue, 'a');
}
}
-}).export(module)
+}).export(module)
+
+vows.describe('Error Handling').addBatch({
+ "A topic with a function that errors": {
+ topic: function() {
+ throw("Something wrong here");
+ },
+ "should return an error to a vow with two parameters": function(e, data) {
+ assert.equal(e, "Something wrong here");
+ }
+ },
+ "A topic with a built-in error": {
+ topic: function() {
+ bad.bad;
+ },
+ "should return an error to a vow with two parameters": function(e, data) {
+ assert(e instanceof Error, "Return value " + e + " wasn't an Error.");
+ }
+ },
+ "The previous two topics run in their own suite," : {
+ "connected to two vows expecting one argument each" : {
+ topic: function(){
+ vows.describe().addBatch({
+ "A topic with a function that errors": {
+ topic: function() {
+ throw("Something wrong here");
+ },
+ "should record the error in the test results" : function(data) {
+ assert.ok(!data);
+ }
+ //» An unexpected error was caught: "Something wrong here"
+ },
+ "A topic with a built-in error": {
+ topic: function() {
+ bad.bad;
+ },
+ "should record the error in the test results" : function(data) {
+ assert.ok(!data);
+ }
+ //» An unexpected error was caught: ReferenceError: bad is not defined
+ }
+ }).run({reporter : silent}, this.callback);
+ },
+ "should have an errored count of two" : function(results, unused) {
+ assert.equal(results.errored, 2);
+ },
+ "should have a total count of two" : function(results, unused) {
+ assert.equal(results.total, 2);
+ },
+ "should have an honored count of zero" : function(results, unused){
+ assert.equal(results.honored, 0);
+ }
+ }
+ },
+ "A topic with an error in it" : {
+ topic : function(){
+ throw('awesome');
+ },
+ "should error" : function(error, result){
+ assert.equal(error, 'awesome');
+ },
+ "containing a subtopic" : {
+ topic : function(){
+ return 52;
+ },
+ "should reach a vow in the subtopic" : function(){
+ }
+ }
+ }
+}).export(module);
+
View
10 test/vows-test.js
@@ -168,15 +168,7 @@ vows.describe("Vows").addBatch({
"should work as expected": function (topic) {
assert.isFunction(topic);
assert.equal(topic(), 42);
- },
- }
- },
- "A topic with a function that errors": {
- topic: function() {
- throw("Something wrong here");
- },
- "should error out": function(topic) {
- assert.equal(topic, "Something wrong here");
+ }
}
},
"A topic emitting an error": {
Something went wrong with that request. Please try again.