wait.until(ExpectedConditions.elementToBeClickable) is not waiting for the defined time - java

Using Using Selenium WebDriver with Java and I want to click on an element that is present on the page and is visible, but is grayed out, i.e., element is present on the page but the same is not intractable.
So, I am using ExplicitWebDriverWait to wait until that element is clickable and for that I am using below line of code. But the same is not working. Driver is not waiting for the element to become intractable. It is throwing exception, "is not clickable at point (415, 765). Other element would receive the click:".
Now,if I am using static wait instead of this Explicit Waint, I am able to click on the element.
Code which I have written:
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#name='mobile']")));
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[#name='mobile']")));
newNum.click();
Script Log:
Trying to locate: By.xpath: //*[#name='mobile']
Located element:By.xpath: //*[#name='mobile']
Trying to locate: By.xpath: //*[#name='mobile']
Located element:By.xpath: //*[#name='mobile']
Trying to locate: By.xpath: //*[#name='mobile']
Located element:By.xpath: //*[#name='mobile']
Trying to click on:[[ChromeDriver: chrome on XP (7686dd92e2bb577696qa2e1aa13effd6)] -> xpath: //*[#name='mobile']]
Exception occured:org.openqa.selenium.WebDriverException: unknown error: Element <input id="abc-radiobox-2032-inputEl" data-ref="inputEl" type="text" role="combobox" size="1" name="mobile" placeholder="- select option -" readonly="readonly" class="dummyclass" autocomplete="off" componentid="gwc-combobox-2032"> is not clickable at point (415, 765). Other element would receive the click: <div class="anotherclass" role="status" id="loadmask-1985" tabindex="0" componentid="loadmask-1985" style="">...</div>
(Session info: chrome=71.0.3578.98)
(Driver info: chromedriver=2.41.578737 (49da6702b16031c40d63e1234de03a32ff6c197e),platform=Windows NT 10.0.10586 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 0 milliseconds

According to the error you are getting:
Exception: is not clickable at point (415, 765). Other element would receive the click:
Seems like driver is not able to even find the particular element, so its not waiting until it becomes clickable. Mostly whenever this type of error occurs, we can use JavaScript Clicks instead of using wait or any other types of clicks.
Try the below code: make sure element locator's value should be good enough to locate the element uniquely:
WebElement element = driver.findElement(By.xpath("//*[#name='mobile']"));
JavascriptExecutor Js = (JavascriptExecutor)driver;
Js.executeScript("arguments[0].clicks();", element)
This code always works for me. Sometimes I need to insert scrollIntoView() method to scroll the page to the element to perform action on it.

You should wait, until the element is visible. And then need to check whether element is in enable state(clickable state) or not. After that only, you have to perform the click operation.
Steps
1.Create Firefox browser session
2.Navigate to the page as per you requirement
3.Wait, until the web element (//*[#name='mobile']) is visible [wait for approximately 15 seconds]
[What is web element ? Ans : Whatever the action you are going to perform with this element. This element may be a button , link, icon, text field, etc..]
4.Now check the element, it is in clickable state(enable state) or not
5.If it is in clickable state(enable state), then perform the click operation.
public void test_01_ButtonClick()
{
WebDriver driver = new FirefoxDriver();
driver.navigate().to("www.hlo.com");
//Here will check element is visible or not
waitForElementInDOM(driver, "//*[#name='mobile']", 15);
//Here will check element is enable or not
boolean enable = elementIsEnable(driver, "//*[#name='mobile']");
if(enable)
{
driver.findElement(By.xpath("//*[#name='mobile']")).click();
}
else
{
System.out.println("Element not visible. Please increase your waiting time");
}
}
----------------------------------------------------------------------------
public void waitForElementInDOM(WebDriver driver,String elementIdentifier, long
timeOutInSeconds)
{
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds );
try
{
//this will wait for element to be visible for 15 seconds
wait.until(ExpectedConditions.visibilityOfElementLocated
(By.xpath(elementIdentifier)));
}
catch(NoSuchElementException e)
{
e.printStackTrace();
}
}
-------------------------------------------------------------------------------
public boolean elementIsEnable(WebDriver driver, String elementIdentifier)
{
WebElement element = driver.findElement(By.xpath("elementIdentifier"));
if(element.isEnabled())
{
return true;
}
else
{
return false;
}
}

Related

Java and Selenium: Extreme StaleElementReferenceException

I'm experiencing a StaleElementReferenceExpection that seems beyond all reason in an application. It involves absolutely no refreshing or reloading of the page, but just two consecutive actions of accessing the element - one click and one assertion that the element is not selected.
Java/Selenium code:
this.element.findElement(By.cssSelector("input[type='checkbox']")).sendKeys(Keys.SPACE);
(SPACE is used because when usng click, Selenium claims "ElementClickInterceptedExcpetion - other element would receive the click")
assertThat(this.element.findElement(By.cssSelector("input[type='checkbox']")).isSelected()).isFalse();
This results in:
org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
even when I use brake points int the code, and skip slowly through each step.
Markup:
<div class="hb-cell hb-cell--autoWidth">
<input tusenskilletegn="" id="utgift-2-belop">
<input type="checkbox" id="utgift-2-inkludert">
<div class="hb-label>
<label class="hb-label-tekst" for="utgift-2-inkludert"></label>
</div>
</div>
Also tried accessing the for" in the label, with no luck: (using partial match, in this example)
this.element.findElement(By.cssSelector("label[for$=-inkludert]")).click();
It results in
org.openqa.selenium.ElementNotInteractableException: element not interactable
Any ideas? Selenium seems to have become impossible for me to use lately, with this type of error occuring all "over the place".
If you have issues with the click() function you could always just click it using JS
public void clickWebElementUsingJS(WebElement element) {
JavascriptExecutor executor = (JavascriptExecutor) driver;
executor.executeScript("arguments[0].click();", element);
}
As for the StaleElementReferenceExpection instead of adding an arbitrary Thread.sleep you could just write a little helper method using ExpectedConditions to click it and wait for the element to go stale, then just find the element again.
private WebElement clickCheckBoxAndWaitToGoStale() {
final By byCSS = By.cssSelector("input#utgift-2-inkludert");
// find the element
WebElement checkbox = this.element.findElement(byCSS);
// click it
clickWebElementUsingJS(checkbox ); // or sendKeys(Keys.SPACE) if this doesn't work or you just prefer it
// wait for the WebElement variable to go stale
try {
new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(5))
.pollingEvery(Duration.ofSeconds(1))
.ignoring(StaleElementReferenceException.class)
.ignoring(NullPointerException.class)
.until(ExpectedConditions.invisibilityOf(element));
} catch (WebDriverException e) {
// log
}
// re-find and return the checkbox to run the assert on
return this.element.findElement(byCSS);
}

Selenium can't find iframe after postback inside the iframe after finding one element inside the frame

I am trying to create a test where I have to fill out some information inside an iframe. Getting access to the iframe work fine and I can fill out information inside the frame. The issue is that when I find out a element 'A' it has a postback attached to it which reloads the content inside the iframe, to find out another element 'B'. So i am not able to find that element.I am getting below error:
org.openqa.selenium.WebDriverException: unknown error: Element <iframe style="overflow-x:hidden;" id="t5" height="1350" frameborder="0" width="98%" src="https://edata.ndtv.com/coronavirus/table/india_table.html?shgraph=1&days=7" cd_frame_id_="7da8f2aea5a580b3a6e90a9d5016fa0d">...</iframe> is not clickable at point (554, 7). Other element would receive the click: <div class="topnav2014" style="border-bottom: none;">...</div>
(Session info: chrome=85.0.4183.83)
Here are my observations: When I first locate the iframe it looks like this:
<iframe style="overflow-x:hidden;" id="t5" height="1350" frameborder="0" width="98%" src="https://edata.ndtv.com/coronavirus/table/india_table.html?shgraph=1&days=7">
After the postback has occurred it looks like this:
<iframe style="overflow-x:hidden;" id="t5" height="1350" frameborder="0" width="98%" src="https://edata.ndtv.com/coronavirus/table/india_table.html?shgraph=1&days=7" cd_frame_id_="a5006acf28d8c288313681ab9ad7a4fa">
I can easily find element A:
But element B i am not able to find
The code fails when I try to get hold of the iframe element.
How can I get hold of the iframe again, after the postback inside the frame?
I have tried this suggestion also but it is not working
//Ensure that you are back to the base frame
driver.SwitchTo().DefaultContent();
//SwitchTo the intended frame
driver.SwitchTo().Frame(driver.FindElement(By.XPath("//iframe[contains(#src,'<removed for clearity>')]")));
Use a driver.executescript() for the first problem since another element is receiving the click.
element = driver.findElement(By.id(""));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();", element);
This error message...
org.openqa.selenium.WebDriverException: unknown error: Element <iframe style="overflow-x:hidden;" id="t5" height="1350" frameborder="0" width="98%" src="https://edata.ndtv.com/coronavirus/table/india_table.html?shgraph=1&days=7" cd_frame_id_="7da8f2aea5a580b3a6e90a9d5016fa0d">...</iframe> is not clickable at point (554, 7). Other element would receive the click: <div class="topnav2014" style="border-bottom: none;">...</div>
(Session info: chrome=85.0.4183.83)
...implies that the WebDriverException was raised as you tried to invoke click() on the <iframe> element.
Factually, instead of clicking on the <iframe> element you would invoke click() on an element within the <iframe>. Moreover, as the the desired element is within a <iframe> so you have to:
Induce WebDriverWait for the desired frameToBeAvailableAndSwitchToIt.
Induce WebDriverWait for the desired elementToBeClickable.
You can use either of the following Locator Strategies:
Using xpath:
new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//iframe_xpath")));
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("element_xpath"))).click();
References
You can find a couple of relevant discussions in:
Ways to deal with #document under iframe
Is it possible to switch to an element in a frame without using driver.switchTo().frame(“frameName”) in Selenium Webdriver Java?
I am able to extract the data of the active cases rise and fall for every state. There is a single frame which contains both the locators shared by you. Check below working code.
driver.get("https://www.ndtv.com/coronavirus");
driver.manage().window().maximize();
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(By.className("tab-wrapper")));
driver.switchTo().frame(driver.findElement(By.xpath("//iframe[contains(#src,'https://edata.ndtv.com/coronavirus/table/india_table.html?shgraph=1')]")));
//cases down
List<WebElement> eleCasesUp = driver.findElements(By.xpath("//tr//td[3]//p//span[#class='data-up']"));
List<String> casesUpList = new ArrayList<String>();
for (WebElement element : eleCasesUp) {
casesUpList.add(element.getText());
}
//cases up
List<WebElement> eleCasesDown = driver.findElements(By.xpath("//tr//td[3]//p//span[#class='data-down']"));
List<String> casesDownList = new ArrayList<String>();
for (WebElement element : eleCasesDown) {
casesDownList.add(element.getText());
}
System.out.println("Cases Up List -->" + casesUpList);
System.out.println("Cases Down List -->" + casesDownList);

