Selenium webdriver: finding all elements with similar id - java

I have this xpath: //*[#id="someId::button"]
Pressing it shows a dropdown list of values.
Now, I know all the elements in the list have an id like this :
//*[#id="someId--popup::popupItemINDEX"]
, where INDEX is a number from 1 to whatever the number of options are.
I also know the value which I must click.
One question would be: since I will always know the id of the button which generates the dropdown, can I get all the elements in the dropdown with a reusable method? (I need to interact with more than one dropdown)
The way I thought about it is:
get the root of the initial ID, as in:
//*[#id="someId
then add the rest : --popup::popupItem. I also need to add the index and I thought I could use a try block (in order to get though the exceptions when I give a bigger than expected index) like this:
for(int index=1;index<someBiggerThanExpectedNumber;index++){
try{
WebElement aux= driver.findElement(By.xpath(builtString+index+"\"]"));
if(aux.getText().equals(myDesiredValue))
aux.click();
}catch(Exception e){}
}
Note that I am using the webdriver api and java.
I would like to know if this would work and if there is an easier way of doing this, given the initial information I have.
EDIT: The way I suggested works, but for an easier solution, the accepted answer should be seen

As a rule of thumb, try to select more elements by one query, if possible. Searching for many elements one-by-one will get seriously slow.
If I understand your needs well, a good way to do this would be using
driver.findElement(By.id("someId::button")).click();
driver.findElement(By.xpath("//*[contains(#id, 'someId--popup::popupItem') " +
"and text()='" + myDesiredValue + "']"))
.click();
For more information about XPath, see the spec. It's surprisingly a very good read if you can skip the crap!
That finds and clicks an element with text equal to you desired value which contains "someId--popup::popupItem" in its ID.
List<WebElement> list = driver.findElements(By.xpath("//*[contains(#id, 'someId--popup::popupItem')]"));
That finds all just all elements that contain "someId--popup::popupItem" in their ID. You can then traverse the list and look for your desired element.
Did you know you can call findElement() on a WebElement to search just it's children?
- driver.findElement(By.id("someId")).findElements(By.className("clickable"))
Without a peek on the underlying HTML, I guess I can't offer the best approach, but I have some in my head.

Have you tried using JavascriptExecutor?
If you are willing to write a little JavaScript then this would be straightforward than in java (I think)
All you will need to do is have some JavaScript crawl through the DOM subtree, and return a list of DOM elements matching your criteria. WebDriver will then happily marshall this as List<WebElement> in the java world.

The Safer Method to use here is
int size=driver.findElements(By.xpath("//*[#id='someId::button']")).size();
Start using Index Now
String builtString="//*[#id='someId::button'][";
for(int index=1;index<=size();index++)
{
try
{
WebElement aux= driver.findElement(By.xpath(builtString+index+"\"]"));
if(aux.getText().equals(myDesiredValue))
aux.click();
}
catch(Exception e){}
}
Please Let me know is the above funda is working or not.

Related

Trying to put a list of ids with a common phrase into an array/list in selenium java

