Selenium alert only shows in debug mode - java

I am testing a site page using Webdriver/Java which contains many fields. One of the fields is a dropdown box (or select box) and it contains validation upon losing focus (e.g. tabbing out). So if I select a particular option in the dropdown and tab to the next field, an alert box will pop up saying "You cannot choose that!".
Now I am doing code that checks for the presence of the alert box, and accepts it, however this is only working for me in DEBUG mode. When running the test (i.e. not in debug) I get "Timed out after 10 seconds waiting for alert to be present Build info: version: '2.53.0'".
I understand that this is probably a timing issue since it works in DEBUG mode, but I can't understand why as I'm using ExpectedConditions.alertIsPresent(). The code where this is failing is here:
WebElement currentElement = driver.findElement(By.id("selectbox"));
Select currentSelect = new Select(currentElement);
currentSelect.selectByVisibleText(updatedValue);
currentElement.sendKeys(Keys.TAB);
System.out.println("milestoneA");
if ((exceptionExpected()) {
System.out.println("milestoneB");
wait.until(ExpectedConditions.alertIsPresent());
System.out.println("milestoneC");
checkAlertBox(getExpectedResultFromExcel());
}
In DEBUG mode, the code keeps going fine and all is good. In RUN mode in my logs I get up to milestoneB and then the above mentioned error is thrown.
Further to this, if I add a Thread.sleep(1000) before Tabbing, all works fine.
Any ideas please?

I would try to send the TAB key until the element loses the focus:
WebElement currentElement = driver.findElement(By.id("selectbox"));
currentElement.click();
currentElement.sendKeys("abcd");
// wait for the popup to be visible
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#abc")));
// send the TAB key while the current element has focus
new WebDriverWait(driver, 20).until((WebDriver wd) -> {
currentElement.sendKeys(Keys.TAB);
return !wd.switchTo().activeElement().equals(currentElement);
});

Related

How to "handle" an alert as per UnhandledAlertException?

This topic is sadly very poisoned by non-applying answers, e.g. 1, 2, 3, 4, etc. pp.
The issue:
One may do an action which, when successful, makes the website raise an alert.
E.g. click on a "logout" button to see an "Are you sure you want to logout?" alert:
public class Logout extends PageObject {
static final Target LOGOUT = /* logout button, which will display the alert when clicked */;
public Performable logout() {
return Task.where("{0} clicks on Logout"
, Ensure.that(LOGOUT).isDisplayed()
, Click.on(LOGOUT) // done manually: alert visible; done by Serenity: no alert
);
}
}
Serenity will cause an org.openqa.selenium.UnhandledAlertException during execution of Click.on and the alert will not be present after this task. If the next task would be "interact with alert" in any way or form (as done in all the linked articles and all others I have perused before posting this question), the next task will then always fail because there is no alert .
This can be easily observed in the browser window as well: The alert may show, if at all, for but a split second and immediately disappear.
The question:
Given that the alert has to be handled before the action causing it completes: How do I do that?
N.b.:
I have done a deeper analysis in this old bug report. Includes a call stack where one may place breakpoints inbetween the alert's appearance and disappearance.
Others have indicated that it is an issue pertaining to chromedriver - but using a different framework with the same chromedriver works just fine.
A workaround might be to disable screenshots, but
I do not want to do that!
Serenity indicates (via a log warning) that this is a user error. So I'd rather correct my error than work around it.

Selenium Java - Click if element exists, continue with the next command if element not found

i'm trying to create a script to test a web site (js application), code is almost done but i encounter a problem. The script its supposed to edit a question on the website (the question uses a lot of variables from a database) and depending on were the script failed or if anyone else edited the question there is a chance for the script to get a pop-up message(not a separate window or new tab). I want the code to:
Click the element if present or go to the next line of code if the element does not exist.
I tried using but it does not help:
Alert alert = driver.switchTo().alert();
alert.accept();
My code:
driver.findElement(By.xpath("//button[2]")).click();
// Click unselect all
Thread.sleep(1000);
driver.findElement(By.linkText("Romania")).click();
// Select Romania
log.debug("Select Romania");
Thread.sleep(2000);
driver.findElement(By.linkText("Germany")).click();
// Select Germany
log.debug("Select Germany");
Thread.sleep(2000);
driver.findElement(By.xpath("//div[4]/a")).click();
// Click Save Button
log.debug("Click Save");
Thread.sleep(3000);
**driver.findElement(By.xpath("//div[4]/div/div/div/div/div/button")).click();**
// Pop-up message
log.debug("Click Pop-up message");
Thread.sleep(3000);
/////////////// Single Answer
driver.findElement(By.linkText("Change")).click();
// Click Change Template
log.debug("Click Change");
Thread.sleep(2000);
The you can find the line with the issue between **** (pop-up), how can i click if the element exists or move to driver.findElement(By.linkText("Change")).click(); if element not found.
Please let me know if more info is required.
Edit:
To give more details about why the pop-up appears. The script edits a question, the questions have multiple templates and the script is supposed to go through each template after selecting the template the script will associate a variable from the database to the question.
Templates:
Single answer question
Single answer dropdown question
Multiple answer question
Multiple answer dropdown question
Date
The pop-up message appears as a warning (that the variable used will be removed )when the template is changed from multiple answer to single answer/date or the other way around.
In the perfect case if the script finishes successfully (it will end with single answer dropdown - first question is single answer so the pop-up does not appear )and no one edits the question i will not encounter the pop-up but if the script fails due to x reason after changing the template to multiple answer, when i restart the script i will receive that pop-up/warning.
The issue also occurs when changing the language of the question as shown in the code above, i have multiple steps were i encounter this problem.
At the moment in order for the script to run and avoid the problem mentioned above, i need to edit the question myself and select a specific language and template before running the script.
If no matching elements are found, an instance of NoSuchElementException is thrown.
try {
WebElement popUp = driver.findElement(By./**your expression**/);
popUp.click();
} catch(NoSuchElementException | StaleElementReferenceException e) {
log.debug("Impossible to click the pop-up. Reason: " + e.toString());
}
I'd recommend two approaches.
Simply poll the DOM for the pop-up and click the button if exists:
List<WebElement> button = driver.findElements(By.xpath("//div[4]//button"));
if (!button.isEmpty()) {
button.get(0).click();
}
....
driver.findElements() is used to avoid try-catching NoSuchElementException in case using driver.findElement()
You may use explicit wait to wait some time for the button to appear:
try{List<WebElement> button = (new WebDriverWait(driver,10)).until(ExpectedConditions.presenceOfElementsLocated(By.xpath("//div[4]//button")));
if (!button.isEmpty()) {
button.get(0).click();
}
}
catch(TimeoutException e)
{
}

Selenium - Text entered in same field, even though intended to type in different fields

Using selenium, when trying to enter username and password in login form, sometimes the text is entered on the same field. Username and password are having unique identifier.
For sending keys, the following steps are done.
sendKeys(By.id("login_username"), "abc");
sendKeys(By.id("login_password"), "efg");
public void sendKeys(By locator, String text) {
WebElement element = findElement(locator);
if(element != null) {
element.clear();
element.sendKeys();
}
}
public WebElement findElement(By locator) {
return wait(org.openqa.selenium.support.ui.ExpectedConditions.presenceOfElementLocated(locator));
}
public WebElement wait(ExpectedCondition<WebElement> condition) {
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).pollingEvery(1, TimeUnit.SECONDS)
.withTimeout(60, TimeUnit.SECONDS)
.ignoreAll(Arrays.asList(NoSuchElementException.class, TimeoutException.class));
return wait.until(condition);
}
But somehow, when entering text, both the username and password texts are getting typed onto the password field. This is not happening always though. Not able to understand what could possibly go wrong or what to check. Any suggestions...
platform: Ubuntu 16.04.1 LTS 64-bit
chromedriver version: 2.25
chrome browser version: 55.0.2883.87
Thanks in advance.
The sendKeys() action performs the following steps:
Gets the coordinates of the element
Clicks at the coordinates it got (using a mouse action)
"Types" the text (that will be received by whatever element is currently focused)
It can go wrong if the element can't be focused when starting the action (because it's disabled for example), or if the coordinates change between getting the coordinates and clicking/focusing the element (because the layout is still changing).
Another common cause can be onClick action hooked on the element, that can lead to race conditions. Without seeing the actual page, it is possible that after selenium clicks, an onClick action is still working when the text is being typed. This basically looks like this:
Selenium clicks
onClick action starts (element might get focused only after it finishes)
Selenium starts typing (onClick haven't
returned yet, so the wrong elements gets the text)
the onClick
action finishes, but by that time Selenium finished too.
As a solution you can try focusing the element directly, and wait until it is really focused before sending the keys. This question might be of use for this case.

