Selenium, Java- finding table by class (without ID) - java

I have something like this:
<table class="table">
<thead>
<tr>
<th>Role</th>
<th>Description</th>
<th>Access</th>
<th>Grant</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="role in roles">
<td>{{role.role_name}}</td>
<td>{{role.role_description}}</td>
<td><input type="checkbox" ng-model="role.allow_access" ng-change="updateAllow(role)" ng-disabled="!(role.grantor_allow_grant == 'Y' || haveAllAdminRoles)" ng-true-value="'Y'" ng-false-value="'N'"></td>
<td><input type="checkbox" ng-model="role.allow_grant" ng-change="updateAllow(role)" ng-disabled="!(role.grantor_allow_grant == 'Y' || haveAllAdminRoles)" ng-true-value="'Y'" ng-false-value="'N'"></td>
</tr>
</tbody>
</table>
How I can find this table using WebDriver or WebConnector ? I tried sth like this:
WebElement table = driver.findElement(By.className("table"));
and it doesn't work, I received error:
org.openqa.selenium.NoSuchElementException: Unable to locate element:
Thanks for any help.

That might be due to timing issue. You can use explicit wait to wait for the table to load or to be visible
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement table = wait.until(ExpectedConditions.presenceOfElementLocated(By.className("table")));
// or
WebElement table = wait.until(ExpectedConditions.visibilityOfElementLocated(By.className("table")));

May be when you are going to finding table, it could not be visible on the page due slow internet or other reason. To make sure table visible on the page try to find using WebDriverWait to wait until table visible as below :-
WebDriverwait wait = new WebDriverwait(driver, 10);
WebElement table = wait.until(Expectedconditions.visibilityOfElementLocated(By.className("table")));
Hope it helps..:)

Related

How can I get the XPATH directly from accessed element using different selector [duplicate]

I would like to find an element using a differect cssSelector / tag / ClassName amd them get it's xpath value ( to be more specific, I have a website where when a day changes, one of the classes change it's class) here is what do I meean:
<tr>
<td> 1.1.2019 </td>
<td> 2.1.2019 </td>
<td class="active"> 3.1.2019 </td>
<td> 4.1.2019 </td>
</tr>
<tr>
<td> </td>
<td> 10 </td>
<td> </td> #Here
<td> </td>
</tr>
I want to according to where is that "active class", click the table under it. ny idea how to do so ?
short version of what I want :
Find element using cssSelector
Get this element's Xpath <- the problem
click it using edited xpath
I want to GET XPATH OF LOCATED ELEMENT , not to locate it using Xpath
You can find the index by locating all the <td> elements in the first row and check wich one has the index
List<WebElement> columns = driver.findElements(By.xpath("//tr[td[#class='active']]/td")); # just an example, can be any other locator
int index = 0;
for (int i = 0 ; i < columns.getSize() ; i++) {
String attribute = columns.get(i).getAttribute("class")
if (attribute != null && attribute.equals("active")) {
index = i + 1;
}
}

WebElement.findElement method is finding element under WebDriver scope

I have the following HTML code on which I am trying to run my selenium test
<html>
<head></head>
<body>
<table id="Original">
<tr>
<td>Original-11</td>
<td>Original-12</td>
<td>Original-13</td>
</tr>
<tr>
<td>Original-21</td>
<td>Original-22</td>
<td>Original-23</td>
</tr>
<tr>
<td>Original-31</td>
<td>Original-32</td>
<td>Original-33</td>
</tr>
</table>
<br/><br/>
<table id="Duplicate">
<tr>
<td>Duplicate-11</td>
<td>Duplicate-12</td>
<td>Duplicate-13</td>
</tr>
<tr>
<td>Duplicate-21</td>
<td>Duplicate-22</td>
<td>Duplicate-23</td>
</tr>
<tr>
<td>Duplicate-31</td>
<td>Duplicate-32</td>
<td>Duplicate-33</td>
</tr>
</table>
</body>
</html>
The selenium java code looks like this:
public static void main(String[] args) throws Exception
{
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "/src/test/drivers/chromedriver.exe");
WebDriver drv = new ChromeDriver();
drv.get("C:/Users/MYUserName/git/er_test/SeleniumTestHtml.html");
WebElement tableElement = drv.findElement(By.id("Duplicate"));
WebElement rowElement = tableElement.findElement(By.xpath("//tr[2]"));
WebElement cellElement = rowElement.findElement(By.xpath("//td[2]"));
System.out.println(rowElement.getText());
System.out.println(cellElement.getText());
drv.close();
drv.quit();
}
I am expecting a result as follows :
Duplicate-21 Duplicate-22 Duplicate-23
Duplicate-22
But I am getting this result :
Original-21 Original-22 Original-23
Original-12
Am I doing something wrong here ?
Your problem is that // makes you go back to search from top root element.
Which means
WebElement rowElement = tableElement.findElement(By.xpath("//tr[2]"));
Is as good as
WebElement rowElement = driver.findElement(By.xpath("//tr[2]"));
If you need to search only inside the current element then you should use
WebElement rowElement = tableElement.findElement(By.xpath(".//tr[2]"));

