How to locate table when no Id defined for the table in Selenium WebDriver? - selenium

I have been searching on the Internet for answer, seems no luck.
The problem here is I try to locate the following dynamic table which doesn't have id defined for the table:
<div class="modal-body">
<table class="table table-striped data-table">
<thead>
<tr>
<th dt-bSortable="false">Name</th>
<th dt-bSortable="false">ID</th>
<th dt-bSortable="false">Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>NameA</td>
<td>111</td>
<td>nameA#test.com</td>
</tr>
<tr>
<td>NameB</td>
<td>222</td>
<td>nameB#test.com</td>
</tr>
...
What I need which is based on a given ID, I could find the corresponding Name and Email. But first, I should locate the table. I tried the following ways, but none of them are working:
WebElement table = driver.findElement(By.className("table table-striped data-table"));
WebElement table = driver.findElement(By.xpath("//table[#class='table table-striped data-table']"));
WebElement table = driver.findElement(By.cssSelector("table.table-striped"));
I also tried to directly fetch all the rows by:
List<WebElement> rows = driver.findElements(By.xpath("//table[#class='table table-striped data-table']/tbody/tr"));
But rows.isEmpty() always returns true.
Please help me on this issue. Thanks in advance for any advice.

I would have expected
WebElement table = driver.findElement(By.cssSelector("table.table-striped"));
to work, since this means, 'find the table element with the class table-striped'. If, however, you were intending to 'find the element with the class table and the class table-striped' (which it looks like you are based on your other attempts), the command would be
WebElement table = driver.findElement(By.cssSelector(".table.table-striped"));
Note the extra '.'.

Related

How to extract the text 8 from the 2nd row and 2nd column as per the html through Selenium and VBA

Using selenium vba i want 2nd row and 2nd column value from webpage table below is the code which i have try but it capture all table.
The output which i want is 8.
driver.FindElementByXPath("//table[contains(#class,'zedoLocTable')]").text
Please find the below html code.
<tr>
<td colspan="4">
<div id="localityTiers">
<br><br>
<table class="zedoLocTable" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<th>TYPE</th>
<th>TIER</th></tr>
<tr>
<td><b>Resedential Sale</b>
</td><td>8</td>
</tr>
<tr><td><b>Resedential Rent</b>
</td><td>5</td>
</tr><tr>
<td><b>Commercial Sale</b>
</td><td>1</td>
</tr><tr>
<td><b>Commercial Lease</b>
</td><td>1</td>
</tr></tbody></table><table></table></div>
</td>
</tr>
Below is the table pic
As per the HTML you have shared to extract the text 8 you can use the following solution:
driver.FindElementByXPath("//table[#class='zedoLocTable']//tr/td/b[contains(.,'Resedential Sale')]//following::td[1]").text
You can use a faster CSS selector, than using xPath, if you are working with later IE or other browers apart from IE
Debug.Print driver.FindElementByCSS(".zedoLocTable td + td").innerText

Adding a second header row to bootstrap-vue's b-table

I have a table header that looks like this:
I'm trying to recreate this table in bootstrap-vue. The raw HTML looks like this (simplified):
<table>
<thead>
<tr>
<th></th>
<th colspan="4">Group 1</th>
<th colspan="4">Group 2</th>
<!--etc-->
</tr>
<tr>
<th>Field</th>
<th>Median</th>
<!-- etc -->
</tr>
</thead>
<tbody><!-- actual data --></tbody>
</table>
The core b-table code will create the 2nd row easily/automatically. I'm trying to figure out how to jam the 1st row in there. As a little kicker, I need to be able to control the contents of the two group names (i.e. if they change a control somewhere, "Group 1" becomes "Group Foo").
I made a playground for anyone that needs a starting point for helping figure this out: https://codesandbox.io/s/p56y3y2lnx The goal in there would be to programmically add a 1st row that includes the group1name and spans the width of the table in one colspan.
As of version v2.0.0-rc.14 (released 2019-03-08) you can now add additional rows above the header using the slot thead-top.
For your example, you would place the following code inside of the b-table tag:
<template slot="thead-top" slot-scope="data">
<tr>
<th></th>
<th colspan="3">Group 1</th>
<th colspan="4">Group 2</th>
<th colspan="4"></th>
</tr>
</template>
Here's a reference to the new feature: https://bootstrap-vue.js.org/docs/components/table/#adding-additional-rows-to-the-header
I was unable to find a clean way to achieve the results I wanted, so I ended up with something more hacky.
On b-table you can add an input event, so I did that to know when the table was finished loading.
HTML:
<b-table #input="tableLoaded" ref="table"></b-table>
then in my methods:
tableLoaded() {
if (!this.$refs.table) {
return;
}
var headers = this.$refs.table.$el.querySelectorAll('thead tr');
if (headers.length > 1) {
return;//nothing to do, header row already created
}
var topHeader = document.createElement('tr');
topHeader.innerHTML =
'<th></th>'+
'<th colspan="3">Group 1</th>'+
'<th colspan="4">Group 2</th>'+
'<th colspan="4"></th>';
headers[0].parentNode.insertBefore(topHeader, headers[0]);
}
I'd be happy to accept a cleaner solution.

