I'm using Protractor with Chai as Promised in order to create a javascript-based testing tool and I'm getting the error
AssertionError: expected 'http://localhost:8888/test/homepage.php' to equal 'http://localhost:8888/test/my_homepage.php'
while I'm checking the url with this step definition:
this.Then(/^The url of the page should be "([^"]*)"$/, function(myUrl, callback){
expect(browser.getCurrentUrl()).to.eventually.equal(myUrl);
callback();
});
I would like to catch this error in order to use a different callback function, how can I do that? I've tried to use a try-catch block but it doesn't seem to work. I can't even understand if AssertionErrors are generated by Protractor, can you gently give me an explaination about this?
Thank you in advance
I couldn't find anything which could catch errors from expect and do something else. If #alecxe's suggestion from comments work, that should be your answer otherwise why not just do
browser.getCurrentUrl().then(function(url) {
if(url === myUrl) {
callback();
} else {
callback('something went wrong');
}
});
or would this not work?
try {
expect(browser.getCurrentUrl()).to.eventually.equal(myUrl);
callback();
} catch(e) {
callback('something went wrong '));
}
Related
Today I discovered an error in my code that leads to callbacks potentially being executed more than once. The intended usage of try...catch was meant for JSON.parse() operation; however, an error has occurred right after it inside the callback itself.
var body='{}';
var callback=function (arg){
console.log('callback executed with arg='+arg);
arg? pack_michael(): pack_jolly();
}
try {
JSON.parse(body); //if JSON parse successful should callback once with true argument
callback(true);
} catch (e){
callback(false); //if JSON parse fails should callback once with false argument
}
Above code results in double callback printing this:
callback executed with arg=true
callback executed with arg=false
I can think of some ugly solutions like creating a variable and checking if an error has occurred or nesting another unnecessary try...catch, but isn't there any neat solution to deal with this?
Call the callback after the try/catch:
let parseOk = false;
try {
JSON.parse(body);
parseOk = true;
} catch (e){
// parseOk is already false
}
callback(parseOk);
If you also want to catch errors in the callback itself, you can surround it in a different try/catch, but that's separate from errors that occur in the JSON.parse, so they shouldn't be combined.
Add new try/catch around callback
try {
JSON.parse(body);
try {
callback(true);
} catch(err) { console.log("Error in callback")}
} catch (e){
callback(false); //if JSON parse fails should callback once with false argument
}
Some time ago I was curious on how to execute async tests using Mocha and those tests to expect an error as a result (see Mocha async test handle errors)
Now I tried the same for the newer version of nodejs using await/async. Just a simple case but as I need to wrap the code in a try / catch block, things get out of hand.
After long hours of testing I ended up with a solution but it doesn't look good.
So I'm looking for a better way to do this.
The test looks like this:
it('myTest', async function () {
// THIS WORKS => CODE OPTION 1:
// this works, it uses promises but not await/async
return somePromiseFunction()
.then(() => Promise.reject(new Error('Expected method to reject.')))
.catch(err => assert.ok(err instanceof Error, 'This should be an error!'));
// THIS WORKS => CODE OPTION 2:
// this works, it uses await/async
let forceFail = false;
try {
await somePromiseFunction();
forceFail = true;
} catch (err) {}
if (forceFail) assert.ok(false, 'Expected method to reject.');
// WONT WORK => CODE OPTION 3:
try {
await somePromiseFunction();
assert.ok(false, 'you shouln\'t be here');
} catch (err) {
assert.ok(err instanceof Error, 'This should be an error!');
}
});
Both option 1 and 2 work. Option 1 uses classic Promise.then.catch syntax, and that's ok. Option 2 was the only way for me to make things work but is very complex to understand / maintain. It relies on a sort of global variable and handling states, and it just doesn't look good.
There is an option 3 in the code, but it does not work. Something like that would be easy to read but it does not work at all, not the first assert nor the second one.
If you remove the try / catch block then it won't work either.
Thanks.
In the third option, err would always be undefined since you're catching the exception as e, not as err. And the assert would always fail because undefined is not an instance of Error.
I found a way, but you'll need to upgrade to node version 10. I was using 8, but this new feature included in assert solves my problem in an elegant way.
Instead of trying this:
// WONT WORK => CODE OPTION 3:
try {
await somePromiseFunction();
assert.ok(false, 'you shouln\'t be here');
} catch (err) {
assert.ok(err instanceof Error, 'This should be an error!');
}
Do this:
// this works!
await assert.rejects(
async () => somePromiseFunction(),
Error
);
You can also verify the type of error being thrown, but in my case Error will suffice.
EDIT: async () => was not really necessary, I ended up with a one line assert (second parameter is optional, but I'd rather keep it):
await assert.rejects(somePromiseFunction(), Error);
I want to use the chai.js expect assertions to perform multiple tests in my code.
If a assertion is failing I want to log it and then proceed with the next one.
e.g.>
expect(recvRequest.request.response.statusCode).to.equal(expResponse.statusCode);
expect(recvRequest.request.response).to.have.property(headers);
etc.
I want to be able to write multiple expects without encapsulating each one in a try catch. So I thought I write a simple wrapper for it but it failed.
I get an error at func.call
function exWrapper(func, arg) {
try {
func.call(null, arg);
} catch (e) {
return false;
}
return true;
}
exWrapper(expect(recvRequest.request.response.statusCode).to.equal, 120);
But during execution I get a: TypeError: this.assert is not a function
at assertEqual
I checked with a typeof and expect().to.equal is a function so what am I doing wrong?
I hope somebody can help me.
Regards
Ruvi
I'm trying to test URL schemes via javascript try/catch blocks but my catch blocks are not being executed. Safari just skips them entirely and I don't understand why?!
function open_twitter() {
if (!IS_IOS){ //made unequal IOS so that I could test it on my Macbook
try {
window.location = "twitter://"; //fails and should go to the catch block
} catch (e) { //skipped
try { //skipped
window.location = TWITTERRIFIC_URL_SCHEME; //skipped
} catch (e) { //skipped
null; //skipped
} //skipped
} //skipped
} else {
window.open(TWITTER_URL, "_blank");
}
}
Does anyone have an idea why this is happening?
I want the code to test the first URL scheme. If that isn't successful than it should (in theory) go to the catch block and run the code inside which is in my case a try block again with the next URL scheme to test and so on and so forth.
But this doesn't happen?! I'm really confused...
Try catch doesn't work exactly like what you wrote, You'll need to provide your catch with an exception, Else it doesn't know something bad happened.
See these docs : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
try/catch should be used as a simple test with your custom exception. For example,
try
{
if(false==false)
{
throw "myException"; // generates an exception
}
catch (e) {
// statements to handle any exceptions
logMyErrors(e); // pass exception object to error handler
}
As you can see, The try should test for something and return an exception if some condition is met.
I've looked through the threads here on this subject and can't find what I want.
I have a bunch of functions that return string and I want them to not return a string if the input is bad and I don't want the program to exit either AND I don't want to wrap every call in try / catch.
function foo(num){
if(num > 5){
throw SomeException("Input too big")
}else{
return "bar"+num
}
}
I want to log an error like "6 is too big for foo", instead of exiting the program. But this will be kind of an api, so I don't want the user to have to try/catch every time they use
one of these functions. This is a nodejs script.
this works, but is a awkward:
f = {
command : function(cmd,arg){
try {
console.log(q[cmd](arg));
}
catch (e) {
console.log("Error: " + e + " for " + cmd);
}
},
foo : function(str){
throw ("foo error");
},
foo2 : function(str){
throw ("foo2 error");
}
};
f.command("foo",2);
f.command("foo2",3);
[[Edit]] It's a nodeJS script. Then make the API asynchronous. We do not do synchronous operations in nodeJS. Please conserve the event loop.
You can also rework your API to be asynchronous
function foo(num, cb){
if(num > 5){
cb(SomeException("Input too big"));
}else{
cb(null, "bar"+num);
}
}
foo(5, function(err, data) {
...
});
You can reference a public logger instance.
MyLibrary.errorHandler = defaultErrorHandler() || config.errorHandler
Then have the defaultErrorHandler be
function(error) {
if (console && console.log) { console.log(error.message); }
$("#errordiv").text(error.message);
}
function foo(num){
if(num > 5){
MyLibrary.errorHandler(new Exception("blargh"));
}else{
return "bar"+num;
}
}
If you're creating an API that others will use, and you want to signal that an error happened, well... throw an exception. If that exception doesn't get caught by the programmer using your API, that's their fault, not yours; on the other hand, if their code goes all wonky because your function does something really weird on an error, well... okay, that's still the other programmer's fault for not properly checking input coming into your API, but be a good citizen and help out their debugging by throwing that exception. They may dislike you for putting exceptions everywhere, but they'll hate you if your code just silently does really weird stuff instead of providing a good indication of what the error is.
I'd say log the error, too, but you're doing this in JavaScript, where there isn't any such facility.
And for the record, this is coming from a programmer who has used APIs that both do and do not throw exceptions on errors; the ones that do throw them are generally the ones I consider to be better-written.