StaleElementReferenceException when trying to click an element - java

I'm implementing a Selenium test using Java. But, my tests fail due to a StaleElementReferenceException.I am doing the following
driver.get(URL);
List<WebElement> Anchors = driver.findElements(By.xpath("//div[not(contains(#style,'display:none'))]/a"));
//same URL again
driver.get(URL);
Anchors.get(0).click();
When I try to click any element from the Anchors list I get an error.

Every time the DOM is changing or refreshing, even if you still in the same page, the driver "losses" the WebElements it previously located and you get StaleElementReferenceException. If you really need to use driver.get(URL); again before the click you need to relocate the list.

Related

Selenium Error : org.openqa.selenium.InvalidElementStateException: invalid element state

I am getting invalid element state when I try to clear element after click.
Following are operations I am doing on element:
inputField.click();
inputField.clear();
inputField.sendKeys("name");
The first step click is working fine, but clear is giving exception:
org.openqa.selenium.InvalidElementStateException: invalid element state
There is another test case, which calls the method which has above three steps and it works fine.What can be potential issue?
InvalidElementStateException
InvalidElementStateException implies that a WebElement is in a certain state when actions cannot be performed with it. One of the most frequently encountered examples would include an element being obscured by another when clicking, or perhaps not being visible on the HTML DOM.
This usecase
As you are trying to click(), clear() and sendKeys() within the WebElement ideally you need to induce WebDriverWait for the elementToBeClickable() and you can use the following solution:
WebElement inputField = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//elementXpath")));
inputField.click();
inputField.clear();
inputField.sendKeys("name");

Selenium/Java - is it possible to verify that a driver.switchTo().frame(element) was successful?

I have this code:
WebElement iframeElement = driver.findElement(By.xpath(xpIframe));
driver.switchTo().frame(iframeElement);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpLucka)));
driver.findElement(xpLucka).click(); //this click fails
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpSvara))); //TimeoutException
driver.findElement(xpSvar).click();
driver.findElement(xpSvara).click();
Frequently it fails on the line with the comment //TimeoutException. When I look at the state of the web page in the browser that is left open it is clear that the click on the line before it has failed. This is confusing. The element clearly is there, I find it without problems in the web inspector and the wait.until on the previous line obviously succeeds.
The next thing I want to make sure doesn't fail is the switchTo() statement. How can I verify a switchTo-call?
Note that is also succeeds frequently. I just ran this in a loop 9 times, it failed 5 times "but" succeeded 4 times.
Any other suggestions why this might happen are of course very welcome.
To click() on an element within a <iframe> so you have to:
Induce WebDriverWait for the desired frameToBeAvailableAndSwitchToIt.
Induce WebDriverWait for the desired elementToBeClickable.
You can use the following Locator Strategies:
new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("xpIframe")));
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("xpLucka"))).click();
Reference
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 faced some difficulties within my automation testing that WebDriverWait is not always working. As you may already know that Thread.sleep(3000); is not a recommended approach to use when it comes to automation testing, however sometimes you must use it. So for the testing purposes i would intentionally use:
Thread.sleep(3000); --> add some time, to make sure it switched to iframe
WebElement iframeElement = driver.findElement(By.xpath(xpIframe));
driver.switchTo().frame(iframeElement);
Thread.sleep(3000);
driver.findElement(xpLucka).click(); --> see if it will click on element
Thread.sleep(3000);
driver.findElement(xpSvar).click();
Thread.sleep(3000);
driver.findElement(xpSvara).click(); --> same for all other elements

Selenium cannot target div in iframe only on Chrome

I have a div with a class attribute with the value textLayer. I'm trying to get that div.
Here is my code:
WebElement jsiFrame = driver.findElement(By.tagName("iframe"));
driver.switchTo().frame(jsiFrame);
WebElement docViewerElement = driver.find(By.classname("textLayer")
(note: this isn't exactly the code but it's more or less the functions I call)
I also have a timeout where I wait 5 seconds while requesting each element so it's not a matter of the element not existing when I query it). Selenium fails to find it, even though it's very plainly there. What's more, it only fails on Chrome, Firefox finds it without any problems.
Try dynamic xpath with explicit wait.
You can achieve it in this way
driver.switchTo().frame(0)
WebElement docViewerElement = driver.find(By.classname("textLayer")

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')]

How to Manipulate Search Bar That's Not Present in HTML Source Using Selenium?

I'm trying to use Selenium (Java) to automate some searches.
When I go to the page and click Inspect Element on the search bar, I see that it has the id searchBox and name q, both of which are potentially useful. Nevertheless, these properties are nowhere to be found in the HTML when I go to View Source.
When I try to use
WebElement search = driver.findElement(By.id("searchBox"));
or
WebElement search = driver.findElement(By.name("q"));
both come back as unable to be found.
How do I proceed with populating the search field then hitting submit (the submit button also is missing in the source page) if I can't find either of these elements?
EDIT:
As requested, here's a more detailed picture of what's wrong:
The URL of the page accessed by WebDriver is http://www.ycharts.com using the line
driver.get("http://www.ycharts.com/login");
If you go to this page with your actual web browser, right click on the search bar and choose Inspect Element, you'll see that its ID is "searchBox" and its name is "q". However, if you go to view the same page's source, you'll see that there's no such element in the HTML. Clearly, this is why WebDriver can't find it.
driver was initiated as follows:
WebDriver driver = new HtmlUnitDriver();
When I try something like
WebElement search = driver.findElement(By.id("searchBox"));`
The exception returned is:
Exception in thread "main" org.openqa.selenium.NoSuchElementException: Unable to locate element with ID: searchBox
So, back to the original question: clearly, the element is there, but it's not in the HTML – how do you interact with it?
The problem is being caused by the fact that the search box is added to the html post page load by javascript.
The HTML returned by http://ycharts.com/ does not contain the searchbox, therefore when Selenium thinks the page has finished loading (i.e DOM ready state), there is no search box.
In order to interact with the search box, you need to tell Selenium to wait until the box appears in the DOM.
The easiest way to achieve this is with WebDriverWait;
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id<locator>));

Categories