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);
}
Related
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);
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;
}
}
I've spent the last few days writing tests in Cucumber. The tests I've written so far work fine, I've been able to click objects, sendkeys over. No problem.
I've now gotten to these page elements that cannot be found no matter what selector I use. I've tried using wait, but even though they are clearly visible on the page, they can't be accessed.
This is happening in both table row elements that I want to click on, and a text input I want to sendkeys to. I've included the latter below.
<input type="text" name="EMPLOYEE_label" value="" class=""
onkeypress="return dtPk(event,this);" onkeydown="return dtKd(event,this);"
onchange="dltCh(this,'EMPLOYEE__test');" size="30" wbvalid="true"
isresolving="false">
Here is the code I am using at present.
webdriver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(webdriver, 30);
wait.until(ExpectedConditions.visibilityOfElementLocated(By
.name("EMPLOYEE_label")));
JOptionPane.showMessageDialog(null, "WebDriver =" + webdriver);
WebElement empIDTextInput = webdriver.findElement(By.name("EMPLOYEE_label"));
empIDTextInput.sendKeys("Bennett");
Thread.sleep(1000);
gtaProxyPage.clickFindButton().click();
Thread.sleep(1000);
gtaProxyPage.checkAssociateBox().click();
gtaProxyPage.loadTimesheet().click();
Thread.sleep(2000);
EDIT:
I changed the code to this. It more closely resembles what I started with
Thread.sleep(30000);
//this calls for the input element by className.
gtaProxyPage.UserEntersNumberUnderTimesheet().click();
gtaProxyPage.clickFindButton().click();
gtaProxyPage.checkAssociateBox().click();
gtaProxyPage.loadTimesheet().click();
This is the error I'm getting now
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"class name","selector":"input.triggerButton"}
I switched what I"m doing to click a button that opens a modal, and allows me to use a text field within that. But the button is not being seen.
This error message...
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"class name","selector":"input.triggerButton"}
...implies that the no such element was found using the Locator Strategy with classname attribute as input.triggerButton.
Irespective of all the changes and manipulation done while publishing the relevant HTML within the question, to send a character sequence to the element:
<input type="text" name="EMPLOYEE_label" value="" class="" onkeypress="return dtPk(event,this);" onkeydown="return dtKd(event,this);" onchange="dltCh(this,'EMPLOYEE__test');" size="30" wbvalid="true" isresolving="false">
As the element is a dynamic element you have to induce WebDriverWait for the element to be clickable and you can use either of the following solutions:
cssSelector:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("input[name='EMPLOYEE_label'][onchange*='EMPLOYEE__test']"))).sendKeys("Bennett");
xpath:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//input[#name='EMPLOYEE_label' and contains(#onchange, 'EMPLOYEE__test')]"))).sendKeys("Bennett");
I have submit button, which is only one on the page, and it's in form.
html part:
<form class="search-form ng-touched ng-dirty ng-valid" novalidate="" style="" xpath="1">
<div class="row">...</div>
<div class="row">...</div>
<div class="row">...</div>
<div class="form__actions" xpath="1">
<div class="form__buttons">
<!---->
<div class="btn__wrapper">
<button class="btn btn__primary" type="submit">
Select My Car
</button>
</div>
</div>
</div>
</form>
So, I'm taking xpath:
//button[#type='submit']
I'm successfully pressing it via submit() (let me skip WebDriver init, its fine):
WebElement searchButton = driver.findElement(By.xpath("//button[#type='submit']"));
searchButton.submit();
(and some search performs)
But when I'm trying to press it via click()
WebElement searchButton = driver.findElement(By.xpath("//button[#type='submit']"));
searchButton.click();
it's not pressed in browser which is launched, and same time Junit test is green (not test, but just pressing button):
#Test
public void test() {
WebElement button = driver.findElement(By.xpath("//button[#type='submit']"));
button.click();
}
Can please someone explain, why submit() successfully presses button in such case, but click() - no. And I do not understand, why "test" is green, when we are trying to click(), but it was not performed, if looking on browser launched by driver.
UPDATED:
I tried
WebElement button = driver.findElement(By.xpath("//button[#type='submit']"));
if (button.isEnabled()) {
button.click();
}
and
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(button)).click();
but still the same - submit() works fine, click() - does not.
The method object.submit() is there for submitting the form to the server. It has another advantage, in case if you're not able to locate the "submit" button then you can take any object of the form and trigger submit() function.
It seems in searchButton.submit(); searchButton is an element of the form and the submit action on it triggers submission of form on server.
Now, why searchButton.click(); not working here could have following reasons.
The button is visible but not enabled.
Driver is finding the 2
instances of searchButton element.
Suggestion: Evaluate following code and check it returns more than one element. If it does then you're clicking on the wrong instance.
List<WebElements> e = driver.findElements(By.xpath("//button[#type='submit']"));
Also try,
driver.findElement(By.xpath(".//button[#class='btn btn__primary'][#type='submit']")).click()
http://docs.seleniumhq.org/docs/03_webdriver.jsp#user-input-filling-in-forms
submit()
submit() method is defined as :
void submit()
Throws:
NoSuchElementException - If the given element is not within a form
As per the JavaDocs when you invoke submit() on an WebElement, if this current element is a form, or an element within a form, then this will be submitted to the remote server. If this causes the current page to change, then this method will block until the new page is loaded.
click()
click() method is defined as :
void click()
Throws:
StaleElementReferenceException - If the element no longer exists as initially define
As per the JavaDocs when you invoke click() on an WebElement and if this causes a new page to load, you should discard all references to this element and any further operations performed on this element will throw a StaleElementReferenceException. Note that if click() is done by sending a native event (which is the default on most browsers/platforms) then the method will not wait for the next page to load and the caller should verify that themselves. There are some ExpectedConditions for an element to be clicked. The element must be visible and it must have a height and width greater then 0.
Your Usecase :
In your usecase, the target WebElement //button[#type='submit'] is within a <form> tag. You are able to successfully press it via submit() as it blocks the method untill the new page is loaded completely as a result of submission on the previous page. Hence the following works :
WebElement searchButton = driver.findElement(By.xpath("//button[#type='submit']"));
searchButton.submit();
But when you try click() method as below, click() being a native event doesn't waits for the new page to load completely. Hence invoking click() method fails.
WebElement button = driver.findElement(By.xpath("//button[#type='submit']"));
button.click();
Your Code Trials :
Validating the button.isEnabled() condition won't fetch us the required result if the element is clickable or not as isEnabled() validates Is the element currently enabled or not? This will generally return true for everything leaving out the disabled input elements. But necessarily isEnabled() wouldn't be validating if the WebElement is visible, interactable and clickable or not.
Solution :
As per the details provided, the solution to invoke click() method would be to induce WebDriverWait with ExpectedConditions clause set to elementToBeClickable as below :
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//button[#type='submit']"))).click();
Update :
Best Practice :
As per the updated HTML and your subsequent comment where you mentioned about Angular4 being used in your app, a much more effective way would be to construct the xpath mocking the HTML DOM as follows :
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//form[#class='search-form ng-touched ng-dirty ng-valid']//button[#class='btn btn__primary' and #type='submit']"))).click();
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);