I want to click a button until a javascript alert is present.
Here is what I would like to do:
while(!ExpectedConditions.alertIsPresent())
button.click();
But this does not work as the expression is not evaluated to a boolean condition.
I have tried:
while(ExpectedConditions.alertIsPresent() == null)
button.click();
But this results in never going into the loop. Thanks for any guidance
The predicate ExpectedConditions.alertIsPresent cannot be evaluated directly in a while.
You can use it with a waiter:
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.alertIsPresent());
But in your case a better choice would be to implement a predicate that clicks on the button until the alert is present:
WebElement button = driver.findElement(By.id("..."));
// clicks on the button every 100ms until the alert is present
Alert alert = new WebDriverWait(driver, 20, 100).until((WebDriver drv)->{
try{
button.click();
return drv.switchTo().alert();
}catch(NoAlertPresentException ex){
return null;
}
});
// accept the alert
alert.accept();
You can go with this workaround:-
while(alert.getClass().getCanonicalName().toString().equals("org.openqa.selenium.remote.RemoteWebDriver.RemoteAlert")){
button.click();
}
Related
I have written a function as following
public static WebElement waitForElementToBeClickable(WebDriver driver, WebElement webElement, int seconds) {
WebDriverWait wait = new WebDriverWait(driver, seconds);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(webElement));
element.click();
return element;
}
Now i am importing this function and using it as following
private String loginButton = "btnActive";
private String home = "//a[#id='pt1:_UIShome']";
WebElement login = driver.findElement(By.id(loginButton));
libraryUtils.waitForElements.waitForElementToBeClickable(driver, login, 20).click();
WebElement homeButton = driver.findElement(By.xpath(home));
libraryUtils.waitForElements.waitForElementToBeClickable(driver, homeButton, 20).click();
The login button is clicked but then after going to the next page i get the following error -
org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
The Xpath is right, I have checked that. And when I use element.click(), that also works but then that would require me to manually enter the sleep time, which is what I'm doing. I would like this to be dynamic. Appreciate any help or suggestions.
Sometimes JS had not been finished running, and if you try to interact with the web element or web elements you would see staleElemenent exception.
However the below solution may work for you :
new WebDriverWait(driver, 10).ignoring(StaleElementReferenceException.class).until(ExpectedConditions.elementToBeClickable(By.xpath("//a[#id='pt1:_UIShome']")));
driver.findElement(By.xpath("//a[#id='pt1:_UIShome']")).click();
Possibly it will be not a nice, but I see no stable solution other that adding some sleep there.
So, please try this:
private String loginButton = "btnActive";
private String home = "//a[#id='pt1:_UIShome']";
WebElement login = driver.findElement(By.id(loginButton));
libraryUtils.waitForElements.waitForElementToBeClickable(driver, login, 20).click();
driver.findElement(By.xpath(home));
libraryUtils.waitForElements.waitForElementToBeClickable(driver, homeButton, 20);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
driver.findElement(By.xpath(home)).click();
Problem here is that you are already doing element.click() in the waitForElementToBeClickable function and calling click again while calling this function.
libraryUtils.waitForElements.waitForElementToBeClickable(driver, login, 20).click();
Since you have already clicked while waiting for the element to be clickable, you shouldn't be clicking it again. I hope you got the answer for StaleElementException
I'm trying to click on a pop-up alert message on a UI with Selenium Webdriver.
The problem is, it is not clicking on accept or cancel even if I explicitly and implicitly wait. Is there any other alternative to clicking on a pop-up message. I tried to send key by Robot and press enter, but it did not work too.
click ok popup message function:
try {
WebDriverWait wait = new WebDriverWait(driver, 40);
wait.until(ExpectedConditions.alertIsPresent());
Alert alert = driver.switchTo().alert();
report.log(LogStatus.INFO, "Displayed Pop-up Window Alert Message -> " + alert.getText() + " for the Field -> " + fieldName);
System.out.println("Displayed Pop-up Window Alert Message -> " + alert.getText() + " for the Field -> " + fieldName);
alert.accept();
Thread.sleep(3000);
} catch (NoAlertPresentException ex) {
System.err.println("Error came while waiting for the alert popup. ");
report.log(LogStatus.INFO, "Alert pop up box is NOT populating when user clicks on: ");
}
this is what the html looks like for the popup:
<input type="submit" name="ctl00$ctl00$Content$ContentPlaceHolderMain$Continue" value="Continue..."
onclick="if(warnOnDelete('ctl00_ctl00_Content_ContentPlaceHolderMain_EditRadioOptions_1',"
+ "'Please confirm if you wish to delete.') == false) return false;"
id="ctl00_ctl00_Content_ContentPlaceHolderMain_Continue" style="width:100px;">
It has to be in IE, we are not allow to use anything except IE
Update: function for the confirm boxes
function warnOnDelete(deleteButtonID, msg) {
var deleteRadioButton = document.getElementById(deleteButtonID);
if (deleteRadioButton != null) {
if (deleteRadioButton.checked == true)
return confirm(msg);
}
return true;
}
Seems the element is not an Alert but an <input> element and to click() on the element you have to induce WebDriverWait for the elementToBeClickable() and you can use either of the following Locator Strategies:
cssSelector:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("input[id$='_Content_ContentPlaceHolderMain_Continue'][value^='Continue'][name$='Continue']"))).click();
xpath:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//input[contains(#id, '_Content_ContentPlaceHolderMain_Continue') and starts-with(#value, 'Continue')][contains(#name, 'Continue')]"))).click();
I used explicit waits and I have the warning:
org.openqa.selenium.WebDriverException:
Element is not clickable at point (36, 72). Other element would receive
the click: ...
Command duration or timeout: 393 milliseconds
If I use Thread.sleep(2000) I don't receive any warnings.
#Test(dataProvider = "menuData")
public void Main(String btnMenu, String TitleResultPage, String Text) throws InterruptedException {
WebDriverWait wait = new WebDriverWait(driver, 10);
driver.findElement(By.id("navigationPageButton")).click();
try {
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(btnMenu)));
} catch (Exception e) {
System.out.println("Oh");
}
driver.findElement(By.cssSelector(btnMenu)).click();
Assert.assertEquals(driver.findElement(By.cssSelector(TitleResultPage)).getText(), Text);
}
WebDriverException: Element is not clickable at point (x, y)
This is a typical org.openqa.selenium.WebDriverException which extends java.lang.RuntimeException.
The fields of this exception are :
BASE_SUPPORT_URL : protected static final java.lang.String BASE_SUPPORT_URL
DRIVER_INFO : public static final java.lang.String DRIVER_INFO
SESSION_ID : public static final java.lang.String SESSION_ID
About your individual usecase, the error tells it all :
WebDriverException: Element is not clickable at point (x, y). Other element would receive the click
It is clear from your code block that you have defined the wait as WebDriverWait wait = new WebDriverWait(driver, 10); but you are calling the click() method on the element before the ExplicitWait comes into play as in until(ExpectedConditions.elementToBeClickable).
Solution
The error Element is not clickable at point (x, y) can arise from different factors. You can address them by either of the following procedures:
1. Element not getting clicked due to JavaScript or AJAX calls present
Try to use Actions Class:
WebElement element = driver.findElement(By.id("navigationPageButton"));
Actions actions = new Actions(driver);
actions.moveToElement(element).click().build().perform();
2. Element not getting clicked as it is not within Viewport
Try to use JavascriptExecutor to bring the element within the Viewport:
WebElement myelement = driver.findElement(By.id("navigationPageButton"));
JavascriptExecutor jse2 = (JavascriptExecutor)driver;
jse2.executeScript("arguments[0].scrollIntoView()", myelement);
3. The page is getting refreshed before the element gets clickable.
In this case induce ExplicitWait i.e WebDriverWait as mentioned in point 4.
4. Element is present in the DOM but not clickable.
In this case induce ExplicitWait with ExpectedConditions set to elementToBeClickable for the element to be clickable:
WebDriverWait wait2 = new WebDriverWait(driver, 10);
wait2.until(ExpectedConditions.elementToBeClickable(By.id("navigationPageButton")));
5. Element is present but having temporary Overlay.
In this case, induce ExplicitWait with ExpectedConditions set to invisibilityOfElementLocated for the Overlay to be invisible.
WebDriverWait wait3 = new WebDriverWait(driver, 10);
wait3.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("ele_to_inv")));
6. Element is present but having permanent Overlay.
Use JavascriptExecutor to send the click directly on the element.
WebElement ele = driver.findElement(By.xpath("element_xpath"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", ele);
In case you need to use it with Javascript
We can use arguments[0].click() to simulate click operation.
var element = element(by.linkText('webdriverjs'));
browser.executeScript("arguments[0].click()",element);
I ran into this error while trying to click some element (or its overlay, I didn't care), and the other answers didn't work for me. I fixed it by using the elementFromPoint DOM API to find the element that Selenium wanted me to click on instead:
element_i_care_about = something()
loc = element_i_care_about.location
element_to_click = driver.execute_script(
"return document.elementFromPoint(arguments[0], arguments[1]);",
loc['x'],
loc['y'])
element_to_click.click()
I've also had situations where an element was moving, for example because an element above it on the page was doing an animated expand or collapse. In that case, this Expected Condition class helped. You give it the elements that are animated, not the ones you want to click. This version only works for jQuery animations.
class elements_not_to_be_animated(object):
def __init__(self, locator):
self.locator = locator
def __call__(self, driver):
try:
elements = EC._find_elements(driver, self.locator)
# :animated is an artificial jQuery selector for things that are
# currently animated by jQuery.
return driver.execute_script(
'return !jQuery(arguments[0]).filter(":animated").length;',
elements)
except StaleElementReferenceException:
return False
You can try
WebElement navigationPageButton = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.id("navigationPageButton")));
navigationPageButton.click();
Scrolling the page to the near by point mentioned in the exception did the trick for me. Below is code snippet:
$wd_host = 'http://localhost:4444/wd/hub';
$capabilities =
[
\WebDriverCapabilityType::BROWSER_NAME => 'chrome',
\WebDriverCapabilityType::PROXY => [
'proxyType' => 'manual',
'httpProxy' => PROXY_DOMAIN.':'.PROXY_PORT,
'sslProxy' => PROXY_DOMAIN.':'.PROXY_PORT,
'noProxy' => PROXY_EXCEPTION // to run locally
],
];
$webDriver = \RemoteWebDriver::create($wd_host, $capabilities, 250000, 250000);
...........
...........
// Wait for 3 seconds
$webDriver->wait(3);
// Scrolls the page vertically by 70 pixels
$webDriver->executeScript("window.scrollTo(0, 70);");
NOTE: I use Facebook php webdriver
If element is not clickable and overlay issue is ocuring we use arguments[0].click().
WebElement ele = driver.findElement(By.xpath("//div[#class='input-group-btn']/input"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", ele);
The best solution is to override the click functionality:
public void _click(WebElement element){
boolean flag = false;
while(true) {
try{
element.click();
flag=true;
}
catch (Exception e){
flag = false;
}
if(flag)
{
try{
element.click();
}
catch (Exception e){
System.out.printf("Element: " +element+ " has beed clicked, Selenium exception triggered: " + e.getMessage());
}
break;
}
}
}
In C#, I had problem with checking RadioButton,
and this worked for me:
driver.ExecuteJavaScript("arguments[0].checked=true", radio);
Can try with below code
WebDriverWait wait = new WebDriverWait(driver, 30);
Pass other element would receive the click:<a class="navbar-brand" href="#"></a>
boolean invisiable = wait.until(ExpectedConditions
.invisibilityOfElementLocated(By.xpath("//div[#class='navbar-brand']")));
Pass clickable button id as shown below
if (invisiable) {
WebElement ele = driver.findElement(By.xpath("//div[#id='button']");
ele.click();
}
I am trying to automate functional testing of a web application using Selenium and Java. In my application there are several menus. When clicked on a particular menu, a drop down of sub menus appear
click to view screenshot of menu
I use below code to click sub menu
driver.findElement(By.xpath("id=menu")).click();
driver.findElement(By.xpath("id=sub_menu_a")).click();
but the issue is that it throws a 'ElementNotVisibleException' at the second line. The same happens even if I use implicit wait
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
explicit wait
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("id=sub_menu_a")));
and fluent wait.
Wait<WebDriver> fluentWait=new FluentWait<WebDriver>(driver)
.withTimeout(60, TimeUnit.SECONDS)
.pollingEvery(2, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class,ElementNotVisibleException.class);
WebElement element=fluentWait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver){
driver.findElement(By.xpath("id=menu"));
return driver.findElement(By.xpath("id=sub_menu_a"));
}
});
element.click();
but no luck. But the code works fine if add sleep time using
Thread.sleep(sleeptime);
before and after the first line of code. But it is not a permanent solution since the page load time may vary depend on the network speed and the data in the page. Is there any other solution?
Try this
WebElement menu=driver.findElement(By.xpath("id=menu"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", menu);
WebElement subMenu=driver.findElement(By.xpath("id=sub_menu_a"));
executor.executeScript("arguments[0].click();", subMenu);
Hope this work
Try to use Actions class and see if it works or not ...
driver.findElement(By.xpath("id=menu")).click();
WebElement subMenu=driver.findElement(By.xpath("id=sub_menu_a"));
Actions myaction = new Actions(driver);
myaction.moveToElement(subMenu);
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.elementToBeClickable(subMenu));
myaction.click().perform();
Fluent waits should work fine.
Try using something like this:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("id=sub_menu_a")));
but I would go for css Selectors they are perfect for html pages.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#sub_menu_a")));
Or if your sub_menu_a is a child of menu I would go for
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#menu #sub_menu_a")));
Could you try
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("id=sub_menu_a")));
Also it would be better if you can give html to find the right xpath as I think better XPATH will yield the result of click on the submenu.
Long time ago I have the similar issue (don't remember the exact case so indeed your HTML page snipped would be helpful) so I was forced to use Thread.sleep()
To avoid long waits will propose something like this method:
static void waitAndClick(WebDriver driver, By by, int attempts, int sleep) throws InterruptedException {
for (int i = 0; i < attempts; i++) {
WebElement element = null;
try {
element = driver.findElement(by);
} catch (NoSuchElementException e) {
// Do nothing
}
if (element == null) {
int time = sleep * (i + 1);
Thread.sleep(time);
} else {
element.click();
break;
}
}
throw new NoSuchElementException("Error");
}
It's not a 100% complete solution but just an idea.
I using Selenium 2 and Java 1.7.
I want to wait my HtmlUnitDriver until ajax done when i clicked filter button.
My driver:
Webdriver driver = new HtmlUnitDriver(true);
Filter button and click action:
WebElement weFilterButton = driver.findElement(By.name("filterButton"));
weFilterButton.click();
I tried three ways for wait AJAX done.
first:
WebElement el = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("ctl00_ContentPlaceHolder1_Reports1_ajaxloadingImage")));
second:
Boolean el = wait.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
JavascriptExecutor js = (JavascriptExecutor) driver;
return (Boolean) js.executeScript("return document.readyState").toString().equals("complete");
}
});
and although it is not a good solution
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
but is not work.
EDIT
Selenium dependency is :
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.45.0</version>
</dependency>
Use the code below. It checks if the JQuery is active or not and wait till it is active.
Boolean isJqueryUsed = (Boolean)((JavascriptExecutor)driver).executeScript("return (typeof(jQuery) != 'undefined')"));
if(isJqueryUsed){
while (true){
// JavaScript test to verify jQuery is active or not
Boolean ajaxIsComplete = (Boolean)(((JavascriptExecutor)driver).executeScript("return jQuery.active == 0"));
if (ajaxIsComplete) break;
try{
Thread.sleep(100);
}catch (InterruptedException e) {}
}
}
The main problem is after you click something you have to wait for the ajax load to be invisible not visible.That means you have to wait for the element to fade away or hide.
You can achieve that by using not in ExpectedConditions.It will return a boolean type.If it is true you can proceed .Else increase the wait time and see..
WebDriverWait wait = new WebDriverWait(driver, 60);
Boolean present = wait.until(ExpectedConditions.not(ExpectedConditions.visibilityOfElementLocated(By.id("ctl00_ContentPlaceHolder1_Reports1_ajaxloadingImage"))));
Give a try with "return Ajax.activeRequestCount == 0"