Skip to content

click, wait: include original call stack in error message #137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions lib/browser/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,19 @@ module.exports = {
},

click: function (selector, keys) {
var self = this;
var origCaller = new Error("at");

return this.__custom__(function (operand, done) {
operand.browser.elementByCssSelectorOrNull(selector, done);
}).then(function (element) {
if (!element) {
throw new Error('element ' + selector + ' does not exists');
self.throwWithMessage('element ' + selector + ' does not exists', origCaller);
}
return new Promise(function (resolve, reject) {
element.click(either(reject).or(resolve));
element.click(either(
self.rejectWithMessage('clickError(' + selector + ', ' + keys + ')', origCaller, reject)
).or(resolve));
});
});
},
Expand Down
22 changes: 21 additions & 1 deletion lib/browser/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ var fs = require('fs');

module.exports = {};

module.exports.rejectWithMessage = function(message, origCaller, reject) {
"use strict";

return function(err){
var stack = String(origCaller.stack);
stack = stack.substring(stack.indexOf('\n', stack.indexOf('\n') + 1) + 1);
reject(new Error(message + ' ' + err + '\n' + stack));
};
};

module.exports.throwWithMessage = function(message, err) {
"use strict";

var stack = String(err.stack);
stack = stack.substring(stack.indexOf('\n', stack.indexOf('\n') + 1) + 1);

throw new Error(message + '\n' + stack);
};

module.exports.execute = function (code, args) {
"use strict";

Expand Down Expand Up @@ -155,6 +174,7 @@ module.exports.wait = function (timeout, message, code, args) {
}

var self = this;
var origCaller = new Error("at");

return self.__custom__(function (operand, done) {

Expand Down Expand Up @@ -223,7 +243,7 @@ module.exports.wait = function (timeout, message, code, args) {
// retry after reparing the problem
return retry(function (operand, done) { loadChai(operand.browser, done) });
}
throw err;
self.throwWithMessage("waitError("+err.message+")", origCaller);
});

};
Expand Down
40 changes: 35 additions & 5 deletions lib/meteor/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module.exports = {};

module.exports.promise = function (code, args) {
"use strict";
var origCaller = new Error("at");

var deprecated = false;

Expand All @@ -23,13 +24,14 @@ module.exports.promise = function (code, args) {
var closure = operand.closure;
var context = this;

callDDPMethod(ddpClient, '/gagarin/promise', [ context, closure(), code.toString(), clean(context, args) ], getSetter(context), closure, cb);
callDDPMethod(origCaller, ddpClient, '/gagarin/promise', [ context, closure(), code.toString(), clean(context, args) ], getSetter(context), closure, cb);

});
}

module.exports.execute = function (code, args) {
"use strict";
var origCaller = new Error("at");

var deprecated = false;

Expand All @@ -50,13 +52,14 @@ module.exports.execute = function (code, args) {
var closure = operand.closure;
var context = this;

callDDPMethod(ddpClient, '/gagarin/execute', [ context, closure(), code.toString(), clean(context, args) ], getSetter(context), closure, cb);
callDDPMethod(origCaller, ddpClient, '/gagarin/execute', [ context, closure(), code.toString(), clean(context, args) ], getSetter(context), closure, cb);

});
}

module.exports.wait = function (timeout, message, code, args) {
"use strict";
var origCaller = new Error("at");

var deprecated = false;

Expand All @@ -77,7 +80,7 @@ module.exports.wait = function (timeout, message, code, args) {
var closure = operand.closure;
var context = this;

callDDPMethod(ddpClient, '/gagarin/wait', [ context, closure(), timeout, message, code.toString(), clean(context, args) ], getSetter(context), closure, cb);
callDDPMethod(origCaller, ddpClient, '/gagarin/wait', [ context, closure(), timeout, message, code.toString(), clean(context, args) ], getSetter(context), closure, cb);

});
}
Expand All @@ -89,13 +92,40 @@ function clean(self, args) {
});
}

function callDDPMethod (ddpClient, name, args, context, closure, cb) {
function cleanError(caller, feedback){
//console.error("cleanError", feedback);
var lineOffset = 11; // taken from the COMPILED debug message in backdoor.js
var anonRE = /^ at Object\.<anonymous> \(evalmachine.<anonymous>:(\d+):\d+\)$/m;

var res = anonRE.exec(feedback.stack);
if(res){
var loc = parseInt(res[1]) - lineOffset;

var callerStack = caller.stack.split(/\n +/);
var lineTestScript = callerStack[2]; // skip msg and call to execute/promise/wait
var res = lineTestScript.match(/^(at .+):(\d+):\d+$/);
if(res){
var computedLineNum = loc + parseInt(res[2]);
var newLine = res[1] + ":" + computedLineNum + ":1";
feedback.error = feedback.error + "\n " + newLine;
//console.log("CLEAN ERROR", feedback.error);
}else {
throw new Error("UNEXPECTED ERROR: couldn't find lineTestScript", lineTestScript);
}
}else {
throw new Error("UNEXPECTED ERROR: couldn't find evalmachine.<anonymous> in", feedback.stack);
}
return feedback.error;
}

function callDDPMethod (origCaller, ddpClient, name, args, context, closure, cb) {
"use strict";

if (!ddpClient) {
return cb(new Error('invalid ddpClient'));
}
ddpClient.call(name, args, function (err, feedback) {
//console.log("ddpClient.call", name, err, feedback);
if (feedback && feedback.closure) {
closure(feedback.closure);
}
Expand All @@ -109,7 +139,7 @@ function callDDPMethod (ddpClient, name, args, context, closure, cb) {
return cb(new Error('no feedback provided'));
}
if (feedback.error) {
return cb(new Error(feedback.error));
return cb(new Error(cleanError(origCaller, feedback)));
}
cb(null, feedback.value);
});
Expand Down
11 changes: 8 additions & 3 deletions meteor/backdoor.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ if (Gagarin.isActive) {

chai.should();
chai.use(Npm.require('chai-things'));
chai.config.includeStack = true; // for newer > 2.1 versions
chai.Assertion.includeStack = true; // for currently included 2.1 version

plugins.chai = chai;
plugins.Fiber = Fiber;
Expand Down Expand Up @@ -41,7 +43,8 @@ if (Gagarin.isActive) {
try {
return { value : userFunc.apply(context, args), context: context, closure : getClosure() };
} catch (err) {
return { error: err.message, context: context, closure: getClosure() };
// console.log("/gagarin/execute error",err);
return { error: err.message, stack: err.stack, context: context, closure: getClosure() };
}
}));

Expand Down Expand Up @@ -80,7 +83,8 @@ if (Gagarin.isActive) {
try {
userFunc.apply(context, args);
} catch (err) {
return { error: err.message, context: context, closure: getClosure() };
// console.log("/gagarin/promise error",err);
return { error: err.message, stack: err.stack, context: context, closure: getClosure() };
}

})) || future.wait();
Expand Down Expand Up @@ -197,7 +201,7 @@ function isolateScope(code, closure) {
" return action(userFunc, getClosure);",
" } catch (err) {",
// this should never happen ...
" return { error: err.message, closure: getClosure() };",
" return { error: err.message, stack: err.stack, closure: getClosure() };",
" }",
" })("
);
Expand Down Expand Up @@ -253,6 +257,7 @@ function align(code) {
*/
function compile(code, closure) {
code = providePlugins(isolateScope(code, closure)).join('\n');
//console.log("COMPILED", code);
try {
return vm.runInThisContext('(' + code + ')').apply({}, values(plugins));
} catch (err) {
Expand Down