How to handle UnexpectedAlertOpenError in Protractor - javascript

I'm working on the automation of a website and i ran into a particular problem.
I'm using protractor over gulp to run the automated tests and also a report generator included in the gulp task.
The issue at hand is the following:
Whenever an alert is triggered by chrome, protractor stops and throws the "UnexpectedAlertOpenError" in the console, stopping the test run and canceling the report generation.
I would like to know if there is a way to make the spec fail and continue running the rest of the suite.
I know you can do this:
browser.get(url).catch(function () {
return browser.switchTo().alert().then(function (alert) {
alert.accept();
return browser.get(url);
});
});
But i don't want protractor to close the alert and continue, I would like to fail the test where it came up, and return an error message to continue with the run.
Is there any way to do that? Is it possible to pass an exception to the catch function and return a message? I could not find any documentation about that catch method.
Thank you!
EDIT: After going over the stack trace on the console, I've found that protractor detects as if the spec failed, and the exception comes from the reporter when it tries to take a screenshot (I'm using protractor-jasmine2-html-reporter)
I'm going to paste a bit of the stack trace in case someone can figure out something, I'm lost really.
E/launcher - UnexpectedAlertOpenError: unexpected alert open: {Alert text : You have pending changes}
From: Task: WebDriver.takeScreenshot()
EDIT2: I found the real problem with my implementation. The npm plugin protractor-jasmine2-html-reporter (which i'm using) was trying to take a screenshot when the alert was open, causing the webdriver to break and the kept the report from being generated.
What i did to fix this was to fork from their repository and before trying to take a screenshot confirm if the alert was open and avoid taking the screenshot if it was:
function alertIsPresent() {
return browser.driver.switchTo().alert()
.then(function (alert) {
alert.accept();
return true;
}, function (err) {
return false;
});
};
In case it was open, i would close it and continue without taking the screenshot, otherwise take the screenshot.
By doing this the report generates correctly and it documents that on the next spec report that there was an alert open.
Hope this is helpful to someone.

I've had a similar problem. Searched for hours and finally found this:
unexpectedAlertBehaviour: 'accept'
See https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities#read-write-capabilities for more information. You basically create a capabilities object and pass the desired values into it:
capabilities: {
browserName: "chrome",
unexpectedAlertBehaviour: 'accept',
chromeOptions: {
args: ["--window-size=1920,1080", "--disable-gpu"],
},
},
Hope this helps!

You should be able to check for these Error codes and force a failure via the jasmine fail function
browser.switchTo().alert().then(function(alert) {
alert.accept();
}, function(err) {
if (err.code == webdriver.error.ErrorCode.UNEXPECTED_ALERT_OPEN) {
fail('Fail this spec');
}
});

This is odd that your test Protractor test completely fails and Protractor stops working. If this is the case, please feel free to open up a Protractor issue.
My guess is that you have an it spec that fails, and it puts up an alert causing other tests to not work. There are a couple of things you could do:
Restart the browser after each test (see the config). This quits the driver session and creates a new browser instance. As you can imagine, this will slow down your test. In your config set:
restartBrowserBetweenTests: true
Try using the postTest plugin. Use postTest to check if the test failed, and maybe check if there is an alert and close it.
postTest: function(passed, testInfo) {
if (!passed) {
// should check to see if there is an alert
// close the alert
return browser.switchTo().alert().then(function (alert) {
return alert.accept();
});
}
}

Related

Why does execution of program stop - I caught the exception?

I'm writing a unit test framework. I noticed Mocha purports to handle exceptions in your test code gracefully, mapping the exception to the correct test in the log output. I'm attempting to do the same thing here. Let's ignore mapping the exception to the correct test for now (I'll def take a suggestion though, I'm stumped on how I'll do that for now)
I add all the test functions into the testmap, iterate over the keys in the testmap, and call each test's function one by one. I stall till the tests report back completed. I wrap around this a try-catch block to catch any exceptions that happen in any of the tests. It works - I can catch exceptions generated in the tests but even though I catch them, the program terminates. I do not want the program to terminate, and I don't think it's supposed to if you catch the exception... what gives?
Here is the try-catch in my library code
this.runtests = () => {
try {
Object.keys(this.testmap).forEach((test) => {
performance.mark(test)
this.testmap[test].testfunc();
});
this.stalltillgood(() => {
this.finallog();
});
}
catch (e) {
console.log('UNHANDLED EXCEPTION IN TEST');
console.log(e.stack);
}
};
Here is the client code which generates the exception - it is ENOENT - no such file or directory - hello.htm doesn't exist (on purpose)
expected('<fuck>&<fuck>');
testinfo('A Hello World Test', //the name of the test [MUST PASS TO ACTUAL AS WELL]
'This is the hello world test doc lol'); //the doc
comparator(cmp.equals); //you can use the pre built compare functions or your own
test(() => { //pass your test function to test
const file = fs.readFileSync('./hello.htm');
actual('A Hello World Test', file.toString());//make a call to actual in your test code
}); //to pass it your test result
//write more tests with the same sequence of commands
I think my problem is that this.runtests is the last method called, and after continuing on from my catch block, the program literally never has anything to output to me again, everything should be logged by then. The program just terminates after the catch block. I think I will have an extra var in test 'started' and just restart this.runtests, which will now check to see if a test has been started before trying to start it! Hooray! Still don't know how to map the exception to the proper test, maybe e.stack? Actually yeah that should be easy I guess lol.
I think my problem is that this.runtests is the last method called, and after continuing on from my catch block, the program literally never has anything to output to me again, everything should be logged by then. The program just terminates after the catch block. I think I will have an extra var in test 'started' and just restart this.runtests, which will now check to see if a test has been started before trying to start it! Hooray! Still don't know how to map the exception to the proper test, maybe e.stack? Actually yeah that should be easy I guess lol.

