Is it possible to execute a command while waiting for an element to appear? In particular I'm waiting for an element to appear but it's not going to appear unless I refresh the page. Here's my code
wait = new WebDriverWait(driver, 30);
element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("xpath_here")));
state = element.getText();
The element I'm waiting for is never going to appear unless I hit the app's refresh button. How can I refresh during the 30 second timeout that I set?
You can do something like this:
System.out.println("before wait");
WebElement el = (new WebDriverWait(driver, 30))
.until(new ExpectedCondition<WebElement>(){
//try the following cycle for 30 seconds
#Override
public WebElement apply(WebDriver driver) {
//refresh the page
driver.navigate().refresh();
System.out.println("Refreshed");
//look for element for 5 seconds
WebElement sameElement = null;
try{
sameElement = (new WebDriverWait(driver, 5))
.until(new ExpectedCondition<WebElement>(){
#Override
public WebElement apply(WebDriver driver) {
System.out.println("Looking for the element");
return driver.findElement(By.id("theElementYouAreLookingFor"));
}});
} catch (TimeoutException e){
// if NULL is returns the cycle starts again
return sameElement;
}
return sameElement;
}});
System.out.println("Done");
It will try to get the element for 30 seconds, refreshing the page every 5 seconds.
I would add more lines to that code: basically, if state.isEmpty() then use a Webdriver "Action" class to move the mouse to the refresh button (you app would need a refresh button inside of it for this to work) then run the wait one more time to verify it appears.
Related
I am trying to make some tests using selenium based Katalon Studio. In one of my tests I have to write inside a textarea. The problem is that I get the following error:
...Element MyElement is not clickable at point (x, y)... Other element would receive the click...
In fact my element is place inside some other diva that might hide it but how can I make the click event hit my textarea?
Element ... is not clickable at point (x, y). Other element would receive the click" can be caused for different factors. You can address them by either of the following procedures:
Element not getting clicked due to JavaScript or AJAX calls present
Try to use Actions Class:
WebElement element = driver.findElement(By.id("id1"));
Actions actions = new Actions(driver);
actions.moveToElement(element).click().build().perform();
Element not getting clicked as it is not within Viewport
Try to use JavascriptExecutor to bring the element within Viewport:
JavascriptExecutor jse1 = (JavascriptExecutor)driver;
jse1.executeScript("scroll(250, 0)"); // if the element is on top.
jse1.executeScript("scroll(0, 250)"); // if the element is at bottom.
Or
WebElement myelement = driver.findElement(By.id("id1"));
JavascriptExecutor jse2 = (JavascriptExecutor)driver;
jse2.executeScript("arguments[0].scrollIntoView()", myelement);
The page is getting refreshed before the element gets clickable.
In this case induce some wait.
Element is present in the DOM but not clickable.
In this case add some ExplicitWait for the element to be clickable.
WebDriverWait wait2 = new WebDriverWait(driver, 10);
wait2.until(ExpectedConditions.elementToBeClickable(By.id("id1")));
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")));
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);
I assume, you've checked already that there is no any other component overlapping here (transparent advertisement-iframes or some other component of the DOM => seen quite often such things in input/textfield elements) and, when manually (slowly) stepping your code, it's working smoothly, then ajax calls might cause this behaviour.
To avoid thread.sleep, try sticking with EventFiringWebDriver and register a handle to it.
(Depending on your application's techstack you may work it for Angular, JQuery or wicket in the handler, thus requiring different implementations)
(Btw: This approach also got me rid of "StaleElementException" stuff lots of times)
see:
org.openqa.selenium.support.events.EventFiringWebDriver
org.openqa.selenium.support.events.WebDriverEventListener
driveme = new ChromeDriver();
driver = new EventFiringWebDriver(driveme);
ActivityCapture handle=new ActivityCapture();
driver.register(handle);
=> ActivityCapture implements WebDriverEventListener
e.g. javascriptExecutor to deal with Ajax calls in a wicket/dojo techstack
#Override
public void beforeClickOn(WebElement arg0, WebDriver event1) {
try {
System.out.println("After click "+arg0.toString());
//System.out.println("Start afterClickOn - timestamp: System.currentTimeMillis(): " + System.currentTimeMillis());
JavascriptExecutor executor = (JavascriptExecutor) event1;
StringBuffer javaScript = new StringBuffer();
javaScript.append("for (var c in Wicket.channelManager.channels) {");
javaScript.append(" if (Wicket.channelManager.channels[c].busy) {");
javaScript.append(" return true;");
javaScript.append(" }");
;
;
;
javaScript.append("}");
javaScript.append("return false;");
//Boolean result = (Boolean) executor.executeScript(javaScript.toString());
WebDriverWait wait = new WebDriverWait(event1, 20);
wait.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return !(Boolean) executor.executeScript(javaScript.toString());
}
});
//System.out.println("End afterClickOn - timestamp: System.currentTimeMillis(): " + System.currentTimeMillis());
} catch (Exception ex) {
//ex.printStackTrace();
}
}
As #DebanjanB said, your button (or another element) could be temporarily covered by another element, but you can wait and click it even if you don't know which element is covering the button.
To do this, you can define your own ExpectedCondition with the click action:
public class SuccessfulClick implements ExpectedCondition<Boolean> {
private WebElement element;
public SuccessfulClick(WebElement element) { //WebElement element
this.element = element;
}
#Override
public Boolean apply(WebDriver driver) {
try {
element.click();
return true;
} catch (ElementClickInterceptedException | StaleElementReferenceException | NoSuchElementException e) {
return false;
}
}
}
and then use this:
WebDriverWait wait10 = new WebDriverWait(driver, 10);
wait10.until(elementToBeClickable(btn));
wait10.until(new SuccessfulClick(btn));
Try Thread.Sleep()
Implicit - Thread.Sleep()
So this isn’t actually a feature of Selenium WebDriver, it’s a common feature in most programming languages though.
But none of that matter.
Thread.Sleep() does exactly what you think it does, it’s sleeps the thread. So when your program runs, in the majority of your cases that program will be some automated checks, they are running on a thread.
So when we call Thread.Sleep we are instructing our program to do absolutely nothing for a period of time, just sleep.
It doesn’t matter what our application under test is up to, we don’t care, our checks are having a nap time!
Depressingly though, it’s fairly common to see a few instances of Thread.Sleep() in Selenium WebDriver GUI check frameworks.
What tends to happen is a script will be failing or failing sporadically, and someone runs it locally and realises there is a race, that sometimes WedDriver is losing. It could be that an application sometimes takes longer to load, perhaps when it has more data, so to fix it they tell WebDriver to take a nap, to ensure that the application is loaded before the check continues.
Thread.sleep(5000);
The value provided is in milliseconds, so this code would sleep the check for 5 seconds.
I was having this problem, because I had clicked into a menu option that expanded, changing the size of the scrollable area, and the position of the other items. So I just had my program click back on the next level up of the menu, then forward again, to the level of the menu I was trying to access. It put the menu back to the original positioning so this "click intercepted" error would no longer happen.
The error didn't happen every time I clicked an expandable menu, only when the expandable menu option was already all the way at the bottom of its scrollable area.
I am clicking one element and I am using wait function to identify the next element. This is the wait function.
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("some xpath")));
After identifying the element, I carry out other actions but when I click for the 1st element it will lead to next page so by the time page loads the wait function is applying for the current page and giving exception. Is there any solution for this? I tried
Browser.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
before wait but it's not working. It will only work if I use thread.sleep(1000) before wait but I dont want use thread.sleep().
I'm guessing the problem is with the fact that you are using
ExpectedConditions.presenceOfElementLocated(...)
Presence just means that the element is present in the DOM, not that it's visible, enabled, clickable, etc. I would suggest that you change to wait to match what you want to do with the element you are looking for. If you want to click it, wait for it to be clickable. If you want to get text from it, wait for it to be visible, etc.
Another issue may be that you are intending to wait for an element on page 2 but an element matches that locator on page 1. One solution is to find a unique element on page 2, wait for it to be visible, and then wait for your desired element. That way you ensure that you are on the correct page before waiting for the desired element on page 2.
I think there are 2 waits in this situation:
Wait for next page loaded
Wait for specified element loaded in the new page
Below is an option to wait for page loaded:
public void waitForLoad() {
ExpectedCondition<Boolean> condition = webDriver -> webDriver.getCurrentUrl().contains(getPageUrl());
WebDriverWait wait = new WebDriverWait(driver, pageLoadTimeout);
wait.until(condition);
}
Then wait for next element visible:
protected void waitFor(By by) {
ExpectedCondition<Boolean> condition = webDriver -> !webDriver.findElements(by).isEmpty();
WebDriverWait wait = new WebDriverWait(driver, pageLoadTimeout);
wait.until(condition);
}
or using other solutions:
public WebElement elementToBeClickable(By locator, int timeout) {
try {
return getWebDriverFluentWait(timeout)
.until(ExpectedConditions.elementToBeClickable(locator));
} catch (Exception e) {
return null;
}
}
with:
private Wait<WebDriver> getWebDriverFluentWait(int timeout) {
return new FluentWait<WebDriver>(driver)
.withTimeout(timeout, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
}
I think you want to click on element, so use elementToBeClickable
WebDriverWait wait=new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.elementToBeClickable(locator))
I also Have the same Problem
But using this I solved
WebElement element = (new WebDriverWait(driver, 30)).until(ExpectedConditions.elementToBeClickable(By.xpath(".//*[#class='IM_overlay']"))); //it will wait 30 second for get this element
element .click();
//You can Do any operator here
If the element that is to be clicked is in the next(new) page, you'll have to use the windows iterator.
You could use this code:
Set <Strings> ids = driver.getWindowHandles();
Iterator <String> it = ids.iterator();
String currentPage = it.next();
String newPage = it.next();
driver.switchTo().window(newPage);//this will switch to the new window. Use your 'wait' condition now and do all the operations
//now to switch back to the previous(current) window, you could use the below code
driver.switchTo().window(currentPage);
In my project, there has one advertisement provider who shows us pop up advertisement but Problem is this pop-up will come it's not fixed.Sometimes add not show sometimes comes this pop up after 1 minute and interrupts my test case.
I write a code for close this popup but it's not a perfect solution I think..If anyone can help?
boolean Imclose = wd.findElement(By.xpath(".//*[#class='IM_overlay_close_container IM_overlay_close_button']")).isDisplayed();
if (Imclose == true) {
wd.findElement(By.xpath(".//*[#class='IM_overlay_close_container IM_overlay_close_button']")).click();
}
Try these code, to handle the unwanted pop up page. I have provided 180 seconds of wait. Then Click on close button inside the advertisement pop up page.
After click on advertisement pop up page, another window is getting open, So I have to redirect to my main window, then only further code will execute.
driver.get("https://www.rentbyowner.com/usa");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
try
{
WebDriverWait wait = new WebDriverWait(driver, 180);
wait.until(ExpectedConditions.visibilityOf(driver.findElement(By.xpath("//div[contains(#class,'IM_overlay_foreground')]"))));
driver.findElement(By.xpath("//div[contains(#class,'IM_overlay_foreground')]//span[#class='IM_close_text']")).click();
try
{
String winHandleBefore = driver.getWindowHandle();
for(String winHandle : driver.getWindowHandles())
{
driver.switchTo().window(winHandle);
//driver.switchTo().window(winHandle).close();
}
driver.switchTo().window(winHandleBefore);
//Verify purpose written code, weather my driver is getting move to parent window or not.
WebDriverWait element = new WebDriverWait(driver, 10);
element.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.id("top_k_search"))));
driver.findElement(By.id("top_k_search")).clear();
System.out.println("Try block");
}
catch(Exception a)
{
System.out.println("Inner Catch");
}
}
catch(Exception e)
{
System.out.println("Element not present");
//Provide your code here..
}
I observed that this is a normal pop-up overlay over the webpage and not an alert and it appears almost within 60 seconds. So, the below code might just work for you.
//Waiting for the Popup to appear
WebDriverWait wait = new WebDriverWait(driver,60);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[contains(#class,'IM_overlay_foreground')]")));
//Clicking on the 'Close' text to close the popup.
driver.findElement(By.xpath("//div[contains(#class,'IM_overlay_foreground')]//span[#class='IM_close_text']")).click();
NOTE: You can increase the time from 60 to 90, in case it appears to take longer. Thing is, whenever the popup appears within the timeframe set, it is handled(as in Closed).
Actually it is coming after 30-50 seconds so you have to wait and then click on close button.
System.setProperty("webdriver.chrome.driver", "E:\\software and tools\\chromedriver_win32\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://www.rentbyowner.com/usa");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
WebElement ad=driver.findElement(By.xpath(".//*[#id='IM_target_overlay']/div/div/div/div[1]/a/div"));
WebDriverWait wait= new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.visibilityOf(ad));
ad.click();
Refer this link for more information:
Handling Alerts in Selenium Webdriver
The Code is:
public void setRing(int index, String ringPattern) throws InterruptedException {
List<WebElement> webElementList = driver.findElements(By.xpath(an.getProperty("an_ringPattern")));
webElementList.get(index).click();
List<WebElement> options = webElementList.get(index).findElements(By.tagName("option"));
for (WebElement element : options) {
if (element.getText().equals(ringPattern)) {
element.click();
Thread.sleep(2000);
}
}
}
When I execute this code in debug mode, it is working fine. It selects whatever value I pass to the method.
But when I run this code it is not able to change the value in the drop down. It selects the value in the drop down, but it's not able to set the value.
Please let me know if I am missing something.
If the Exception .Error message display below at org.openqa.selenium.support.ui.WebDriverWait.timeoutException(WebDriverWait.java:80) is being thrown, means that somehow that element is not ready on the frame, the driver is not on that frame or the xpath is wrong.
You can try to switch to the frame where the element is located, like this: driver.switchToFrame("here goes the id of the frame"); You can inspect the ID of the frame or sometimes just passing the integer 0 works. Also, I would rather use wait1.until(ExpectedConditions.visibilityOfElementLocated(element)); instead of wait1.until(ExpectedConditions.presenceOfElementLocated(element));.
When you use presenceOfElementLocated, you cant assure that the element is visible for the driver.
You can use explicit wait in selenium - WebDriverWait
Use below modified code
public void setRing(int index, String ringPattern) throws InterruptedException {
List<WebElement> webElementList = driver.findElements(By.xpath(an.getProperty("an_ringPattern")));
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.presenceOfElementLocated(webElementList.get(index)));
webElementList.get(index).click();
List<WebElement> options = webElementList.get(index).findElements(By.tagName("option"));
for (WebElement element : options) {
WebDriverWait wait1 = new WebDriverWait(driver, 60);
wait1.until(ExpectedConditions.presenceOfElementLocated(element));
if (element.getText().equals(ringPattern)) {
element.click();
Thread.sleep(2000);
}
}
}
There is a html page with button, and my selenium test is testing, that there is an action executed, when the button is clicked.
The problem is, that it looks like the click happens before the javascript is executed - before the handler is bound to the page. The consequence is, that the selenium test will click on the button, but no action happens.
I can solve this problem by repeatedly trying to click and then observe, if the desired action happened (some element is present on page, typically). I'd like to hear that there are some more elegant solutions...
There is no clear way to say "wait until element X has such-and-such handler"; this is a limitation of JavaScript and the DOM (see for example Get event listeners attached to node using addEventListener and jQuery find events handlers registered with an object), and for that matter a selenium Expected Condition can't be created, at least not trivially.
I've resorted to time.sleep(0.5).
You can write some logic to handle this.
I have write a method that will return the WebElement and this method will be called three times or you can increase the time and add a null check for WebElement
Here is an example
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
driver.get("https://www.crowdanalytix.com/#home");
WebElement webElement = getWebElement(driver, "homekkkkkkkkkkkk");
int i = 1;
while (webElement == null && i < 4) {
webElement = getWebElement(driver, "homessssssssssss");
System.out.println("calling");
i++;
}
System.out.println(webElement.getTagName());
System.out.println("End");
driver.close();
}
public static WebElement getWebElement(WebDriver driver, String id) {
WebElement myDynamicElement = null;
try {
myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By
.id(id)));
return myDynamicElement;
} catch (TimeoutException ex) {
return null;
}
}