Selenium - iterate over elements

My goal is:
Iterate on WebElements in a webpage
Click on all elements founded and open link in same session
Parse the new page with some other logic
Return back to prev page and continue the loop for all prev matched id
I have this code:
List<WebElement> links = driver.findElements(By.cssSelector("div[data-sigil='touchable']"));
// this will display list of all images exist on page
for(WebElement ele:links)
{
System.out.println("test->"+ele.getAttribute("id"));
ele.click();
Thread.sleep(500);
System.out.println("URI->"+driver.getCurrentUrl());
js.executeScript("window.history.go(-1)");
}
return "ok";
Which is working fine and it finds correct elements id, "ele.click()" is actually working, but I'm always failing when I execute js.executeScript("window.history.go(-1)")
This is my error message:
org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
(Session info: chrome=73.0.3683.103)
(Driver info: chromedriver=2.40.565498 (ea082db3280dd6843ebfb08a625e3eb905c4f5ab),platform=Windows NT 10.0.17134 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 0 milliseconds
So basically I'm not able to continue the loop.
Is it there any useful technique to "click into new tab" and manage different Selenium driver session?
Thanks a lot in advance for any suggestion.
What is happening is that when you proceed to another page it makes all the elements in the list stale. Those elements are not attached to the page when you come back to the page again. You need to find the elements every time you load the page.
Try this:
List<WebElement> links = driver.findElements(By.cssSelector("div[data-sigil='touchable']"));
// this will display list of all images exist on page
String address;
for(int i=0; i<links.size(); i++){
address = driver.getCurrentUrl();
links = driver.findElements(By.cssSelector("div[data-sigil='touchable']"));
System.out.println("size: "+links.size());
WebElement ele = links.get(i);
System.out.println("test->"+ele.getAttribute("id"));
ele.click();
Thread.sleep(500);
System.out.println("URI->"+driver.getCurrentUrl());
//js.executeScript("window.history.go(-1)");
//driver.navigate().back();
driver.get(address);
}
Edit:
Try the driver.get() as it waits for the page to load. Or you can directly add another sleep as you used after the click.
I think you need to create the js object, like so.
Reason being that you "lost" the reference to the JavascriptExecutor
List<WebElement> links = driver.findElements(By.cssSelector("div[data-sigil='touchable']"));
// this will display list of all images exist on page
for(WebElement ele:links){
System.out.println("test->"+ele.getAttribute("id"));
ele.click();
Thread.sleep(500);
System.out.println("URI->"+driver.getCurrentUrl());
// Re initialise js executor
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.history.go(-1)");
}
return "ok";

Xpath issue in element location

I am getting a very long xpath for an element that I selected. Is there anyway to shorten it? This is the xpath I am getting:
//li[#class='menu_men 1-level hasChild']//div[contains(#class,'level-2')]//div[#class='menu-wrapper']//ul[#class='level-2']//li[#class='1-level']//div[#class='level-3']//ul[#class='level-3']//li//a[#class='level-3'][contains(text(),'Socks')]
This is the URL: Calvin Klein Singapore I hovered over 'MEN', the accessories section will appear, than I hover the 'Socks' to get the xPath.
I am getting the following execption in my code and I am wondering if somehow the long xpath could be one of the reasons:
org.openqa.selenium.NoSuchElementException: no such element: Unable to
locate element: {"method":"xpath","selector":"//li[#class='first
menu_men 1-level
hasChild']//div[contains(#class,'level-2')]//div[#class='menu-wrapper']//ul[#class='level-2']//li[#class='1-level']//div[#class='level-3']//ul[#class='level-3']//li//a[#class='level-3'][contains(text(),'Socks')]"}
I am using cropath from within chrome developer tools to get the xPath.
I am new to automation, I really hope someone can advise. Thank you.
#SameerArora this is the code I have to clear the pop up window, as what I had mentioned in the comments below.
//for clearing the popup window
#FindBy(how=How.XPATH,using="//*[starts-with(#id,'popup-subcription-closes-link-')]")
public WebElement newsletterpopup;
public String clickCategory(){
//.....
resusableFunctions.buttonClick(driver, newsletterpopup, "popoup");
}
public void buttonClick(WebDriver driver, WebElement element, String elementName) throws InterruptedException
{
try
{
element.click();
System.out.println("Log: ResuableFunction.buttonClick");
}
catch (org.openqa.selenium.ElementNotInteractableException notInteract)
{}
The element you are looking for can be found using xpath:
WebElement element = driver.findElement(By.xpath("(//a[contains(text(),'Socks')])[1]"));
However, as the element is not visible directly when you are opening the link, you would be getting NoSuchElementException, so to resolve it you can use javascript click method on the element which directly operates on the div of the page.
Addition to this, i can see that a subscription popup comes when i am opening the page for the first time, so you need to dismiss that popup first(if the popup is present) and then click on the "Socks" element using the JavaScript click method.
Your code should be like:
List<WebElement> closeSubscriptionPopUp = driver.findElements(By.xpath("//a[contains(#id,'popup-subcription-closes-link')]"));
if (closeSubscriptionPopUp.size() > 0) {
closeSubscriptionPopUp.get(0).click();
}
WebElement sockElement = driver.findElement(By.xpath("(//a[contains(text(),'Socks')])[1]"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", sockElement);
To hovered over 'MEN' >> accessories >> 'Socks' section, You need to use selenium Actions class.
As it is not really possible to first click on men(as it will open other section),
So to hover to sock, you need to chain all of the actions that you want to achieve in one go.
Process should be:
move to men element first
Move to accessories
then move to Socks and click on it.
Note: By using Action class, we can chain all the process in one single go.
As mentioned below
1) First way:
Actions action = new Actions(driver);
action.moveToElement(driver.findElement(By.xpath("(//a[contains(text(),'MEN')])[2]")))
.moveToElement(driver.findElement(By.xpath("(//a[contains(text(),'Socks')])[1]")))
.click().build().perform();
2) Second way with wait:
WebDriverWait wait= new WebDriverWait(driver, 10);
Actions action = new Actions(driver);
action.moveToElement(driver.findElement(By.xpath("(//a[contains(text(),'MEN')])[2]"))).build().perform();
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("(//a[contains(text(),'Socks')])[1]")));
action.moveToElement(driver.findElement(By.xpath("(//a[contains(text(),'Socks')])[1]")));
action.click().build().perform();
Try this:
//a[normalize-space(text()) = 'Socks']
I would recommend you to not use such long xpath's and try to write xpath on your own.
Try :
//li[contains(#class,'menu_men')]//a[contains(text(),'Socks')]

aria-hidden span/button prevents from fetching element - Selenium

I am trying to click a calendar from the following website using Selenium with Java (3.3.0 and java version "1.8.0_66").
https://www.cathaypacific.com/cx/en_US.html
Target to be clicked - Flights - One Way - 'Departing On' button
No matter, what possible options I tried - by.id, by.xpath and Actions, EventFiringMouse etc., this button does not get clicked at all.
"<div class="button-date-picker-wrapper field-group cx-inputfield">
<span class="field-label input-filled" aria-hidden="true">Departing on</span>
<button id="dppju1sm" class="button-date-picker field-button from-button has-dates input-filled" role="link" type="button" data-ui-overlay-shared="true" data-ui-overlay-id="trip-dates-picker" aria-expanded="false" aria-label="Departing on Thursday 20 April 2017">
</div>"
private static void pickFlightCode() throws InterruptedException {
WebElement element = driver.findElement(By.xpath("//div[1]/button[starts-with(#id,'dp')]"));
//wdwait.until(ExpectedConditions.elementToBeClickable(element));
Actions actions=new Actions(driver);
actions.moveToElement(element).moveToElement(driver.findElement(By.xpath("//div[1]/button[starts-with(#id,'dp')]"))).click().build().perform();
element = driver.findElement(By.xpath("//div[1]/button[starts-with(#id,'dp')]"));
System.out.println(element.getAttribute("aria-hidden"));
}
(or)
driver.findElement(By.xpath("//div[1]/button[starts-with(#id,'dp')]")).click();
String js = "document.getElementById("field-label").style.display = "block";';
arguments[0].style.visibility='visible';";
The above code does not work and I am getting 'Element Not Visible' Exception.
Driver.findElement - isEnabled returns true and Driver.findElement - isDisplayed returns false.
Is this something to do with the 'aria-hidden'=true attribute in span? How should we handle 'aria-hidden' and click on the button?
In order to reach to the required control, you can make use of its container. Hence, try following:
//div[#data-date-picker-id='book-trip']//button[starts-with(#id,'dp') and starts-with(#aria-label, 'Departing on ')]
Let me know, whether it works for you.
Try this for the button's xpath -
//div[#class = 'dates-picker-wrapper splited-date-picker flight-datepicker']/div[1]/button
I have checked this in Firefox and it working for me.
Try this JavaScript code to enable visibility of selected element.
WebElement element = driver.findElement(By.xpath("Element Xpath"));
String js = "arguments[0].style.height='auto'; arguments[0].style.visibility='visible';";
((JavascriptExecutor) driver).executeScript(js, elem);

Categories