I am working on selenium webdriver using java. I am facing a problem. I have a web table and I have test case for add event functionality, that successfully adds the event in the table. Now I want to assert/verify if I got the added event in my table or not (Because if the functionality is broken, then date will not add in the table, and I can fail that test deliberately). The number of events are unknown before the start of test case. My logic for this test case verification is as follows:
Add the event in the table. The code to add event is :
public void addIndividualEvent(String eventDate, String eventName) throws Exception
{
driver.findElement(individualEventDate).sendKeys(eventDate);
driver.findElement(individualEventName).sendKeys(eventName);
driver.findElement(addIndividualEventBtn).click();
}
Now, after this step, there may be multiple events already in the table. So my next step would be to.
Find the number of rows in the table.
Construct a for loop that goes through each row and get the text of the date field.
Add the result of for loop to a list.
Then Assert.assertEquals(List,eventDate); will tell me if my added event is in the table or not.
Now, below is the HTML code of the table in my website.
<table class="table table-condensed table-hover event-list">
<tbody>
<tr class="study-event-row ng-scope" ng-repeat="event in events | orderBy:'-date'">
<tr class="study-event-row ng-scope" ng-repeat="event in events | orderBy:'-date'">
<tr class="study-event-row ng-scope" ng-repeat="event in events | orderBy:'-date'">
</tbody>
</table>
I was able to construct the xpath that highlights all my rows available in the table.
xpath = //table[#class='table table-condensed table-hover event-list']/tbody/tr
Now the issue I am facing is that I dont know how to use this xpath to get the count of rows from my table. I tried to use xpath.getSize(); but this returned the dimensions of the table and not the actual count.
Can anyone tell me how can I get the no of rows? Thanks
To get the rows, do the following-
Using CSS selector:
List<WebElement> rows = driver.findElement(By.cssSelector("[class='table table-condensed table-hover event-list'] tr"));
Or if you have to use XPATH, then do:
List<WebElement> rows = driver.findElements(By.xpath("//table[#class='table table-condensed table-hover event-list']/tbody/tr"));
This is returning a list of WebElements. You can get the count here:
int count = rows.size();
System.out.println("ROW COUNT : "+count);
Then you can get text for each element and assert if it's as expected. As you are saying the text should be same for all elements, then you can do something like this:
for(WebElement e : rows) {
assertEquals("expected text", e.getText());
}
Use the following code to get the row size of the table.
WebElement webElement=project.login.driver.findElement(By.xpath("tbodyXpath"));
List<WebElement> rows=webElement.findElements(By.xpath("tablerowXpath"));
System.out.println("Size -------"+rows.size());
Assuming your XPath works, you can just do this...
List<WebElement> rows = driver.findElements(By.xpath("//table[#class='table table-condensed table-hover event-list']/tbody/tr"));
System.out.println(rows.size());
It will return you the number of rows (TRs) in that table.
You could use the XPath:
count(//table[#class='table table-condensed table-hover event-list']//tr)
This will count all the tr elements that are descendants of the table element with #class="table table-condensed table-hover event-list"
Resolve the table object through your xpath, then use that WebElement as your SearchContext and get all TR elements within. The size of the return list should tell you your visible row count.
int EXPECTED_ROW_COUNT = 3;
/**
* Test case for counting the number of visible rows in a table.
* #see "http://stackoverflow.com/questions/33233883/getting-the-count-of-rows-from-a-web-table-selenium-webdriver-java"
* #author http://stackoverflow.com/users/5407189/jeremiah
*/
#Test
public void testCountRows() {
WebDriver wd = new FirefoxDriver();
wd.get("http://www.w3schools.com/html/tryit.asp?filename=tryhtml_table");
WebDriverWait wait = new WebDriverWait(wd, 10);
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("iframeResult"));//Specific to test location # w3schools!
WebElement parentTable = wd.findElement(By.xpath("html/body/table/tbody"));
//WebElement parentTable = wd.findElement(By.xpath("//table[#class='table table-condensed table-hover event-list']/tbody"));
//Now use the parentTable as the root of the search for all 'tr' children.
List<WebElement> rows = parentTable.findElements(By.xpath("./tr"));
Assert.assertTrue(EXPECTED_ROW_COUNT == rows.size());
}
/**
* Test that you can use to direct at your url and interact with rows.
*/
#Test
public void testYourRowCount() {
WebDriver wd = new FirefoxDriver();
//FIXME
wd.get("yourURLHere");
WebElement parentTable = wd.findElement(By.xpath("//table[#class='table table-condensed table-hover event-list']/tbody"));
//Now use the parentTable as the root of the search for all 'tr' children.
List<WebElement> rows = parentTable.findElements(By.xpath("./tr"));
//FIXME: Do stuff with the rows.
}
Related
My code is like below.
private List<WebElement> reports;
public List<WebElement> getReports(){
return Common.returnElementList(DriverFactory.getDriver(), reportsMenu, reports);
}
public Map<String, String> getReportDesc() {
Map<String, String> temp = new HashMap<>();
for(WebElement item: getReports()){
List<WebElement> cols = item.findElements(By.xpath("/child::td[#role='gridcell']"));
String key = Common.getElementText(DriverFactory.getDriver(), cols.get(0));
String desc = Common.getElementText(DriverFactory.getDriver(), cols.get(1));
temp.put(key, desc);
}
return temp;
}
With item.findElements(By.xpath("/child::td[#role='gridcell']")); I am trying to get the cells of that specific row, instead I am getting all the cells in that table.
How Can I get the specific row columns?
You need to use relative XPath locator.
Since you didn't share a link to the page containing that table we can only guess. So, I guess:
Instead of
item.findElements(By.xpath("/child::td[#role='gridcell']"));
try this:
item.findElements(By.xpath(".//td[#role='gridcell']"));
The dot . infront of the XPath means this is relative XPath, we want to locate element matching //td[#role='gridcell'] inside current node item.
Otherwise driver will search for all elements matching /child::td[#role='gridcell'] expression form the first, top element on the page.
I need to go through all the table values and grab those into array list (or your some suggested place)
First-row xpath list
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/th[1]
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[1]
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[2]
.
.
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[5]
2nd row, few xpaths
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[2]/th[1]
/html[1]/body[1]/div[4]/div[1]/main[1]/div[1]/div[3]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[2]/td[1]
Please provide some Custom keyword logic for capture those values in easy way.
DOM
We can start using relative xpath for table's tbodythen we can use tagName method of By class for html tag names 'tr' and 'td' to fetch the rows and column elements
then we can save to arrayList as shown below in code.
Note - Closely observe first call to get table start is findElement and remaining are findElements as we want all elements with tr and td tagname.
#Test
public void testWebTable() {
WebElement simpleTable = driver.findElement(By.xpath("//table[1]/tbody[1]"));
// Get all rows
List<WebElement> rows = simpleTable.findElements(By.tagName("tr"));
List<String> webTableData = new ArrayList<String>();
// Print/Save data from each row
for (WebElement row : rows) {
List<WebElement> cols = row.findElements(By.tagName("td"));
for (WebElement col : cols) {
webTableData.add(col.getText());
System.out.print(col.getText() + "\t");
} System.out.println();
}
}
You can use PHP Simple HTML Dom parser library to parse those table data easily. Check out https://simplehtmldom.sourceforge.io/
I am trying to read all the heading tag on a page and need to click only one heading tag named "dropdown". The sample structure of HTML is as follows
<div> <ul> <li>
<a href="submit_button_clicked.php">
<h2>Submit Button Clicked</h2>
<figure>
</a>
</li>
<li>
<a href="dropdown.php">
<h2>Dropdown</h2>
<figure>
What i did is to create a custom xpath and store it in List,then iterate through list using for loop but i am unable to /read/write the value of tag on console.
List l = ff.findElements(By.xpath("//div/ul/li/a/h2"));
To retrieve the text value of an element use:
element.getText();
In your case with your list it would look something like this:
for(WebElement element : l) {
System.out.println(element.getText());
}
Since you want to click on an element, it would be better to use an xpath such as the following:
ff.findElements(By.xpath("h2[text()='Dropdown']")).click();
To find and click the specific element you want. The above xpath selector looks for a h2 element with the exact text 'Dropdown' and then clicks on it.
Reading all <h2> tags can look something like:
List<WebElement> elements = ff.findElements(By.xpath("//h2"));
for(WebElement element : elements) {
System.out.println(element.getText()); // just to show that it prints text
}
Note that I defined list as List<WebElement> which is to avoid usage of raw types, and changed xpath to match any <h2>.
But when you need to click, usually you are required to click on parent <a> element, not on <h2> itself, i.e. the following should click on a correct link
ff.findElement(By.xpath("//a[#href='dropdown.php']")).click();
But if you want to find a link from header, in the above loop:
List<WebElement> elements = ff.findElements(By.xpath("//h2"));
for(WebElement element : elements) {
if("Download".equals(element.getText()) {
// get the parent <a> element and click on it
element.findElement(By.xpath("..")).click();
}
}
Hi please do it like below
WebDriver driver = new FirefoxDriver();
driver.get("http://www.seleniumhq.org");
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// Hi please do it like below ,take all H2 tag inside the list
List<WebElement> myH2Tags = driver.findElements(By.tagName("h2")); // you can put any tag name as per your requirement
for(int i=0;i<myH2Tags.size();i++){
System.out.println("Value of My H2 Tags are : " + myH2Tags.get(i).getText());
if(myH2Tags.get(i).getText().equals("Selenium News")){ // you can replace this with drop down value
myH2Tags.get(i).click();
}
// to avoid stale element exception you have to re identify the elements
myH2Tags = driver.findElements(By.tagName("h2"));
}
If anyone needs reference or background here was my first question asked
Retrieving a list of WebElements and Identifying them
At this point I have retrieved a list of WebElements
#FindBy(css = "td[id^=ctl00_SomeGridData_ucControlList_trgControlList_ctl00__]")
List<WebElement> allGridData;
At this point in my code I can use the web Element to call the index for example
allGridData.get(0).click
however the list is not strictly integers for example if I access at the row level <tr> it would be:
ctl00_SomeGridData_ucControlList_trgControlList_ctl00__0
but if I were to call a link within row they are table data <td> broken into divs that look like this:
ctl00_SomeGridData_ucControlList_trgControlList_ctl00__ctl04_lbView
ctl00_SomeGridData_ucControlList_trgControlList_ctl00__ctl04_hlTestPlan
or this
ctl00_SomeGridData_ucControlList_trgControlList_ctl00__ctl07_lbView
ctl00_SomeGridData_ucControlList_trgControlList_ctl00__ctl07_hlTestPlan
Since all the WebElements start with a common css selector
#FindBy(css = "td[id^=ctl00_SomeGridData_ucControlList_trgControlList_ctl00__]")
List<WebElement> allGridData;
how can identify a specific index that is a char value (ie ctl107) vs just an integer?
Assuming you want two lists, one for the View Details and one for the View Test Plans, you need the $ (ends with):
#FindBy(css = "a[id$=lbView]")
List<WebElement> allDetailViewLinks;
#FindBy(css = "a[id$=hlTestPlan]")
List<WebElement> allTestPlanLinks;
But my best guess is that you want to click on a link in a specific row rather than based on index in a list of Web Elements. For instance based on the text in the td in <tr id="ctl00_SoxMain_ucControlList_trgControlList_ctl00__0" class="rgRow">
<td class="rgExpandCol" valign="top"/><td valign="top">AL-01</td>.
You need a method to get the row with specific text in the td.
WebElement getRow(String specificValue) {
return driver.findElement(By.xpath("//td[text()='"+specificValue+"']"))
.findElement(By.xpath(".."));
}
Then you can make the methods for detail view and test plan view.
public void openDetailsView(String specificValue) {
getRow(specificValue)
.findElement(By.cssSelector("a[id$=lbView]"))
.click();
}
public void openTestPlanView(String specificValue) {
getRow(specificValue)
.findElement(By.cssSelector("a[id$=hlTestPlan]"))
.click();
}
I have to fetch two labels 'Text 1', 'Text 2' which belongs to same class ='xyz', which are located in two div's.Structure as shown below.
<div class='xyz'>TEXT 1</div>
<div class='xyz'>TEXT 2</div>
Can anyone please help me to solve this ?
You find elements by className and then use getText() to get the text:
List<WebElement> elements = driver.findElements(By.className("xyz"));
for(WebElement element:elements) {
System.out.println(element.getText());
}
Use FindElements method and then access to necessary div using index, e.g:
var elements = driver.FindElements(By.CssSelector((".xyz"));
//get text in first element;
elements[0].getText();
//in second
elements[1].getText(); //etc