I need to get the IDs present in the DOM that start with "starx-" into an array. After that hyphen, there is usually some combination of uppercase, lowercase, and digits - it depends upon the dropdown selected previously. But starx- is common to all ids, no matter what is selected in the previous dropdown (and there are a LOT of options so... no to creating a bunch of "if" statements based on the previous drop down)
To do so, I created this line here to match all of the id's in the DOM that start with starx-:
List<WebElement> allStarX = driver.findElements(By.cssSelector("[id^='starx-']"));
So it's good at finding them. A few print statements I threw in there show me that if there are 4 such IDs in the DOM, it will find them all. If there are 7, it will have 7 elements in that List. Unfortunately , this List doesn't contain the actual IDs. It contains:
[[ChromeDriver: chrome on WIN8_1 (f665490daee44e1039265763f67008cc)] -> css selector: [id^='starx-']]
for each id beginning with starx- that exists in the DOM. Ideally I'd get all the ID using the .getAttribute method, but that's for strings. For example, if I add it onto the end of this:
List<WebElement> allStarX = driver.findElements(By.cssSelector("[id^='starx-']")).getAttribute();
I have a type mismatch. And if I do this:
for (WebElement starx : allStarX)
{
starx.getAttribute("id");
System.out.println(starx);
}
It still prints out a bunch of this:
[[ChromeDriver: chrome on WIN8_1 (f665490daee44e1039265763f67008cc)] -> css selector: [id^='starx-']]
I kind of know why that last one doesn't work, but I don't understand why the first one doesn't.
Absolute xpaths don't seem to work because there are a lot of previous options add and remove things from the DOM.
Can anyone suggest something that might help?
As far as my understanding goes, you are trying to get the IDs which start with the text of 'starx-'. You have created a list of webelements (List<WebElement>) and while extracting the text, you are looping it by not extracting the attribute of the id, which is the issue.
You can handle it as mentioned below:
List<WebElement> allStarX = driver.findElements(By.cssSelector("[id^='starx-']"));
for (WebElement starx : allStarX)
{
System.out.println(starx.getAttribute("id"));
}
Hope this helps.

Jsoup eq selector returns no value

Trying to fetch data using Jsoup 1.10.3, seems like eq selector is not working correctly.
I tried the nth-child, but it seems like its not getting the second table (table:nth-child(2)).
Is my selector correct?
html > body > table:nth-child(2) > tbody > tr:nth-child(2) > td:nth-child(2)
in the example below, trying to extract the value 232323
Here is the try it sample
There are several issues that you may be struggling with. First, I don't think that you want to use the :nth-child(an+b) selector. Here is the explanation of that selector from the jsoup docs:
:nth-child(an+b) elements that have an+b-1 siblings before it in the document tree, for any positive integer or zero value of n, and has a parent element. For values of a and b greater than zero, this effectively divides the element's children into groups of a elements (the last group taking the remainder), and selecting the bth element of each group. For example, this allows the selectors to address every other row in a table, and could be used to alternate the color of paragraph text in a cycle of four. The a and b values must be integers (positive, negative, or zero). The index of the first child of an element is 1.
I guess you want to use the :table:nth-of-type(n) selector.
Second, you only select elements with your selector, but you want to get the visible content 232323, which is only one inner node of the element you select. So what is missing is the part where you get to the content. There are several ways of doing this. I again recommend that you read the docs. Especially the cookbook is very helpful for beginners. I guess you could use something like this:
String content = element.text();
Third, with CSS selector you really do to need to go through every hierarchy level of the DOM. Since tables always contain a tbody and tr and td elements, you may do something like this:
String content = document.select("table:nth-of-type(2) tr:nth-of-type(2) td:last-of-type").text();
Note, I do not have a java compiler at hand. Please use my code with care.

Retrieving a list of WebElements and Identifying them