selenium dynamic growing table

I have some troubles to handle dynamic growing table with selenium.
To sum up quickly, on my web app I have a table with 30 items but it only displays the twenty first items and we have to scroll down to display the rest.
And I don't know how to get the 26th (for example) items without scrolling down.
My HTML:
<table id="tableID" tabindex="0" aria-multiselectable="true" role="grid">
<thead>
<tbody id="tableID-tblBody">
<tr id="item1" role="row" tabindex="-1">
<tr id="item2" role="row" tabindex="-1">
[... 17 more]
<tr id="item20" role="row" tabindex="-1">
</tbody>
</table>
After scrolling:
<table id="tableID" tabindex="0" aria-multiselectable="true" role="grid">
<thead>
<tbody id="tableID-tblBody">
<tr id="item1" role="row" tabindex="-1">
<tr id="item2" role="row" tabindex="-1">
[... 27 more]
<tr id="item30" role="row" tabindex="-1">
</tbody>
</table>
If someone could help me it would be great ^^
Thanks!
I would scroll into view of the last row in the table (if necessary multiple times until you get the desired row count). For this I'd use scrollIntoView() via executeScript():
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("arguments[0].scrollIntoView();", element);
where element:
WebElement element = driver.findElements(By.xpath("//table[#id = 'tableID']//tr[last()]")).
You cant get that item without scrolling down (to scroll down use #alecxe solution), because the element you want to choose is not even in the html at the time you search for it.
After the scroll you should be able to find it easily by id.
I think you are trying to compare values
Expected Value V/s Actual Value.
To do this I would request you to take all elements/object under this table : tableID-tblBody and search for ID of 26 and take value.
Here is my code that I used to perform similar task.
WebDriverWait wait = new WebDriverWait(driver, timeout);
List<WebElement> totalrow = wait.until(ExpectedConditions
.presenceOfAllElementsLocatedBy(By.Id("tableID-tblBody"));
for (int i = 0; i <= totalrow.size(); i++) {
String xPath ="" //"XPATH OF 26 ITEM";
try {
WebElement element = ExpectedBehaviors
.expectPresenceofElementBy(driver, By.xpath(xPath),
getAlertTimeout());
if (element.getText().trim().equals("EXPECTED VALUE")) {
//"PERFORM YOUR ACTION"
break;
}
} catch (Exception e) {
//"You can add your exception and error message
}
}

HREF + TEXT with Jsoup

I've the following HTML Page:
</div><div id="page_content_list01" class="grid_12">
<h2><strong class="floatleft">TEXT1</strong></h2><br>
<table>
<tbody>
<tr>
<th class="no_width">
<p class="floatleft">Attachments:</p>
</th>
<td class="link_azure">
<a target="_blank" href="http://www.example.com">TEXT2</a><br/>
</td>
</tr>
</tbody>
</table><h2><strong class="floatleft">TEXT3</strong></h2><br>
<table>
<tbody>
<tr>
<th class="no_width">
<p class="floatleft">Atachments:</p>
</th>
<td class="link_azure">
<a target="_blank" href="http://www.example2.com">TEXT4</a><br/>
</td>
</tr>
</tbody>
</table><h2><strong class="floatleft">TEXT5</strong></h2><br>
<table>
<tbody>
<tr>
Actually I'm doing:
Elements rows = document.select("div#page_content_list01");
Now I to select "TEXT" and link. I wanna to make clickable link, so I'm using:
for (Element eleme : rows) {
Elements elements = eleme.select("a");
for (Element elem : elementi) {
String url = elem.attr("href");
String title = elem.text();
}
}
and I'm getting:
url = "http://www.example.com";
title = "TEXT2";
and it's ok, but in this way I can't read "TEXT1" and "TEXT3".
Can someone help me please?
I think you need to work on the selecors. First, your primary selector
Elements rows = document.select("div#page_content_list01");
will return with a list of ONE element only, since you actually select the div, not the tables or table rows. I would instead do this to get all relevant info:
Elements tables = document.select("div#page_content_list01>table");
for (Element table : tables){
Element h2 = table.previousElementSibling();
String titleStr = h2.text();
Element a = table.select("a").first();
String linkStr = a.attr("href");
}
Note that the Text in the h2 elements is on the same level as the table, not inside a common div. This is why I use the previous sibling notation. Also note that I wrote this out of my head and it is untested. You should get the idea though.

How to locate links in a calendar table using webdriver and java?

I'm learning to work with Maven, Java, testng and webdriver by doing a self training course. I been doing great with all exercises until I got to the last one, I honestly don't know how to solve it. Let me give you some context:
Exercise description: Open the site homepage and using the calendar(html calendar in a wordpress site), check how many days of
the current month contain posts, then access the first day which has
post and print the titles of the posts in the console.
When any day in the calendar has posts, instead of showing the day in
plain text, the site shows the day number as a link that once clicked
opens the lists of posts in the main page.
This is a screen capture of how this site looks when I click on the day which has posts, in this case October 10th 2013: http://i.stack.imgur.com/wGRO2.jpg
Like I said the site is a wordpress site (unfortunately can only be accessed through VPN so I can't share it), and I need to use the calendar widget which is a table. I was able to go over each row and column of the table and print each column's text.
But how do I find if any of those days have a link in it and then having located that element how can I access it and print it's content (is this case they want me to print the titles of all posts created under that date)?
This is the code I'm using to go over the entire table and print the content:
//Test Case 6
#Test (timeOut=20000)
public void TestCalendar(){
HomePage homePage = PageFactory.initElements(driver, HomePage.class);
homePage.Go(driver);
WebElement table = homePage.ReturnCalendarElement();
//Actual Month has no posts, so we select previous one which has 2 posts
homePage.ClickPreviousMonth();
//We Get All rows of the calendar then we get all columns and its data
List<WebElement> rows = table.findElements(By.tagName("tr"));
for (WebElement row: rows) {
List<WebElement> cols= row.findElements(By.tagName("td"));
for (WebElement col: cols){
System.out.print(col.getText() + "\t");
}
}
}
I'm adding the HTML code of that page in case it helps you to provide some answers:
Follow this link to open a Public Gist with the HTML code of the page: https://gist.github.com/anonymous/599cd722b5c906808528
The following is the HTML code for the Table I'm testing:
<aside id="calendar-2" class="widget widget_calendar"><h3 class="widget-title">Posts by date:</h3><div id="calendar_wrap"><table id="wp-calendar">
<caption>October 2013</caption>
<thead>
<tr>
<th scope="col" title="Monday">M</th>
<th scope="col" title="Tuesday">T</th>
<th scope="col" title="Wednesday">W</th>
<th scope="col" title="Thursday">T</th>
<th scope="col" title="Friday">F</th>
<th scope="col" title="Saturday">S</th>
<th scope="col" title="Sunday">S</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="3" id="prev" class="pad"> </td>
<td class="pad"> </td>
<td colspan="3" id="next" class="pad"> </td>
</tr>
</tfoot>
<tbody>
<tr>
<td colspan="1" class="pad"> </td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>11</td>
<td>12</td>
<td>13</td>
</tr>
<tr>
<td>14</td>
<td>15</td>
<td>16</td>
<td>17</td>
<td>18</td>
<td>19</td>
<td>20</td>
</tr>
<tr>
<td>21</td>
<td>22</td>
<td>23</td>
<td>24</td>
<td>25</td>
<td>26</td>
<td>27</td>
</tr>
<tr>
<td>28</td>
<td>29</td>
<td>30</td>
<td>31</td>
<td class="pad" colspan="3"> </td>
</tr>
</tbody>
</table></div></aside>
This is the last problem I need to solve to end with this training, so any help and orientation will be highly appreciated.
Use a better CSS query to get the links of the calendar.
It would be something like:
td a
Elements TD with a link A inside.
Not much help without the HTML code of the page.
I ended up finding a solution, while i'm sure there should be a better way to do this. But this worked for me & might help someone else somehow:
// Test Case 6
#Test(timeOut = 40000)
public void TestCalendar() {
HomePage homePage = PageFactory.initElements(driver, HomePage.class);
CalendarPage calendarPage = PageFactory.initElements(driver,
CalendarPage.class);
homePage.Go(driver); //this just navigates to the page
homePage.ReturnPreviousMonth().click();
//returns the calendar element mapped in the page
WebElement table = homePage.ReturnCalendarElement();
WebElement dayWithPost = calendarPage.GetFirstDayWithPosts(driver,
table);
Assert.assertNotNull(dayWithPost);
System.out.println("We'll be working with the following day: " + dayWithPost.getText());
dayWithPost.click();
List<WebElement> articles = driver.findElements(By
.className("entry-title"));
for (WebElement article : articles) {
System.out.println("Retrieved Post's Title: [ "
+ article.findElement(By.tagName("a")).getText() + " ]");
}
public class CalendarPage {
public List<WebElement> ReturnArticlesOnPage(WebDriver driver) {
List<WebElement> articles = driver.findElements(By.tagName("article"));
return articles;
}
public WebElement GetFirstDayWithPosts(WebDriver driver, WebElement table) {
List<WebElement> rows = table.findElements(By.tagName("tr"));
for (WebElement row : rows) {
List<WebElement> cols = row.findElements(By.tagName("td"));
for (WebElement col : cols) {
try {
if (col.findElement(By.tagName("a")).getAttribute("href") != null ){
System.out.println("Day: " + col.getText()+ " has posts and was returned.");
return col;
}
}
catch (NoSuchElementException e){
//System.out.println("Day: " + col.getText()+ " has no posts.");
}
}
}
return null;
}
}

Categories

Resources