Selenium can't find dynamic web element - java

I'm attempting to write a Selenium test script in Java for a web application. The application has a button which dynamically adds a form field onto the screen. The problem I've been having is that I can't seem to get the Selenium Web Driver to recognize the new form element element. I first tried initializing the elements in the constructor using #FindBy like this:
#FindBy(how = How.CSS, using = "#WIN_0_536870929") private WebElement form;
Then, I tried using an explicit wait to make sure the element was loaded (on the button which adds the form to the DOM):
WebDriverWait webDriverWait = new WebDriverWait(this.getDriver(), 20);
WebElement formButton = webDriverWait.until(ExpectedConditions.elementToBeClickable(By.id("WIN_0_536870929")));
formButton.click();
But either way, the dynamic form elements fail to load. There error I get is as follows:
org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"id","selector":"#WIN_0_817000996"}
Even more confusing, when I step through the test in the debugger, the form field is fully loaded into the DOM before the test tries to access it.
Does anyone have any idea what could be causing this to happen?

So it turns out I was trying to access an element that was in an iframe. Big thanks to Vivek Singh for suggesting I look into that. I was able to get into the iframe using this line of code:
this.driver.switchTo().frame(this.driver.findElement(By.cssSelector("#WIN_0_817000899 iframe")));

You have to define your WebElement only if you are expecting for its visibility:
public static WebElement waitForVisibleElement( WebDriver driver, By locator, int timeOutInSeconds ) {
WebDriverWait wdw = new WebDriverWait( driver, timeOutInSeconds );
try {
return wdw.until( ExpectedConditions.visibilityOfElementLocated(locator) );
} catch ( NoSuchElementException | TimeoutException | NullPointerException ex ) {
return null;
}
}

Related

Selenium Web Driver with Java

