For Example,
WebElement parentEle = driver.findElement(By.id("xyz"));
WebElement childEle = parentEle.findElement(By.id("abc"));
childEle.click();
In the above example, We are finding childEle with in parentEle.
How can we achieve this using #FindBy annotation (in conjunction with PageFactory)
First of all why do you need to find child from a parent if the child has a UNIQUE id? The main purpose of id is to provide the flexibility of finding the element with a unique selector.
In case if the child element is really nested to other, find that with xpath. I often use that.
#FindBy(how = How.XPATH, using = "//something/something")
private WebElement TestElement;
Or with ID
#FindBy(how = How.ID, using = "abc")
private WebElement TestElement;
This can be achieved in couple of steps:
//identify parent element with #FindBy annotation
1) #FindBy(className="locator")
List<WebElement> parent;
//loop through each parent to get child(<li> in your case) of each parent
2) for(WebElement list_items:Parent){
list_items.findElement(By.xpath("child locator"));
I had used this approach and was able to achieve the desired results. Hope this explains your query as well.
#FindBy (id = "abc")
private WebElement TestElement;
In your page factory try this and call that method from your test method.
public WebElement Child_Of_ParentElement(WebElement TestElement, String Child_Id)
{
return TestElement.findElement(By.id(Child Id));
}
As stated in other answers I would use xpath although you would have to rewrite the root path for each child element, unless you make a string constant or something but that could start to get messy.
// Child 1
#FindBy(xPath = "//[#id='xyz']/[#id='abc']";
private WebElement childAbcOfParentXyz;
// Child 2
#FindBy(xPath = "//[#id='xyz']/[#id='def']";
private WebElement childDefOfParentXyz;
Related
Currently I am using #FindBy annotation for an element as below
#FindBy(xpath = "//a[#class='fNiv' and contains(text(), 'Home')]")
public static WebElement Tab_Home;
But when I try using Boolean I am getting an error "Change to getSize()" and my Boolean syntax is
//AllGeneralTabs is the class name where I have stored my elements
Boolean home=AllGeneralTabs.Tab_Home.size()>0;
I want something to work in such a way when I define my Element as
public static final By Tab_Home=By.xpath("//a[#class='fNiv' and contains(text(), 'Home')]");
then the Boolean will work perfectly for the below syntax
Boolean home=driver.findElements(AllGeneralTabs.Tab_Home).size()>0;
It returns true/False and works as expected but this is not happening for #FindBy annotation. As I defined all my elements using #FindBy now and I cannot go back and change it to final statement, I don't have time.
Try below solutions.
#FindAll(#FindBy(how = How.XPATH, using = "//a[#class='fNiv' and contains(text(), 'Home')]"))
List<WebElement> allElements;
OR
#FindBys(#FindBy(xpath="//a[#class='fNiv' and contains(text(), 'Home')]")))
List<WebElement> allElements;
Let me know if it works for you.
You are mixing between WebElement size witch return Dimension and List size witch return int. You didn't say what exactly you are trying to do, but it seems you are looking for
#FindBy(xpath = "//a[#class='fNiv' and contains(text(), 'Home')]")
public static List<WebElement> Tab_Home;
Hi I need to access to a Select Field component from the Material UI library. I'm using the traditional way but as expected is throwing an error because this library generates div elements instead of select.
Please any idea of how to select elements with this component?
WebSite Url: http://www.material-ui.com/#/components/select-field
Error: "org.openqa.selenium.support.ui.UnexpectedTagNameException: Element should have been "select" but was "div".
The code I used is the follow:
public class MaterialUITest {
private WebDriver driver;
By selectFieldLocator = By.xpath("//div[contains(#id,'undefined-undefined-Frequency')]/div[1]/div[2]");
#Before
public void setUp() throws Exception {
System.setProperty("webdriver.chrome.driver", "./src/test/resources/drivers/chromedriver.exe");
driver = new ChromeDriver();
driver.get("http://www.material-ui.com/#/components/select-field");
}
#After
public void tearDown() throws Exception {
}
#Test
public void test() {
WebElement selectField = driver.findElement(selectFieldLocator);
Select dropdown = new Select(selectField);
dropdown.selectByVisibleText("Weekly");
WebElement option = dropdown.getFirstSelectedOption();
System.out.println(option.getText());
}
}
As I understand problem that you're having is not related to material itself it's more related to custom implementation of select, i.e. this is not select, you should treat this 'select' as regular web element and handle it respectively in other words you need to click on it to expand and then perform another click on required element to select it.
Inspect element and copy full xpath.
Try with Full xpath it will work you need take the xpath of full tab because inner elements are not enabled because of parent elements.
I am writing the test code using java selenium web driver,
I want to search for "Honey rose varghese" and when the result is available, from this result I want to click the Filmography link available on the result page.
public class ByPartialLink {
public static void main(String[] args) throws InterruptedException {
System.setProperty("webdriver.chrome.driver",System.getProperty("user.dir")+"\\chromedriver\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.google.co.in");
WebElement searchbox = driver.findElement(By.id("lst-ib"));
searchbox.sendKeys("Honey rose varghese");
searchbox.submit();
Thread.sleep(3000);
List<WebElement> search = driver.findElements(By.partialLinkText("Filmography"));
System.out.println(search.size());
}
}
This worked for me and returned 1. I just searched for the full link text instead of partial. Using a Thread.sleep() isn't a best practice. Try the WebDriverWait below for better, more consistent results.
driver.get("http://www.google.co.in");
WebElement searchbox = driver.findElement(By.id("lst-ib"));
searchbox.sendKeys("Honey rose varghese");
searchbox.submit();
WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("resultStats")));
// Thread.sleep(3000);
List<WebElement> search = driver.findElements(By.linkText("Filmography"));
System.out.println(search.size());
EDIT 1: after feedback
If you want to click the first Filmography link, there are a couple ways to do this...
1) Maybe you want to count the number of links to make sure there's only one, etc. You could still use the code above but click the first element.
List<WebElement> search = driver.findElements(By.linkText("Filmography"));
search.get(0).click();
2) If you always want to click the first link or are confident that there will ever only be one link you can just use .findElement() to return only the first element and click it.
WebElement search = driver.findElement(By.linkText("Filmography"));
search.click();
or a one-liner...
driver.findElement(By.linkText("Filmography")).click();
Best practice in a case like this (where there might be none or more than one search result) would be to return the collection and make sure there is at least one.
List<WebElement> search = driver.findElements(By.linkText("Filmography"));
if (!search.isEmpty())
{
search.get(0).click();
}
I have tried to use Html Elements framework. Here are one of my blocks:
#Block(#FindBy(id = "test"))
public class FirstBlock extends HtmlElement {
#FindBy(id = "nameS")
private TextInput id;
#FindBy(id = "saveBt")
private Button add;
public void addNewClient(String idText) {
add.click();
id.sendKeys(idText);
}
}
I have initialized page factory like:
PageFactory.initElements(new HtmlElementDecorator(driver), this);
Now I want to wait after add.click(); until next element is present.
As I found out where is possibility to use AjaxElementLocatorFactory
But how can I make this using Html Elements framework?
HtmlElements use AjaxElementLocatorFactory by default, so you don't need any explicit waits in your code. It will try to find your id element until succeed and then executes sendKeys() on it. In case element wait timeout will be reached, it'll throw ElementNotFound exception.
I am working on selenium web driver using the language "Java" and want to access two elements of same classname. Actually, both the elements are error messages which are coming in small popup having the same class. But the problem is that every time it only picks the first element of the class which is coming. Please suggest which method I should use to get both the elements.
Also, I need to compare both the messages with the string that I have added. Here is the code I have tried:
public class mysignup {
public static WebDriver d;
public static void main(String []args)throws Exception{
d = new FirefoxDriver();
d.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
d.findElement(By.name("firstname")).sendKeys("qwertyuiokjhgfdsazxcvbnmkloiuytr");
d.findElement(By.name("firstname")).click();
d.findElement(By.name("lastname")).sendKeys("singh");
d.findElement(By.name("email_id")).sendKeys("abcgmail.com");
d.findElement(By.name("firstname")).click();
d.findElement(By.name("email_id")).click();
String bodyText = d.findElement(By.cssSelector(".popover-content")).getText();
While findElement returns you a single WebElement, findElements will return all elements that match given conditions.
In such a scenario I would suggest using findElements method. It will return you a list of all elements if found or an empty list. So you can try out with:
List<WebElement> lstEle = d.findElements(By.cssSelector(".popover-content"));
List<String> strLst = new ArrayList<String>();// list to contain all texts in each element
lst.forEach(new Consumer<WebElement>() { // foreach element add text to strLst
#Override
public void accept(WebElement t) {
strLst.add(t.getText());
}
});