Is there a way to Identify and assign WebElement Names to a list of WebElements? For example using the following convention:W
#FindBy(xpath="")
WebElement listFirstObject;
#FindBy(xpath="")
WebElement listSecondObject;
Forgive me if this is an elementary question, but it seems like it would be a pretty common scenario for any tester as many applications have lists of objects with common names. In my case I have a control list with well over 700 objects and it would be nice to be able to write some iterative method to capture and individually create each common WebElement from the list.
** I have made Updates to my question for further clarification** Taking an entire grid of info is completely new to me so please be specific with the answers as I am trying to understand the logic behind it.
So I have elements I am looking for are Grid Data, I have successfully captured the entire Grid, for example
#FindBy(id="ctl00_SomeGridData_ucControlList_trgControlList_ctl00")
List<WebElement> someGridData;
If I were to individually capture each new addition to the grid it would look as such:
#FindBy(id="ctl00_SomeGridData_ucControlList_trgControlList_ctl00__0")
WebElement someGridObj1;
#FindBy(id="ctl00_SomeGridData_ucControlList_trgControlList_ctl00__1")
WebElement someGridObj2;
#FindBy(id="ctl00_SomeGridData_ucControlList_trgControlList_ctl00__2")
WebElement someGridObj3;
As you can see each individual grid element ends with "__#" Obviously this is an infinite list and I cannot capture every WebElement individually and assign a WebElement value to use for testing. What I am trying to ask is how do I capture this entire list and then if i need to call an individual WebElement later to test how do I do so? I hope this clarifies and thanks for reading.
Ok, now that have edited your question, it's clear what you want to know. Assuming your grid data is in td elements, you can do the following.
#FindBy(css = "td[id^=ctl00_SomeGridData_ucControlList_trgControlList_ctl00__]")
List<WebElement> allGridData;
By using the ^ (which means starts with) you collect all the td elements that have an id starting with ctl00_SomeGridData_ucControlList_trgControlList_ctl00__.
Yes you can do this like below:
List<WebElement> mylist = driver.findElements(By.xpath("ur xpath"));
System.out.println("Size of the list is : " +mylist.size());
This will give you how many webelements are inside your mylist.
Now apply for loop to print the value of the mylist on console
and also in the for loop you can assign them a value like this
for(int i = 0;i<mylist.size();i++){
System.out.println("index of webelements in increasing order is : " + i + mylist.get(i).getText());
// this will assign an index of 0 to max for the weblements in the
list like index 0 = for 1 webelement ,index 1 = for 2nd webelement ,
index 2 = for 3rd webelement and so on
}

How do I determine list type (ul/li vs span) using WebDriver

I am working with a user-created table and list, where my program has to read in a list of entries for processing. I have the processors functioning, and I can navigate to the location in the table without any problems. The issue is that I am trying to allow for some flexibility in creating the list (inside the table) by allowing for the creator to input the list by either using un-ordered lists (/ul/li) and carriage-returns (/p).
Right now, I am determining whether the un-ordered list is used via driver.findElements(By.xpath("foo/ul/li")).size() being greater than 0. The issue is that this can take forever to "fail over." Is there a way that I am missing for making verifying element type (/ul/li vs /p vs /ol/li) faster?
I am using Java and Webdriver.
I guess you want to check if the concerned list is ordered or unordered by getting the size() and checking if it is greater than "0".
My suggestion is to get the parent tag of first "li" element which will then return "ul" or "li".
You can try the below code for that (Assuming list is present under some 'div' tag):
String tag = driver.findElement(By.xpath("//div//li[1]/..")).getTagName();//Returns the parent tag of the first element in the list
if(tag.contains("ul"))
System.out.println("List is unordered");
else if(tag.contains("li"))
System.out.println("List is ordered.");

Jdoms annoying textnodes and addContent(index, Element) - schema solutions?

i have some already generated xmls and the application causing problems now needs to add elements to it which need to be at a specific position to be valid with to the applied schemata...
now there are two problems the first one is that i have to hardcode the positions which is not that nice but "ok".
But the much bigger one is jdom... I printed the content list and it looks like:
element1
text
element2
element4
text
element5
while the textnodes are just whitespaces and every element i add makes it even more unpredictable how many textnodes there are (because sometimes there are added some sometimes not) which are just counted as it were elements but i want to ignore them because when i add element3 at index 2 its not between element2 and element4 it comes after this annoying textnode.
Any suggestions? The best solution imho would be something that automatically puts it where it has to be according to the schema but i think thats not possible?
Thanks for advice :)
The JDOM Model of the XML is very literal... it has to be. On the other hand, JDOM offers ways to filter and process the XML in a way that should make your task easier.
In your case, you want to add Element content to the document, and all the text content is whitespace..... so, just ignore all the text content, and worry about the Element content only.
For example, if you want to insert a new element nemt before the 3rd Element, you can:
rootemt.getChildren().add(3, new Element("nemt"));
The elements are now sorted out.... what about the text...
A really simple solution is to just pretty-print the output:
XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat());
xout.output(System.out, mydoc);
That way all the whitespace will be reformatted to make the XML 'pretty'.
EDIT - and no, there is no way with JDOM to automatically insert the element in the right place according to the schema....
Rolf

Categories