How can I tell Selenium to press cancel on a print popup?

I am checking whether or not a page appears using Selenium. When I click the page, however, a printer print prompt appears (like the window that says select printer and such). How can I have Selenium close this window by hitting cancel?
I tried looking to alerts, but it seems like those will not work since the print window is a system prompt. It does not recognize any alerts appearing.
The most recent I tried using is by just sending keys like tab and enter in order to have the cancel button selected, however, it doesn't recognize any keys as being pressed.
How can I handle this case?
public static boolean printButton() throws Exception {
WebDriver driver = new FirefoxDriver();
driver.get("website");
try {
Thread.sleep(3000);
WebElement temp = driver.findElement(By.xpath("//*[#id='block-print-ui-print-links']/div/span/a"));
temp.click();
Actions action = new Actions(driver);
action.sendKeys(Keys.TAB).sendKeys(Keys.ENTER);
Thread.sleep(6000);
}
catch (Exception e) {
System.out.println("No button.");
driver.close();
return false;
}
I would simply disable the print dialog by overriding the print method :
((JavascriptExecutor)driver).executeScript("window.print=function(){};");
But if you goal is to test that the printing is called then :
// get the print button
WebElement print_button = driver.findElement(By.cssSelector("..."));
// click on the print button and wait for print to be called
driver.manage().timeouts().setScriptTimeout(20, TimeUnit.SECONDS);
((JavascriptExecutor)driver).executeAsyncScript(
"var callback = arguments[1];" +
"window.print = function(){callback();};" +
"arguments[0].click();"
, print_button);
If you are going for testing only Chrome browser here is mine solution. Because of 'Robot' class or disabling print didn't work for my case.
// Choosing the second window which is the print dialog.
// Switching to opened window of print dialog.
driver.switchTo().window(driver.getWindowHandles().toArray()[1].toString());
// Runs javascript code for cancelling print operation.
// This code only executes for Chrome browsers.
JavascriptExecutor executor = (JavascriptExecutor) driver.getWebDriver();
executor.executeScript("document.getElementsByClassName('cancel')[0].click();");
// Switches to main window after print dialog operation.
driver.switchTo().window(driver.getWindowHandles().toArray()[0].toString());
Edit: In Chrome 71 this doesn't seem to work anymore since the script can't find the Cancel button. I could make it work by changing the line to:
executor.executeScript("document.querySelector(\"print-preview-app\").shadowRoot.querySelector(\"print-preview-header\").shadowRoot.querySelector(\"paper-button.cancel-button\").click();");
Actually you can't handle windows (OS) dialogs inside Selenium WebDriver.
This what the selenium team answers here
The current team position is that the print dialog is out of scope for
the project. WebDriver/Selenium is focused on emulating a user's
interaction with the rendered content of a web page. Other aspects of
the browser including, but not limited to print dialogs, save dialogs,
and browser chrome, are all out of scope.
You can try different approach like AutoIt
we can also use key for handling the print or press the cancel button operation. and it works for me.
driver.switchTo().window(driver.getWindowHandles().toArray()[1].toString());
WebElement webElement = driver.findElement(By.tagName("body"));
webElement.sendKeys(Keys.TAB);
webElement.sendKeys(Keys.ENTER);
driver.switchTo().window(driver.getWindowHandles().toArray()[0].toString());
Native window based dialog can be handled by AutoItX as described in the following code
File file = new File("lib", jacobDllVersionToUse);
System.setProperty(LibraryLoader.JACOB_DLL_PATH, file.getAbsolutePath());
WebDriver driver = new FirefoxDriver();
driver.get("http://www.joecolantonio.com/SeleniumTestPage.html");
WebElement printButton = driver.findElement(By.id("printButton"));
printButton.click();
AutoItX x = new AutoItX();
x.winActivate("Print");
x.winWaitActive("Print");
x.controlClick("Print", "", "1058");
x.ControlSetText("Print", "", "1153", "50");
Thread.sleep(3000); //This was added just so you could see that the values did change.
x.controlClick("Print", "", "2");
Reference : http://www.joecolantonio.com/2014/07/21/selenium-how-to-handle-windows-based-dialogs-and-pop-ups/
Sometimes 2 different statements as above (webElement.sendKeys(Keys.TAB)
webElement.sendKeys(Keys.ENTER)) will not work, you can use with combination of Tab and Enter keys as below, This will close the Print preview window.
Using C# :
Driver.SwitchTo().Window(Driver.WindowHandles[1]);
IWebElement element = Driver.FindElement(By.TagName("body"));
element.SendKeys(Keys.Tab + Keys.Enter);
Driver.SwitchTo().Window(Driver.WindowHandles[0]);
Erçin Akçay answer updated.
// Choosing the second window which is the print dialog.
// Switching to opened window of print dialog.
driver.switchTo().window(driver.getWindowHandles().toArray()[1].toString());
// Runs javascript code for cancelling print operation.
// This code only executes for Chrome browsers.
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("document.querySelector(\"body > print-preview-app\").shadowRoot.querySelector(\"#sidebar\").shadowRoot.querySelector(\"print-preview-button-strip\").shadowRoot.querySelector(\"div > cr-button.cancel-button\").click();");
// Switches to main window after print dialog operation.
driver.switchTo().window(driver.getWindowHandles().toArray()[0].toString());

Webdriver showModalDialog

We are using webdriver for our functional tests. But our application uses the showModalDialog JS function a lot to open a popup. When we try to test this functionality with webdriver it hangs from the moment the popup is opened.
We tried several things to test this:
Using the workaround explained here. But this seems to be a fix for selenium and not for webdriver. We tried it but it didn't work.
Searching for a good alternative, HtmlUnit opened the modal dialog and could interact with it, but it has it's drawbacks like no visual help to fix certain tests and it stopped execution when it detected a JS error in a JS library we have to use but have no control over.
How can we test this or work around this problem?
From my experiences with various automation tools interaction with "webpage dialog" windows opened from IE using window.showModalDialog() or window.showModelessDialog() is not available.
Since the window is not a "true" window (look at the taskbar, it doesn't even show up) most tools can't "inspect" it and/or interact with it.
However if you do find a tool that will, please advise - there are many people looking for such a beast.
That all said, if you can possibly avoid using either of these 2 proprietary methods you'll have much more luck.
(and yes, for the picky ones, Firefox and Chrome have adopted these kind of dialogs but they don't work quite the same)
None of the answers answer the question. If the driver hangs, then you can't call any methods on it. The question is NOT about finding the pop up, it is about how to stop the driver hanging. The only way I have found is to not use showModalDialog. This can be done by adding the folowing to your test code :
((JavascriptExecutor) driver).executeScript("window.showModalDialog = window.open;");
which calls window.open each time your JavaScript calls window.showModalDialog.
I am using webdriver.SwitchTo().Window() method but my concern is my popup window does not have "Name"
When I use webdriver.WindowHandles it return only one handle, I am using this statement after popup window open.
As I don't have name / handle I cannot switch from parent window to child window.
Any other solution to do the same functionality
First we have to switch to the active element:
driver.switchTo().activeElement();
To check whether we have actually switched to the correct active element:
driver.switchTo().activeElement().getText();
Even if the window doesn't have name u can use
driver.switchTo.defaultcontent();
and perform the operation you want to execute
or else you can get the window handle name using the below command
for (String handle : driver.getWindowHandles()) {
driver.switchTo().window(handle); }
hope this should work for you.
Issue 284 is for WebDriver. It seems that it will be implemented only after Issue 27 will be implemented, so the fix should be in Beta 1 or 2 of WebDriver.
Set<String> beforePopup = driver.getWindowHandles();
Set<String> afterPopup = driver.getWindowHandles();
afterPopup.removeAll(beforePopup);
if(afterPopup.size()==1){
System.out.println(afterPopup.toArray()[0]);
}
driver.switchTo().window((String) afterPopup.toArray()[0]);
What I have been using and it works great for us on with IE and Firefox is to go through popups
and look for a a unique text on the popup you are trying to interact with. Here is the method, let me know if it works for you. Please note the line driver = driver.switchTo().window(windowHandle);
public void switchWindow(String containingText, WebDriver driver) throws Exception {
if ( StringUtils.isEmpty(containingText))
return;
int counter = 1;
int numOfpopups = driver.getWindowHandles().size();
System.out.println("Waiting for popup to load..... # handles:" + numOfpopups);
while ( numOfpopups < 2 && ((counter%10) != 0) ) {
counter++;
try{Thread.sleep(1000);}catch (Exception e) {}
}
System.out.println("Done waiting for..... " + counter + " seconds");
if (driver.getWindowHandles().size() < 2)
throw new BrowserException("Timeout after " + counter + " secs. No popup present. ");
System.out.println("Going through window handles...");
for (String windowHandle : driver.getWindowHandles()) {
driver = driver.switchTo().window(windowHandle);
if ( driver.getPageSource().contains(containingText)
return;
else
continue;
}
throw new Exception("Window containing text '" + containingText + "' not found");
}
To my knowledge, webdriver has no built-in functionality to handle modal windows as of now. Webdriver will hang once you click button which opens modal window. This happens due to JS on parent window halts until child window is closed.
To handle modal windows such as this one, see below for possible workaround written in Java. The main idea is to perform action that opens modal window (click on the button) in new thread.
/**
* Click button to open modal window and switch to it
* #param we webElement handle of a button
*/
public void clickToOpenModal(final WebElement we) {
//Get handles of all opened windows before opening modal window
Set<String> initWindowHandles = getDriverInstance().getWindowHandles();
//Create new thread and click button to open window
Thread thread1 = new Thread() {
#Override
public void run() {
//Click button
click(we);
}
};
thread1.start();
//Wait for window to appear
waitForWindow(initWindowHandles, pauseL);
thread1.interrupt();
thread1 = null;
//Get handles of all opened windows after opening modal window
Iterator<String> it = getDriverInstance().getWindowHandles().iterator();
//Select handle of modal window
String windowHandle = "";
while(it.hasNext()){
windowHandle = it.next();
}
//Switch focus and work on the modal window
getDriverInstance().switchTo().window(windowHandle);
}
The solution by Hugh Foster works, i tried this and succeeded
((JavascriptExecutor) driver).executeScript("window.showModalDialog = window.open;");
You can find the url of modal dialog then open it on another tab, it will work as normal.
In case you want to deal with open modal dialog, you can try to send "tab" key for move around objects and "send keys... enter" for setText or click.
Note: Below is some information why you cannot use selenium webdriver for work with that modal.
Modal pop-up - This is very specific to IE, Microsoft defined it as
When Windows Internet Explorer opens a window from a modal or modeless HTML dialog box by using the showModalDialog method or by using the showModelessDialog method, Internet Explorer uses Component Object Model (COM) to create a new instance of the window. Typically, the window is opened by using the first instance of an existing Internet Explorer process. When Internet Explorer opens the window in a new process, all the memory cookies are no longer available, including the session ID. This process is different from the process that Internet Explorer uses to open a new window by using the open method.
http://msdn.microsoft.com/en-us/library/ms536759(VS.85).aspx
MSDN blog on Modal dialog
When user select Model popup, parent window is blocked waiting for the return value from the popup window. You will be not able to see the view source of the page, need to close the popup then only the parent window is activated.

Categories

Resources