Protractor - need to find a happy meduim between the default behavour and jasmine-bail-fast

I can share frustration with a lot of professionals about default protractor behavior on test failure - it just keeps running the tests and you have to wait until it finishes to fix the error.
I read the related posts and came across jasmine-bail-fast solution. Link to related post is provided here: Exit Protractor e2e test on fail?
However, this solution puts me on the other side of the pickle. I do NOT want to terminate the testing suite when it failed to close the confirmation message or ran into similar minor issues.
I would like to have the ability to control when to exit the script via exitonfailure() function or something similar. For instance, if had this block of code:
> browser.wait(function()
> return browser.isElementPresent(acceptBudgetButton);
> }, 30000, 'Error - Unable to save budget changes because Accept Budget button is not visible. Terminating test run.');
and put exitonfailure() after this block, I want my test run to exit immediately. However, I want to test keep on running if exitonfailure() is not there.
Is there a feasible way to achieve this goal and take control of my own destiny?
Thank you for your help!
You can handle the browser.wait() success and failure cases appropriately:
var EC = protractor.ExpectedConditions;
browser.wait(EC.presenceOf(acceptBudgetButton), 30000).then(
function () {
// success
},
function () {
// failure
console.log('Error - Unable to save budget changes because Accept Budget button is not visible. Terminating test run.');
jasmine.getEnv().bailFast();
}
});
Also, look into using fail() function which fails a test.

Nightwatch Abort Test on Pass

I'm writing a script in Nightwatch that tests a specific element on a page. It's possible that the script could be testing a URL in which the element is not present on the page, in which case I want the script to end the test without any failures being logged.
I cannot seem to find a way to abort the test early without invoking a failure, however. Is there any way to have a Nightwatch test abort on a pass?
Here's a part of the code I'm working with for reference:
//End test if pagination is not present
'Pagination Present' : function (browser) {
browser
.execute(function() {
return document.querySelectorAll("ul[class='pagination']").length;
},
function(count){
if (count.value == 0) {
browser.assert.equal(count.value, 0, "There is no pagination on this page.");
browser.end();
}
})
},
Invoking browser.end(); closes the browser, but it reopens immediately after and the tests continue. Every single case fails, since the pagination does not exist on the given page. I'd like to end the test immediately after browser.assert.equal passes. Is there any way to do so?
You can use try/catch.
I had the same issue with some tests and i've got it to skip that assertion like this: you try to check something, but if you don't find the element, instead of failing the test, i just display a message in the console and exit the whole test:
'Test product\'s UPSs' : function (browser) {
try {
browser.assert.elementPresent('#someElement');
}
catch(err) {
console.log('this product has no Special features! Skipping');
process.exit();
}
}
In case you have further tests that you know they wouldn't fail and you'd like to continue with them, just leave out the process.exit() function. While it might not be the safest way to do it, at least it gets the job done.

How to Stop the automation testing in ios

Is there any possible way to stop the automation testing? Actually i m testing my app with automation javascript. I have two test in my script. if the first test fail i dont want to continue my script..
MY code:
var target = UIATarget.localTarget();
var testname = "Test1";
UIALogger.logStart(testname);
target.frontMostApp().mainWindow().buttons()[0].tap();
UIALogger.logPass(testname);
target.delay(2);
var testname = "Test2";
UIALogger.logStart(testname);
target.frontMostApp().mainWindow().buttons()[1].tap();
target.frontMostApp().mainWindow().buttons()[0].tap();
UIALogger.logPass(testname);
Here if the test1 fails i have to say the script to stop the process.. please tell me any suggestion to this problem. Thanks...
You should really look at abstracting out your tests. You can use something like:
function test(description, steps) {
try{
UIALogger.logStart(description);
steps();
UIALogger.logPass("Test Passed");
} catch (exception) {
UIALogger.logError(exception.message);
UIATarget.localTarget().logElementTree();
UIALogger.logFail("Test Failed");
throw exception;
}
}
as a function you can wrap your test in. As you can see, it will start the test, complete the steps of your test (if possible). If it failed, the test will log the element tree (very handy) and then will throw the same error again, stopping the test from continuing, and giving information about the error you experienced.
I highly recommend using tuneup_js for running UIAutomation. I don't think you can stop the Test run if one test fails using Instruments GUI, but it will stop when using the tuneup_js library and running the tests from the command line

Why "fail" in promise does not catch errors?

I'm trying to access a file, that might not exist:
var localFolder = Windows.Storage.ApplicationData.current.localFolder;
localFolder.getFileAsync(stateFile).then(function (file) {
Windows.Storage.FileIO.readTextAsync(file).then(function (text) {
// do something with the text
});
}, function (err) {
// log error, load dummy data
});
if the file is not there, the "fail" method does get called, BUT it happens only AFTER my application halts with an exception "file not found". only when I press "continue" for the debugger does it continue to the "fail" method..
what am i doing wrong? should i check for existence beforehand?
You're seeing a first-chance exception. The debugger is breaking at the point of throw. If you hit the "continue" button on the debugger dialog, the app will keep running and the exception handler will run.
You can change this by using the "Debug|Exceptions" menu to turn off first chance exceptions.
I have been struggling with this same problem for two or three days and finally came to the following solution: I use getFilesAsync function to get the list of all files in a folder, and then look through this list to know if the needed file exists. After that I can call getFileAsyns without throwing. Not very pretty, but works for me. I agree that assuming that a developer can turn exceptions off is not the best advice... In my opinion this issue should be considered as a bug in RT implementation.

Categories