I'm trying to access a screen in an application, which appears when I do a mouse-hover over a tab and click on one of the options. I used Actions method to execute this using selenium. Here's my code:
element=driver.findElement(By.id("tab"));
Actions hoverover=new Actions(driver);
hoverover.moveToElement(element).moveToElement(driver.findElement(By.id("menu"))).click().build().perform();
When I login to the application and directly call this tab, I'm able to access this without any issue. But the problem occurs when I access this tab from a different screen in the application.
Whenever I access the hover-over page from a different page in the application, sometimes the page loads correctly but most of the time it fails and I recieve 'no such element' or 'stale element reference' error.
I'm really not sure how it is able to access the tab without any issue sometimes and how sometimes it is throwing errors. Please guide me here and let me know if there is anything else(any additional functions/or an alternative to Actions?) I can do so that the mouse-over click works all the time.
EDIT: I tried using both Explicit and Implicit waits and even thread.sleep as well, but in vain. In Chrome(only in chrome) when i do a manual screen refresh while it tries to access the tab, it works. But when I do the same in my code [driver.navigate().refresh()], it's not working!!
The stale element exception is probably occurring between when you set element and when you hoverover. Selenium does something like:
WebElement element = driver.findElement(By.id("tab"));
// "element" has been set
Actions hoverover=new Actions(driver);
// Between here and hoverover, "element" has changed on the DOM
hoverover.moveToElement(element).moveToElement(
driver.findElement(By.id("menu"))).click().build().perform();
// Uh-oh, what's "element?" Better throw an exception!
Try eliminating the element= line and moving driver.findElement to the inside of moveToElement().
Actions hoverover = new Actions(driver);
hoverover.moveToElement(driver.findElement(By.id("tab")))
.moveToElement(driver.findElement(By.id("menu"))).click().build().perform();
You could also try throwing in a WebDriverWait between hovering over tab and menu.
hoverover.moveToElement(driver.findElement(By.id("tab"))).build().perform();
new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.id("menu")));
hoverover.moveToElement(driver.findElement(By.id("menu"))).click().build().perform();
Related
I am using selenium 3.9.1 and java to automate testing of a web application. The web application has some dynamic content based on pressing of a button for example. The page refreshes whenever this button is clicked. A java script runs on button click and updates the DOM I think. At this time, when I try to access the button (which is visible on the page), I get a staleElementReferenceException.
Does Selenium automatically reload the DOM once it is changed? I am relatively new to selenium. I have researched into this and I have tried to refresh the page using driver.navigate().Refresh() to try to see whether this will solve the problem. It does not solve the issue.
Any pointers will be deeply appreciated.
Since the page has been refreshed, the button reference you have is to the button on the old page that no longer exists.
I'd say you need to get a new reference to the button on the refreshed page (eg call FindElementById).
If the page is refreshed all the items in the DOM are now stale. What this means is that all items found before the button press will have to be found again. Any attempts to use those items will more than likely be treated with a stale element exception.
However, if the button click mearilly affects items on the page without having to ask the webserver to give you a new page you could interact with the old items.
You could do something like this:
public void SaveAndAgainClick() throws Exception{
try{
clicksaveButton(); //method to click save button
WebElement someValue = driver.findElement(By.xpath("(//input[#name='someValue'])[1]"));
someValue.click();
}catch (StaleElementException e){
WebElement someValue = driver.findElement(By.xpath("(//input[#name='someValue'])[1]");
someValue.click();
}
}
If findElement gets staleElementError while looking for (//input[#name='someValue'])[1] then it will again try one more time in the catch block and most certainly find the element and clicks on it. Your test will pass if you follow this approach.
Here are the answers to your questions :
A java script runs on button click and updates the DOM I think : If you inspect the HTML of the element through Development Tools / Inspect Element the element attributes will reveal it all.
Consider the following HTML :
<input value="Click me" onclick="alert('Click!')" type="button">
In the given HTML as per the onclick attribute of this element, if you invoke click() method on the WebElement, an alert would be generated. Similarly the onclick attribute may invoke a JavaScript or Ajax which may bring-in/phase-out new/old elements from the HTML DOM
At this time, when I try to access the button I get a staleElementReferenceException : In this case you should induce WebDriverWait for the WebElement to be interactive before attempting to interact with the element. Else you may face either of the following exceptions :
StaleElementReferenceException
WebDriverException
ElementNotInteractableException
InvalidElementStateException
Does Selenium automatically reload the DOM once it is changed? Short answer, Yes it does.
Refresh the page using driver.navigate().refresh() : No invoking driver.navigate().refresh() wouldn't be a optimum solution as it may not invoke the intended JavaScript or Ajax properly. Hence the intended WebElement may not be interactive in a optimum way.
Good day everyone,
I need your help in this method. I have a web page that will have a loading screen UI when the page loads, and I'm waiting for it to finish before clicking a button.
Here is my code:
#Step("Go to Audit Inquiry Screen")
public void launchAuditInquiry(){
WebDriver webDriver = Driver.webDriver;
WebDriverWait wait = new WebDriverWait(webDriver, 10);
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.className("loading-container")));
WebElement auditInquiryBtn = webDriver.findElement(By.linkText("Audit Inquiry"));
auditInquiryBtn.click();
}
My issue is sometimes, this code works fine. It will wait for the loading ui div to be invisible before clicking the button. But sometimes it will produce this error:
Error Message: org.openqa.selenium.WebDriverException: unknown error: Element <a class="module-item" href="/audit/inquiry">...</a> is not clickable at point (822, 436). Other element would receive the click: <div class="loading-container" style="display: flex; opacity: 0.899842;">...</div>
I tried adding another explicit wait before clicking the button to be sure, like this:
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.className("loading-container")));
WebElement auditInquiryBtn = webDriver.findElement(By.linkText("Audit Inquiry"));
wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Audit Inquiry")));
auditInquiryBtn.click();
But it will sometime produce the same error above, and sometimes it will work fine.
I'm just confused on how to remediate the issue.
Thank you guys for the comments, especially this: Selenium Web Driver & Java. Element is not clickable at point (36, 72). Other element would receive the click
It was helpful, but some items there, I have already tried, but did not work as well. The part that I did check was one item there and also a comment here also which is to force a click:
new Actions(driver).moveToElement(auditInquiryBtn).click().perform();
But I'm having second thoughts on this because, a scenario may happen that when the loading container div is still overlaying the page, then I forced clicked the submit button, it will also produce another loading container div, and I'm not sure what will happen if there are two loading container div present.
Now, my solution on this is to adjust the sleep timer of the wait function:
WebDriverWait wait = new WebDriverWait(webDriver, 10, 2500L);
It now works because it gives the loader div time to generate before the first check of wait. 500 ms was a bit fast for the loader to render. I'm still testing this but if it didn't work, I might do the solution above.
Thanks again.
First thing to try is remove the invisibilityOfElementLocated wait and just use elementToBeClickable. I've never really trusted what Selenium considered "visible" and "invisible".
I've had issues in the past where the element to click on was completely off screen, so Selenium automatically scrolled until it was considered in the viewport. But because of a floating footer, it didn't scroll enough and was still behind the footer so could not be clicked on. It was still considered "visible" because it was in the viewport.
But, if you're sure, you can try forcing a click at a coordinate instead of an element.
new Actions(driver).moveToElement(auditInquiryBtn).click().perform();
I am unable to click on Website hyperlink, the click goes to Recently used pages.
Tried with CSS locator of Website icon [which works in the lower environment as it doesn't have Recently used pages] reference in it.
Tried with XPath Locator[including custom XPath], still, the click goes to another item.
Tried name locator.
Used Actions class for clicking.
Allowed the page to load completely by using sleep and WebDriver wait.
Located the element and send Enter keys, still Recently used pages is clicked.
Tried to click it using coordinates.
Thought of ChromeDriver issue but the issue persists in Firefox too.
Tried below XPath:
html/body/div/div[2]/div[2]/div[1]/a/div
//div[2]/div/a/div
Code snippet:
WebElement elementToClick = driver.findElement(By.cssSelector(".icon.siteadmin"));
elementToClick.click();
WebElement elementToClick = driver.findElement(By.cssSelector(".icon.siteadmin"));
(JavascriptExecutor)driver).executeScript("window.scrollTo(0,"+elementToClick.getLocation().x+")");
elementToClick.click();
WebElement elementToClick = driver.findElement(By.cssSelector(".icon.siteadmin"));
Actions actions = new Actions(driver);
actions.moveToElement(elementToClick);
actions.click().perform();
Actions builder = new Actions(driver);
builder.moveToElement(elementToClick, 40, 207).click().build().perform();
Result: It clicks on Recently Used Pages, and it yields a result of Recently used pages instead of Website.
UI Reference
Development Code Snippet
Hope It Helps you:
.//div[#id='box_2']/a/div[#class='icon siteadmin']/div[1]
Try the following:
driver.findElement(By.XPath(“//a[contains(#title, ‘Websites’)]”)).click()
If this doesn’t work use the above XPath in combination with one of the moves to element paths above and then use click.
I am clicking on the text box displayed on first page
WebElement txtBox = driver.findElement(By.xpath("---xpath---"));
txtBox.click();
Then after some block of execution I am getting the same textbox in new page on same window.
Here also I want to click on the text box.
I used JavascriptExecutor to do this scripting.
((JavascriptExecutor)driver).executeScript("arguments[0].click();", txtBox );
But while running the script I am getting an error message saying:
org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
You need to execute driver.findElement() every time you reload the page.
This method returns WebElement which is integral part of current page. If you refresh browser or navigate to some other URL or even if element is deleted and attached again by some javascript on same page, previously found element cannot be used anymore.
Here you have official explanation of this exception: http://www.seleniumhq.org/exceptions/stale_element_reference.jsp
Stale Element exception comes after you want to interact with an element loaded previously. If you get webelement and then reload the page it gives this exception because it is not in a newly created page. It is better to click the web element without assigning it to a variable like:
driver.findElement(By.xpath("---xpath---")).click();
I have a problem that is occuring some times.
The page is not showing the scroll, so when I need to find/click an element that is not shown in the screen, I get an exception:
(org.openqa.selenium.ElementNotVisibleException: element not visible
Refreshing the page works, but I would like to know if there is other solutions for this issue.
You can simulate scroll using moveToElement from Actions class
// Java syntax, but similar to other languages
Actions actions = new Actions(driver);
WebElement elementToMoveTo = driver.findElement(...);
actions.moveToElement(elementToMoveTo).perform();