How to identify a "search" in Kayak.co.in/flights/One-way page in selenium web driver.
driver = new FirefoxDriver();
driver.get("https://www.kayak.co.in/");
driver.manage().window().maximize();
driver.findElement(By.xpath("//a[#href='/flights']")).click();
driver.findElement(By.xpath("//label[#title = 'One-way']")).click();
driver.findElement(By.xpath("//*[contains(#id='-submit')]")).click();
driver.quit();
Getting the following exception after executing the above code:
Exception in thread "main" org.openqa.selenium.NoSuchElementException:
Unable to locate element: {"method":"xpath","selector":"//*[contains(#id='-
submit')]"}
There are multiple buttons with this xpath. You should specify more your xpath to obtain an unique button. Try with this one .//div[contains(#class,'Flights-Search-StyleJamFlightSearchForm')]/.//div[contains(#class,'centre')]/button[#title='Search']
You should declare a WebElement while calling an element to precisely targeting it and using moveToElement command instead of simply calling FindElement.By.xxxxx ex:
//*** Calling a WebElement and using moveToElement command***//
WebElement (anyElementname) = browser.findElement(By.partialLinkText("xxxxxxxxxxx"));
action.moveToElement(anyElementname).perform();
//*** Waiting for 8 seconds***//
Thread.sleep(8000, 80000);
You can use 'waits' for providing page load time and interacting between elements
I am converting first xpath (flights) command for you. You can do the rest in the same way:
WebElement flights = driver.findElement(By.xpath("//a[#href='/flights']")).click();
action.moveToElement(flights).perform();
Dont forget to import relevant libraries like for action, you have to import:
import org.openqa.selenium.interactions.Actions;
Let me know if it works for you or not. Cheers!

Explicit wait in selenium webdriver

I'm using web driver wait as explicit wait in selenium web driver. But It's not consistent it seems. before mouse over operations, links It's throwing unable to locate element error. Please see the below method and suggest where am I going wrong.
public WebElement waitForElement(String xPathExpression) {
WebDriverWait wait = new WebDriverWait(driver,30);
WebElement element = wait.until(ExpectedConditions.visibilityOf(driver.findElement(By.xpath(xPathExpression))));
return element;
}
Just a guess, but I might have seen similar behavior on very dynamic pages. I.e the element on the page changes while being evalued.
I'm able to workaround these kind of problems by using FluentWait#ignoring
WebDriverWait wait = new WebDriverWait(driver,30)
.ignoring(NoSuchElementException.class);

Going through Chrome://settings by Selenium

I am using Java and Selenium to write a test, I use the code below to get into Chrome:setting
driverChrome.manage().window().maximize();
driverChrome.get("chrome://settings");
But when the page is open I can not find any of its web Elements, for example when I try to find "show advanced setting...." by this code
driverChrome.findElement(By.xpath("//a[#id='advanced-settings-expander']")).click();
it throws an error saying that "no such element: Unable to locate element"
I tried to located other elements, but they all failed. I saw this post here but it did not help.
Find the code below:
driverChrome.manage().window().maximize();
driverChrome.get("chrome://settings");
Thread.sleep(5000);
WebElement w = driverChrome.findElement(By
.xpath("//iframe[#name='settings']"));
driverChrome = driverChrome.switchTo().frame(w);
Thread.sleep(1000);
while (true) {
try {
WebElement we = w.findElement(By
.xpath("//a[text()='Show advanced settings...']"));
if (we.isDisplayed()) {
we.click();
Thread.sleep(1000);
break;
}
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println("=========================");
}
}
I haven't tested this but I took your code snippet and cleaned it up a bit. Try this and see if it works. This should be pretty close.
Once you switch to the IFRAME context, you don't need to reference the IFRAME as you did with w.findElement().
In general, Thread.sleep() is not a good practice. You should prefer to use WebDriverWait with ExpectedConditions. Check the docs for all the different things you can wait for using ExpectedConditions. I used .elementToBeClickable() in my code below. This is perfect since you want to click an element. The .until() returns the element waited for so you can just append .click() on the end of the statement... or you can store the element in a WebElement variable and use it elsewhere.
driverChrome.manage().window().maximize();
driverChrome.get("chrome://settings");
WebElement w = driverChrome.findElement(By.xpath("//iframe[#name='settings']"));
driverChrome = driverChrome.switchTo().frame(w);
WebDriverWait wait = new WebDriverWait(driverChrome, 10);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[text()='Show advanced settings...']"))).click();
// alternative example... store returned element and then click on a separate line... or use the variable elsewhere, etc.
// WebElement link = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[text()='Show advanced settings...']")));
// link.click();
You will need to identify Shadow roots to interact with a lot of Chromes native pages including the Settings page.
See this Thread on how to work with them properly:
How to interact with the elements within #shadow-root (open) while Clearing Browsing Data of Chrome Browser using cssSelector

Selenium WebDriver - Getting NoSuchElementException error even element is present

I am trying to click on drop down box in my application and Xpath is : //*[#id='sel2O5_chzn']/a
But when I try to click on it, am getting NoSuchElementException
Even element is present in application. Tried in IE,Chrome and Firefox still facing same issue
driver.findElement(By.xpath("//*[#id='sel2T1_chzn']/a")).click();
Tried below approch as well but no luck. Getting same NoSuchElementException
Select sel = new Select(driver.findElement(By.xpath("//*[#id='sel2T1_chzn']")));
sel.selectByIndex(1);
Please help me in resolving this issue
Use explicit wait with that it enables you to wait for the element to be located by WebDriver and here is a list of ExpectedConditions you can use
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[#id='sel2T1_chzn']")));
myDynamicElement.click();

Same scenario - StaleElementReferenceException with Java, but Watir is fine

Scenario: Open website, obtain a reference to Webelement "About" , click About , navigate back and use the variable reference again -- Results in StaleElementReference Exception. This happens only with Selenium Java, however when using Watir, it works fine. Both the code snippets are posted below. Anyone got a damn clue what is going on ?
# Below Java code produces StaleElementReferenceException
public class StaleElementException {
public static void main(String[] args) {
ChromeDriver driver = new ChromeDriver();
driver.get("http://seleniumframework.com");
WebElement about = driver.findElementByLinkText("ABOUT");
System.out.println(about.getText());
about.click();
driver.navigate().back();
System.out.println(about.getText());
}
}
#Below Ruby Watir Code works fine
require 'watir-webdriver'
#browser = Watir::Browser.new :chrome
#browser.goto "http://seleniumframework.com"
about = #browser.link(text: 'ABOUT')
puts about.text
about.click
#browser.back
puts about.text
Watir automatically does another find element call after the refresh, which webdriver does not do, so you need to do what Saifur suggested.
I am not sure how Watir works here. But if you find an element click on it it navigates you to a different page and the DOM refreshes. You therefore going back with driver.navigate().back(); and try to use same about element to perform your action which is not valid anymore. The DOM refreshed means the reference to the element is lost and that's not a valid element anymore. What you should be doing is finding the same element again on the fly and perform your action. The complete code should look like the following:
public class StaleElementException {
public static void main(String[] args) {
ChromeDriver driver = new ChromeDriver();
driver.get("http://seleniumframework.com");
WebElement about = driver.findElementByLinkText("ABOUT");
System.out.println(about.getText());
about.click();
driver.navigate().back();
System.out.println(driver.findElementByLinkText("ABOUT").getText());
}
}
Note: The change in last line

Categories