I am trying to verify if the table contains filetype (1st cell) is figure then 3ed cell should contain jpg or png, etc and 5th cell should contain (something)
the function should return true or false.
here is my code I don't know what I am doing wrong, because it always returns false even is the conditions are true. Thanks for the help !!
public bool Results()
{
var aqcTable = Browsers.getDriver.FindElement(By.TagName("table"));
var lstTrElem = aqcTable.FindElements(By.TagName("tr"));
var i = 0;
foreach (var cell in lstTrElem)
{
if (lstTrElem[i].Text== "figure")
if (lstTrElem[ i+ 2].Text.Contains("jpg"))
if (lstTrElem[i + 4].Text.Contains("pass"))
return true;
}
return false;
}
You are trying to get the Text of a <tr> element.
You need to get the text of <td>. So if what you are trying to achieve is:
I am trying to verify if the table contains filetype (1st cell) is
figure then 3ed cell should contain jpg or png, etc and 5th cell
should contain (something)
And you HTML content looks like this:
<table>
<tbody>
<tr>
<td>fig_ure</td>
<td>Some value</td>
<td>jpg</td>
<td>Some other value</td>
<td>Some other value</td>
</tr>
<tr>
<td>Figure</td>
<td>Some value</td>
<td>jpg</td>
<td>Some other value</td>
<td>Some other value which contains the pass word</td>
</tr>
</tbody>
</table>
Note: The text comparison is case sensitive. "figure" will not match "Figure"
Note: Name your variables as such, that the name should immediately convey what it holds
Note: First check existence and access later (tdElements.Count > 0 ?)
var firstTableElement = driver.FindElement(By.TagName("table"));
var trElementList = firstTableElement.FindElements(By.TagName("tr"));
foreach (var trElement in trElementList)
{
var tdElementList = trElement.FindElements(By.TagName("td"));
if (tdElementList.Count > 0)
{
bool trMatchesRequirements =
tdElementList[0].Text == "figure" &&
tdElementList[2].Text.Contains("jpg") &&
tdElementList[4].Text.Contains("pass");
if (trMatchesRequirements)
{
return true;
}
}
}
return false;
Related
Let's say, I've this table:
+--------+----------+----
| Device | Serial # |
+--------+----------+----
| Cam1 | AB123 |
+--------+----------+----
Since I don't know in advance the columns that'll be displayed, I construct the table by sending just a pair of key/vale for each cell.
This is how I'm getting my data in C# code.
List<List<KeyValue>> myTable = deviceRepository.GetKeyValues(int facilityId);
Once set to the client side, data in the myTable will be of the following structure:
myTable = [
[ { key: "DeviceName", value: "Device"}, { key: "SerialNumber", value: "Serial #"}, ..],
[ { key: "DeviceName", value: "Cam1"}, { key: "SerialNumber", value: "AB123"}, ..],
...
]
In razor, I'd just have to loop through the list.
#foreach(var row in Model)
{
<tr>
#foreach(var cell in row)
{
<td>#cell.Value</td>
}
</tr>
}
In Angular, I don't see how to do that with directives.
<tr *ngFor="let myInnerList of myTable">
//I'd like to loop through the each inner list to build each table cell
</tr>
Thanks for helping
EDIT
Is it possible to get something like this? i.e if the column is the ID, display a checkbox so that the row can be selected.
#foreach(var cell in row)
{
if(cell.Key == "Id")
{
<td><input type="checkbox" id="row_#cell.Value" /></td>
}
else
{
<td>#cell.Value</td>
}
}
This way, the first cell for every row will display a checkbox.
I am not sure what you are trying to show, you write this but it is dependent on your arrays all being sorted the same within each array. If that is not the case you can either add code to make it so or create a filter.
This is the equivalent of the c# code you have in your question.
<tr *ngFor="let row of myTable">
<td *ngFor="let col of row">
{{col.value}}
</td>
</tr>
new to this type of work , need your help
in my view .cshtml ----
<table class>
<thead>
<tr>
<th >#Html.CheckBox("IsAllRowSelected")</th>
<th >
#Html.DropDownListFor(m => m._dropDownForcolumn2, new List<SelectListItem>
{ new SelectListItem{Text="option1", Value="option1"},
new SelectListItem{Text="option2", Value="option2"},
new SelectListItem{Text="option3", Value="option3"}
}, new {#id="dropDownForcolumn2" })
</th>
<th>#Html.Label(" column 3 ")</th>
<th>#Html.Label("column 4")</th>
<th>#Html.Label("column 5")</th>
</tr>
</thead>
<tbody>
#foreach (Models.MyModelClass item in Model._List)
{
<tr>
<td>#Html.CheckBox("IsEachRowSelected")</td>
<td>#item.Option1Values</td>
#*//#item.option2values;
#item.option3vlaues;*#
<td>#item.column3value</td>
<td>#item.column4value</td>
<td>#item.column5value</td>
</tr>
}
1 .cant post back to controller again to get only this column values . its just a small table in a huge page
2 i already have the other values in item
now only option1 values are coming in the column , the requirement is to bind 2nd colmn with header dropdown and 2nd option selected then this will show #item.option2values and 3rd option selected then #item.option3values will be shown
other columns will not be changed or touched .
somthing like this
<td>
if(dropdownvalue = option1)
#item.Option1Values
elseif(dropdownvalue == option2 )
#item.option2values
elseif(dropdownvalue == option2 )
#item.option3vlaues
</td>
ajax , jquery is allowed but whole page post or partial view post is not allowed
do it like this
put onload method in table tag
function load()
{
$('.MyProperty2').hide();
$('.MyProperty3').hide();
}
function Filldropdown(){
var value = $('#dropdownID :selected').text();
if (value == 'option1') {
$('.MyProperty1').show();
$('.MyProperty2').hide();
$('.MyProperty3').hide();
} else if (value == 'option2') {
$('.MyProperty2').show();
$('.MyProperty1').hide();
$('.MyProperty3').hide();
} else if (value == 'option3') {
$('.MyProperty3').show();
$('.MyProperty2').hide();
$('.MyProperty1').hide();
}
}
I have a table of fees I am trying to parse through to return data, but it is returning a few blanks before it actually returning the string of data.
<table id="Fees">
<thead>
<tr>
<th>Rate Code</th>
<th>Description</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td class="code">A1</td>
<td>Charge Type 1</td>
<td class="amount">$11.20</td>
</tr>
<tr>
<td class="code">C2</td>
<td>Charge Type 2</td>
<td class="amount">$36.00</td>
</tr>
<tr>
<td class="code">CMI</td>
<td>Cuba Medical Insurance</td>
<td class="amount">$25.00</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Total:</td>
<td class="amount">$145.16</td>
</tr>
</tfoot>
</table>
I return by xpath
private By lst_Fee
{
get { return By.XPath("//*[#id=\"Fees\"]/tbody/tr"); }
}
Selenium code:
IList<IWebElement> fees = GetNativeElements(lst_Fee, 5);
List<string> actual = new List<string>();
foreach (IWebElement elem in fees)
{
actual.Add(GetText(elem, ControlType.Label));
}
Questions
Is ControlType.Label correct for a table? I am getting a few blank elems before actually getting to the data.
If I wanted to separate each Rate, Description and Fee out in each item to make sure the cost adds up to Total correctly, how can I do that?
I would do something like the below. I created a class Fee that holds the parts of a fee: the code, description, and amount. For each table row , you would extract these three values and store them in an instance of the Fee class. The function returns a collection of Fee instances. To get the sum of the fees themselves, you would call the GetFees() method and then iterate through the Fee instances summing the amount into the final Total.
public class Fee
{
private String code;
private String desc;
private BigDecimal amount;
private Fee(String _code, String _desc, BigDecimal _amount)
{
this.code = _code;
this.desc = _desc;
this.amount = _amount;
}
}
public List<Fee> GetFees()
{
List<Fee> fees = new ArrayList<Fee>();
List<WebElement> rows = driver.findElements(By.cssSelector("#Fees > tbody > tr"));
for (WebElement row : rows)
{
List<WebElement> cells = row.findElements(By.cssSelector("td"));
fees.add(new Fee(cells.get(0).getText(), cells.get(1).getText(), parse(cells.get(2).getText(), Locale.US)));
}
return fees;
}
// borrowed from http://stackoverflow.com/a/23991368/2386774
public BigDecimal parse(final String amount, final Locale locale) throws ParseException
{
final NumberFormat format = NumberFormat.getNumberInstance(locale);
if (format instanceof DecimalFormat)
{
((DecimalFormat) format).setParseBigDecimal(true);
}
return (BigDecimal) format.parse(amount.replaceAll("[^\\d.,]", ""));
}
You can grab all the column headers and as well the row data by the below code:
Happy coding =
//// Grab the table
IWebElement grid;
grid = _browserInstance.Driver.FindElement(By.Id("tblVoucherLookUp"));
IWebElement headercolumns = grid.FindElement(By.Id("tblVoucherLookUp"));
_browserInstance.Driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(75));
_browserInstance.ScreenCapture("Voucher LookUp Grid");
//// get the column headers
char[] character = "\r\n".ToCharArray();
string[] Split = headercolumns.Text.Split(character);
for (int i = 0; i < Split.Length; i++)
{
if (Split[i] != "")
{
_log.LogEntry("INFO", "Voucher data", true,
Split + " Text matches the expected:" + Split[i]);
}
}
I have been trying to scrape some data off a website. The source has differentiated all the headers of tables to that of the actual contents by different class names. Because I want to scrape all the table information, I got all the headers into one array and contents into another array. But the problem is that when I am trying to write the array contents into a file, I can write a header but second array contains contents from all the table and I cannot mark where contents of first table ends.
Because htmlagilitypack scrapes all the tags of specified Nodes, I get all the contents. First let me show the code to make it clear:
<tr class=tableHeader>
<th width=16%>Caught</th>
<th width=16%><p>Normal Range</p></th>
</tr>
<TR class=content><TD><i>Bluegill</i></TD>
<TD>trap net</TD>
<TD align=CENTER>4.05</TD>
<TD align=CENTER> 7.9 - 37.7</TD>
<TD align=CENTER>0.26</TD>
<TD align=CENTER> 0.1 - 0.2</TD>
</TR>
<TR class=content><TD><i></i></TD>
<TD>Gill net</TD>
<TD align=CENTER>1.50</TD>
<TD align=CENTER>N/A</TD>
<TD align=CENTER>0.07</TD>
<TD align=CENTER>N/A</TD>
</TR>
<tr class=tableHeader>
<th>0-5</th>
<th>6-8</th>
<th>9-11</th>
<th>12-14</th>
<th>15-19</th>
<th>20-24</th>
<th>25-29</th>
<th>30+</th>
<th>Total</th>
</tr>
<TR class=content><TD><i>bluegill</i></TD>
<TD align=CENTER>19</TD>
<TD align=CENTER>65</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>84</TD>
</TR>
Below is my code to save the headers and contents into array and try to display it exactly like in the website.
int count =0;
foreach (var trTag4Pale in trTags4Pale)
{
string trText4Pale = trTag4Pale.InnerText;
paleLake[count] = trText4Pale;
if (trTags4Small != null)
{
int counter = 0;
foreach (var trTag4Small in trTags4Small)
{
string trText4Small = trTag4Small.InnerText;
smallText[counter] = trText4Small;
counter++;
}
}
File.AppendAllText(path,paleLake[count]+Environment.Newline+smallText[count]+Environment.Newline);
}
As you see, When I try to append the contents of the array to a file, it lines in the first header, and contents of all the table. But I only want contents of the first table and would repeat the process to get the content of the second table and so forth.
If I could get the contents between tr tag tableHeader, the arrays for the content would contain every contents for all the tables in different arrays. I don't know how to do this.
This might not be the best approach but I made it work somehow. It might be useful resource for somebody someday. So below is the code that worked for me. I append the data stored in the list into an excel sheet. As I have all the data I need for each tr tag with each class, I can manipulate the data I want:
var trTags4Header = document.DocumentNode.SelectNodes("//tr[#class='tableheader']");
if (trTags4Header != null)
{
//Create a list to store td values
List<string> tableList1 = new List<string>();
int row = 2;
foreach (var item in trTags4Header)
{
//Get only next siblings which matches the calss name as "content"
var found = item.SelectNodes("followin-sibling::*").TakeWhile(tag => tag.Name == "tr" && tag.Attributes["class"].Value == "content");
//store the nodes selected in an array (this is the selection of nodes I wanted which has td information I want.
HtmlNode[] nextItem = found.ToArray();
foreach (var node in nextItem)
{
//Gets individual td values within tr class='content' Notice .//td- this starts looking from the present node instead of the root nodes.
var tdValues = node.SelectNodes(".//td").TakeWhile(tdTag => tdTag.Name == "td");
int column = 1;
//Stores each td values into the list which is why I have control over the data to where I want to store, I am storing them in one excel worksheet.
foreach (var tdText in tdValues)
{
tableList1.Add(tdText.InnerText);
ws1.Cells[row, column] = tdText.InnerText;
column++;
}
row++;
}
}
//Display the content in a listbox
listBox1.DataSource = tableList1;
}
Please suggest a better solution if you come across this or leave your feedback. Thanks
I wrote the below code for finding the records in a table grid.
$(function () {
grid = $('#tblsearchresult');
// handle search fields key up event
$('#search-term').keyup(function (e) {
text = $(this).val(); // grab search term
if (text.length > 1) {
// iterate through all grid rows
grid.find('tr').each(function (i) {
if ($(this).find('td:eq(1)').text().toUpperCase().match(text.toUpperCase()))
$(this).css({ background: "#A4D3EE" });
});
}
else {
grid.find('tr:has(td)').css({ background: "" });
grid.find('tr').show();
} // if no matching name is found, show all rows
});
});
<table id="tblsearchresult" class="tablesorter"">
<thead>
<tr>
<th>ApplicationName</th>
</tr>
</thead>
<tbody>
<% foreach (var request in Model.ApplicationRoles)
{ %>
<tr>
<td>
<span id="appName_<%: request.Id%>">
<%: request.Application.Name%></span>
</td>
</tr>
</tbody>
</table>
EDIT Table Data
applicationame role
application1 appadministrator
app developer
application2 tester
if i given 'app'as search text need to highlight secondrow only .highlightling firstrow also because 'app' is there in role of firstrow..exact match should be highlight on every rows.please tell me.
Your code is behaving correctly. Just that you need to clear all previously highlighted rows on "keyup" of input text first.
if (text.length > 1) {
grid.find('tr:has(td)').css({ background: "" });
grid.find('tr').show();
......rest of your code.......
You need to clear the highlight before you parse. Add this statement of yours:
grid.find('tr:has(td)').css({ background: "" });
before entering this loop:
// iterate through all grid rows
grid.find('tr').each(function (i) {
...
});
Check this fiddle: http://jsfiddle.net/F3jRj/1/
And this updated fiddle with 3 columns: http://jsfiddle.net/F3jRj/2/