how to get Table element from a Div that has a Heading tag with a known text - using selenium and java

<h3>Movers and Shakers</h3>
<p>
<strong>Strategy Hint 1:</strong><br>
<strong>Strategy Hint 2:</strong><br>
</p>
<table cellspacing="0" cellpadding="0" border="1">
<tbody>
<tr>
<td> </td>
<td>ExternalId</td>
<td>Name</td>
<td>Price cents</td>
<td>Brand</td>
<tr>
<tr>
<td>1</td>
<td>123</td>
<td>Draw</td>
<td>2</td>
<td>Ciko</td>
<tr>
Now, the know text in the h3 tag is 'Movers and Shakers'. The table and h3 are in a Div tag. Now, how do I get the table for this specific div that has that specific known text('Movers and Shakers').
With the help of xpath, use following code to return the DIV element that contains a heading H3 with the text Movers and Shakers:
WebElement div = driver.findElement(By.xpath("//div[h3[text()='Movers and Shakers']]"));
Ant then, find the table inside this div web-element:
WebElement table = div.findElement(By.xpath(".//table"));
This will return the table element you want:
WebElement table = driver.findElement(By.xpath("//div[h3[contains(.,'Movers and Shakers')]]")).findElement(By.tagName("table"));
this short line worked
WebElement table = driver.findElement(By.xpath("//h3[contains(text(),'Movers and Shakers')]/following-sibling::table"));

Get elements from row (Telerik Test Studio)

So I need to get all the values from a bunch of rows using Telerik Test Studio.
I basically recorded a test to go to a certain page on a web app, and I have a row called Session ID with a few randomly generated rows below it and I want to get the values from those rows, to use with code or whatever.
How would I go about doing it?
Here is a picture of what I mean:
This can be achieved in a coded step.
Let's say you have a few rows in a html table and you want to get their values. You need to collect all rows in a collection and then just take the value of each member of the collection.
Here is an example:
HTML:
<table id="table">
<tr>
<td>1</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>3</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr>
<td>5</td>
</tr>
<tr>
<td>6</td>
</tr>
</table>
The code of the coded step in C#:
HtmlTable myTable = ActiveBrowser.Find.ById<HtmlTable>("table"); //Locate the table
IList<HtmlTableRow> myList = myTable.Find.AllByTagName<HtmlTableRow>("tr");//Collect all rows.
foreach (HtmlTableRow rows in myList)
{
Log.WriteLine(rows.InnerText.ToString());
}
Here is a video demonstration.
Hope I could help.
You can find the ID or any other attribute in the HTML structure of the application (e.g. in Chrome/IE by pressing F12).
Here is a sample code against Telerik ASP gridview page. Here I am retrieving the first row and then only the first column:
HtmlTable myTable = ActiveBrowser.Find.ById<HtmlTable>("ctl00_ContentPlaceHolder1_RadGrid1_ctl00");
IList<HtmlTableRow> myList = myTable.Find.AllByTagName<HtmlTableRow>("tr");
//First row
Log.WriteLine(myList[11].InnerText.ToString());
//First column
for (int i = 11; i < myList.Count; i++)
{
Log.WriteLine(myList[i].Cells[1].InnerText.ToString());
}
I also recorded another video for a demonstration.

Use Greasemonkey to remove table

I am trying to replace a table with my own table using grease monkey. The page that has the table has 2 tables with the same class and no IDs.
I need to replace only the second table (with my own table) and do nothing to the first table. There is nothing that really makes the second table unique from the first table, so the only thing I can think of is trying to add a DIV around the second table, but cant figure it out.
Any ideas? Heres the page code:
<h3>Table 1</h3>
<table class="details" border="1" cellpadding="0" cellspacing="0">
<tbody><tr>
<th>1</th>
<td>2</td>
</tr>
</tbody></table>
<h3>Table 2</h3>
<table class="details" border="1">
<tbody><tr>
<th>1</th>
<td>2</td>
</tr><tr>
<th>3</th>
<td>4</td>
</tr>
</tbody></table>
You can use xpath to find the second tables, and do something with it. The xpath expression would be (//table[#class="details"])[2]. Below I added an example which uses (//pre)[1] instead, this will find the first code block on this page, I will hide it as an example. So this hides the page code from your question. (//pre)[2] will hide my script.
See Also here for a tutorial how to use xpath.
// ==UserScript==
// #name so-test
// #namespace test
// #include http://stackoverflow.com/questions/4635696/use-greasemonkey-to-remove-table
// ==/UserScript==
// find first <pre> on this page
var xpathResult = document.evaluate('(//pre)[1]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
var node=xpathResult.singleNodeValue;
// now hide it :)
node.style.display='none';