I am trying to use the following selenium to look for a child in a parent element and this works great
ExpectedConditions.presenceOfNestedElementLocatedBy(parent, By.xpath(xpath))
Now I want a method that returns ALL the elements that match the xPath, however, to my surprise the signature requires a By instead of the WebElement I would expect.
How can I convert my WebElement to a by to get the other elements?
Here's an example for you to get all the child Elements by Passing BY:
public class Demo {
static WebDriver driver;
public static void main(String[] args)
{
System.setProperty("webdriver.chrome.driver", "c:\\eclipse\\selenium\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("http://google.com");
By x = By.xpath("//div"); //or your By.xpath(xpath)
List<WebElement> allItem = getChildElements(x);
System.out.println(allItem.size());
for(WebElement item : allItem){
System.out.println(item.getText());
}
}
public static List<WebElement> getChildElements(By x){
List<WebElement> allElems = driver.findElements(x);
return allElems;
}
}
Try doing class casting and proceed with. The code will look something similar to this.
WebElement parent = driver.findElement(By.xpath(""));
WebElement child = driver.findElement(By.xpath(""));
new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfNestedElementLocatedBy(parent, (By)child));
Hope this helps you. Thanks.
Related
I need a little help. I'm trying to run an automated test on the website http://zara.com and i want to select the language from the language dropdown.
This is the HTML code from Zara. https://prntscr.com/g6hdiv
This is the code i've tried with Selenium 2.53 in IntelliJ
public class RegistrationTest {
WebDriver driver;
#Before
public void setUp(){
driver = new FirefoxDriver();
driver.get("http://zara.com");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
#After
public void tearDown(){
driver.quit();
}
#Test
public void test(){
WebElement languageDropdown = driver.findElement(By.id("language"));
Select selectLanguage = new Select(languageDropdown);
selectLanguage.selectByValue("en");
}
}
I always receive the error below even if I've tried in different setups but it didn't work.
org.openqa.selenium.ElementNotVisibleException: The element is not currently visible and so may not be interacted with
Could you please tell me what am I doing wrong?
Appreciate the help.
The element is not currently visible and so may not be interacted with
You need to scroll the page, so that the element is in the current viewport. Something like this:
WebElement languageDropdown = driver.findElement(By.id("language"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", languageDropdown);
Select selectLanguage = new Select(languageDropdown);
selectLanguage.selectByValue("en");
I am Having a Lot of WebElements
For Example I Declared a WebElement a
#FindBy(id="BtnLogin")
private WebElement btnLogin;
In the Same Manner I created "N" number of WebElements
Every time I Cant use "driver.findElement()" function So I wrote a function
public static void WebElementClick(WebElement we)
{
we.click();
}
When Ever the Control is Going to The Line we.click() in the WebElementclick Function it is Showing NullPointerException as a Result My Purpose is Failing
I am Not Getting What to Do,Some One Please Help Me on this :)
Your WebElementClick should receive the selector and it should: find element -> click, you can get an example from the above link.
In your case you it seems that you are not using wait and the WebElementClick it tries to click on the string.
Using find will return an object that will make click available.
The method should contain something like: driver.findElement(By.xpath("your_selector"));
Ant then use click on what this method returns.You can use also css if you want to.
public class testJava{
#Test
public void testMethod() throws InterruptedException {
WebDriver driver = new FirefoxDriver();
pageClass pageClass = PageFactory.initElements(driver, pageClass.class);
driver.get("http://www.facebook.com");
Thread.sleep(5000);
pageClass.clickLoginBtn();
}}
public class pageClass {
#FindBy(id = "loginbutton")
private WebElement loginBtn;
WebDriver driver;
public pageClass(WebDriver driver) {
this.driver = driver;
}
public void clickLoginBtn()
{
click(loginBtn);
}
public void click(WebElement we)
{
we.click();
}}
Its best practice to use the page class & test class..Try this it will help you i guess.
You are suppose to use driver to find & click the element.
I think that driver may try to click element before it's presented. Good practice before clicking WebElement is to wait for WebElement being clickable. I would try:
public static void WebElementClick(WebElement we)
{
wait.forElementClickable(we);
we.click();
}
I am new to the selenium framework and writing a method for the presence of element. Below is the method which I wrote:
public class WebUtlities {
WebDriver driver;
public void waitforanelement(WebElement element)
{
WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.presenceOfElementLocated((By) element));
}
When I call this method for an element, I see the below error:
java.lang.ClassCastException: com.sun.proxy.$Proxy6 cannot be cast to org.openqa.selenium.By
at Uilities.WebUtlities.waitforanelement(WebUtlities.java:16)
at TestScripts.Testcases.Selfpay(Testcases.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Please correct me how to make it work for the element to wait
Try with this
public class WebUtlities {
WebDriver driver;
public void waitforanelement(WebElement element)
{
driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("xpath of that element"))); //you can use any other By like id, cssselector, name, linktext etc
}
Hope this helps
use the below code:
public void waitforanelement(By element)
{
WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.presenceOfElementLocated(element));
}
when u call the method, do like below:
By css = By.cssSelector("ur selector");
waitforanelement(css);
hope this will help u.
The problem lies with this line:
wait.until(ExpectedConditions.presenceOfElementLocated((By) element));
Firstly, the presenceOfElementLocated method is used to locate an element on the page, rather than to check that a previously found element is present on the page - as such you should change the argument for your waitforanelement method to accept a By locator instead of a WebElement like so:
public void waitforanelement(By by)
You should then subsequently change the arguments passed to the presenceOfElementLocated method like so:
wait.until(ExpectedConditions.presenceOfElementLocated(by));
The Javadoc for the By class lists the locators you can use.
The problem as you can see from the error is that
new WebDriverWait(driver,20);
wait.until(ExpectedConditions.presenceOfElementLocated((By) element));
returns an WebElement instance which should be assigned to an WebElement. So It can not cast a WebElement to nothing.
Follow the following list for complete list of methods of ExpectedConditions Class.
https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html
Try the following,
public WebElement waitforanelement(WebElement element)
{
WebDriverWait wait= new WebDriverWait(driver,20);
WebElement Element=wait.until(ExpectedConditions.presenceOfElementLocated((By) element));
return Element1;
}
I am trying to test this website by using JUnit and Selenium:
https://www.oanda.com/currency/converter/
I tried to select Unit from “Currency I Have” as well as "Currency I Want". Then I found out that the xpaths are the same. Only the "Currency I Have" codes can be run successfully. "Currency I want" always fail.
The Xpath is driver.findElement(By.xpath("//span[text() = 'GBP']")).click();
Could someone help on this? Thanks.
Code1:
public class Currency_I_Have {
WebDriver driver = new FirefoxDriver();
#Before
public void setUp() throws Exception {
driver.manage().window().maximize();
driver.get("https://www.oanda.com/currency/converter/");
}
#Test
public void test() {
driver.findElement(By.id("quote_currency_input")).click();
driver.findElement(By.xpath("//span[text() = 'GBP']")).click();
WebElement Amount = driver.findElement(By.id("quote_amount_input"));
Amount.clear();
Amount.sendKeys("100");
}
}
Code2:
public class Currency_I_Want {
WebDriver driver = new FirefoxDriver();
#Before
public void setUp() throws Exception {
driver.manage().window().maximize();
driver.get("https://www.oanda.com/currency/converter/");
}
#Test
public void test() {
driver.findElement(By.id("base_currency_input")).click();
driver.findElement(By.xpath("//span[text() = 'GBP']")).click();
WebElement Amount = driver.findElement(By.id("base_amount_input"));
Amount.clear();
Amount.sendKeys("200");
}
}
I count 4 elements on that page matching that XPath. (Although on further inspection it looks like you could go with either in each pair, since they are dupes.) What you need to do is find unique parent elements for the specific span you want. For example the two unique matching elements could also be referenced more uniquely via:
//div[#id='quote_currency_selector']//span[text()='GBP']
(I think this is the one you want)
The other one could be referenced more uniquely via:
//div[#id='base_currency_selector']//span[text()='GBP']
I got the "quote currency selector" and "base currency selector" bits from "ancestor" DIVs that were "higher up" the XML tree from the "GBP" entries in the drop downs.
I created a POM for 'Create project' page
public static class addProjInfo_container
{
public static WebElement ProjName_txt(WebDriver driver)
{
element=driver.findElement(By.xpath("//label[text()='Project Name']/following-sibling::input"));
return element;
}
// and so on for every text field for adding project...
And I created a TestUtility class with method for waitForElement as show below
public final class TestUtility {
private static WebDriver driver;
public static void waitforElementXpath(final WebDriver driver,final int waitTime,final String xp)
{
WebDriverWait wait =new WebDriverWait(driver, waitTime);
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xp)));
}
}
Now, in Test script I want to avoid using Thread.sleep() to wait for webelement to be ready to start performing actions.
so, I use
TestUtility.waitforElementXpath(driver,10,CreateProject_Page.addProjInfo_container.projName_txt(driver));
But,it displays error as
The method waitforElementXpath(WebDriver, int, String) in the type TestUtility is not applicable for the arguments (WebDriver, int, WebElement)
Kindly, let me know how to handle the issue.
Basically your want to reverse the By to get its string and you are using xpath
so change to this which return the String instead of WebElement
public static class addProjInfo_container {
public static String projName_txt(WebDriver driver) {
By by = By.xpath("//label[text()='Project Name']/following-sibling::input");
driver.findElement(by);
return getSelectorAsString(by);
}
public static String getSelectorAsString(By by) {
String str = by.toString();
return str.substring(str.indexOf(" ") , str.length());
}
// and so on for every text field for adding project...
}
hope this could help
This is really a convoluted way of trying to accomplish this task. Your ProjName_txt() method already has found the element because that's what it returns so you don't need to wait for it to appear by using waitforElementXpath(). I would recommend that you read some articles on OOP and classes before you write too much more code.
The best way is:
String name = driver.findElementByClassName("classnamesample").getText() ;
Just add .getText() in the last of xpath and receive this as String.