Selenium Webdriver can't find table elements - c#

I'm new with selenium, I can not figure out how to find some elements from an HTML page.
I reproduced the page here :
http://www.ladiana.it/test/test.htm
I need to click on this button :
Selection
and after the table appears, to read and write their values :
values
I'm using c# and I tried all possible way, I also tried to list all the elements with the Id
: "targetDemandReductionMW"
IList IWebElement> all = driver2.FindElements(By.Id("targetDemandReductionMW"));
I get a list of 52 void elements.
Here some other code , it doesn't generate any error but didn't work:
IWebElement element_xpath = driver2.FindElement(By.ClassName("tab_buttonSel"));
element_xpath.Click();
IWebElement table = driver2.FindElement(By.Id("drr1OfferAM"));
var rows = table.FindElements(By.TagName("tr"));
int conteggio = 0;
foreach (var row in rows)
{
var rowTds = row.FindElements(By.TagName("td"));
foreach (var td in rowTds)
{
IWebElement a = td.FindElement(By.XPath("//*[#id='targetDemandReductionMW']"));
Console.WriteLine(conteggio++.ToString()+" "+a.GetAttribute("href")+" "+ a.Text);
}
}
Any help?
Thanks

For the button you need to click, you can use:
//div[#id='tabContainer']/div[2]/following::tr/td[text()='DRR1 Offer']
For the xpath for the table records you can use:
//table[#id='drr1OfferPMHead']//td[#id='targetDemandReductionMW']
This returns the 13 rows that you are looking for. You can then do FindElements on this and get a list.
List<String> search = new List<string>();
IReadOnlyList<IWebElement> cells = driver.FindElements(By.Xpath("//table[#id='drr1OfferPMHead']//td[#id='targetDemandReductionMW']"));
foreach (IWebElement cell in cells)
{
search.Add(cell.Text);
}

The cell (in the html) has cellclick event , but if i try with :
foreach (IWebElement cell in cells)
{
search.Add(cell.Text);
if (cell.Text=="300.0")
{
cell.click();
}
}
it come out this error : "OpenQA.Selenium.ElementNotInteractableException: 'element not interactable"

Related

c# selenium | how to get values ​in table same column

I wrote a code to list the names of the wordpress categories. But I was not successful. The category names column is marked in red.
https://i.stack.imgur.com/NnLk1.jpg
this is the code I wrote:
var table = driver.FindElement(By.TagName("tbody"));
var rows = table.FindElements(By.TagName("tr"));
foreach (var row in rows)
{
IList<IWebElement> satirlar = row.FindElements(By.TagName("td"));
foreach (var satir in satirlar)
{
var a = satir.Text;
listBox1.Items.Add(a);
}
}
output:
https://i.stack.imgur.com/zzWgb.jpg
I just want to list the category names. but the number of articles in the category and the short name of the category are listed. I don't want this to happen. Only category names should be listed. Can you help me please?
Try this:
var a=satir.FindElement(By.CssSelector("a.row-title")).Text;

Selenium C# Tables - reading each values and adding them and Returning as List<string>

I can able to read the table values BUT Im unable to add the values inside foreach loop and returning them as List<string>.
Please share your approach and Will be great helpful
IWebElement tableElement = driver.FindElement(By.XPath("//div[#id='table']"));
IList<IWebElement> tableRow = tableElement.FindElements(By.TagName("tr"));
IList<IWebElement> rowTD;
foreach (IWebElement row in tableRow)
{
rowTD = row.FindElements(By.TagName("td"));
//add the values in list??
}
return list
After this how can I add the td text values into an List<string>? I want this function to return the list.
I'm guessing that you are trying to return all of the table data elements as a list of strings.
If you want to stick with a similar approach of only getting the text of the td elements, then I would do something like this:
IWebElement tableElement = driver.FindElement(By.XPath("//div[#id='table']"));
IList<IWebElement> tableDataElements = tableElement.FindElements(By.TagName("td"));
var reults = new List<string>();
foreach (IWebElement tableDataElement in tableDataElements)
{
var tableData = tableDataElement.Text;
reults.add(tableData);
}
return reults;
You can combine Michiel's answer with LINQ to do this even more concisely--without a foreach loop at all:
First, add
using System.Linq;
Then, you can replace your entire code block with:
return driver.FindElement(By.XPath("//div[#id='table']"))
.FindElements(By.TagName("td"))
.Select(e => e.Text)
.ToList();

Cannot get a tag in a specific html element

I'm trying to get a list of links available inside the tag ul of this site.
The link that I'm trying to get are available inside: More bets, specifically:
all this links are located in a ul tag, as I said before, within a div which have as id bettype-tabs.
I wrote this code:
var chromeOpts = new ChromeOptions();
chromeOpts.AddArguments("headless");
var chromeDriverService = ChromeDriverService.CreateDefaultService();
driver = new ChromeDriver(chromeDriverService, chromeOpts);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
driver.Navigate().GoToUrl(new Uri("http://www.oddsportal.com/soccer/mexico/copa-mexico/cafetaleros-de-tapachula-atletico-san-luis-fcfIQtLo/?r=1#ah;2"));
var listItems = driver.FindElement(By.Id("bettype-tabs"))?.FindElements(By.TagName("li"));
foreach(var c in listItems)
{
Console.WriteLine(c.Text);
}
listItems.Where(li => li.Text == "HT/FT" || li.Text == "Half Time / Full Time").Single().Click();
now the last line will return:
Sequence contains no elements
infact the foreach print:
so why the link inside More bets aren't in the list?
How can I handle this situation?
Try Below for getting the link under More Bets :
var listItems = driver.FindElement(By.Id("bettype-tabs"))?.FindElements(By.TagName("p"))?.FindElements(By.TagName("a"));
foreach(var c in listItems)
{
Console.WriteLine(c.GetAttribute("innerHTML"));
}
Instead of :
var listItems = driver.FindElement(By.Id("bettype-tabs"))?.FindElements(By.TagName("li"));
use this :
var listItems = driver.FindElement(By.CssSelector("div#bettype-tabs li"));
and loop it like you have done it.
and if you want to click on any specific element then :
foreach(var c in listItems)
{
if(c.Text.Trim().Contains("DC")){
c.Click()
}
}

Merge to IList<IWebElement> element into a Dictionary

I'm trying to create a dictionary from a two IWebelement that I obtain from selenium, the first element is the header of a table and the second one is the value of each column. It's possible to do it?
This are my two Ilist:
IList<IWebElement> headersrows = tableheaders.FindElements(By.XPath("tr"));
IList<IWebElement> resultsrows = tableresults.FindElements(By.XPath("tr"));
And I do a for to get all the elements from each of the list:
IList<IWebElement> columnsTable;
foreach (IWebElement row in resultsrows)
{
columnsTable = row.FindElements(By.TagName("td"));
}
IDictionary<IWebElement, IList<IWebElement>> dict = new Dictionary<IWebElement, IList<IWebElement>>();
int index = 0;
foreach (var header in headersRows.SelectMany(r => r.FindElements(By.XPath("th"))))
{
dict.Add(header, resultsRows.Select(r => r.FindElements(By.TagName("td"))[index]).ToList());
index++;
}
This will give you a dictionary where the key is the th element, and the values are a list of td elements containing the values for the column.

Get all <td> title of a table column with coded ui

I need to check a filter function on a table.
This filter is only on the first cell of each row and I'm trying to figure out how to get all those values...
I tried with something like
public bool CheckSearchResults(HtmlControl GridTable, string FilterTxt)
{
List<string> Elements = new List<string>();
foreach (HtmlCell cell in GridTable.GetChildren())
{
Elements.Add(cell.FilterProperties["title"]);
}
List<string> Results = Elements.FindAll(l => l.Contains(FilterTxt));
return Results.Count == Elements.Count;
}
but I get stuck at the foreach loop...
maybe there's a simply way with linq, but i don't know it so much
edit:
all the cells i need have the same custom html tag.
with this code i should get them all, but i don't know how to iterate
HtmlDocument Document = this.UIPageWindow.UIPageDocument;
HtmlControl GridTable = this.UIPageWindow.UIPageDocument.UIPageGridTable;
HtmlCell Cells = new HtmlCell(GridTable);
Cells.FilterProperties["custom_control"] = "firstCellOfRow";
also because there's no GetEnumerator function or query models for HtmlCell objects, which are part of Microsoft.VisualStudio.TestTools.UITesting.HtmlControl library -.-
edit2:
i found this article and i tried this
public bool CheckSearchResults(string FilterTxt)
{
HtmlDocument Document = this.UIPageWindow.UIPageDocument;
HtmlControl GridTable = this.UIPageWindow.UIPageDocument.UIPageGridTable;
HtmlRow rows = new HtmlRow(GridTable);
rows.SearchProperties[HtmlRow.PropertyNames.Class] = "ui-widget-content jqgrow ui-row-ltr";
HtmlControl cells = new HtmlControl(rows);
cells.SearchProperties["custom_control"] = "firstCellOfRow";
UITestControlCollection collection = cells.FindMatchingControls();
List<string> Elements = new List<string>();
foreach (UITestControl elem in collection)
{
HtmlCell cell = (HtmlCell)elem;
Elements.Add(cell.GetProperty("Title").ToString());
}
List<string> Results = Elements.FindAll(l => l.Contains(FilterTxt));
return Results.Count == Elements.Count;
}
but i get an empty collection...
Try Cell.Title or Cell.GetProperty("Title"). SearchProperties and FilterProperties are only there for searching for a UI element. They either come from the UIMap or from code if you fill them out with hand. Otherwise your code should should work.
Or you can use a LINQ query (?) like:
var FilteredElements =
from Cell in UIMap...GridTable.GetChildren()
where Cell.GetProperty("Title").ToString().Contains(FilterTxt)
select Cell;
You could also try to record a cell, add it to the UIMap, set its search or filter properties to match your filtering, then call UIMap...Cell.FindMatchingControls() and it should return all matching cells.
The problem now is that you are limiting your search for one row of the table. HtmlControl cells = new HtmlControl(rows); here the constructor parameter sets a search limit container and not the direct parent of the control. It should be the GridTable if you want to search all cells in the table. Best solution would be to use the recorder to get a cell control then modify its search and filter properties in the UIMap to match all cells you are looking for. Tho in my opinion you should stick with a hand coded filtering. Something like:
foreach(var row in GridTable.GetChildren())
{
foreach(var cell in row.GetChildren())
{
//filter cell here
}
}
Check with AccExplorer or the recorder if the hierarchy is right. You should also use debug to be sure if the loops are getting the right controls and see the properties of the cells so you will know if the filter function is right.
I resolved scraping pages html by myself
static public List<string> GetTdTitles(string htmlCode, string TdSearchPattern)
{
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(htmlCode);
HtmlNodeCollection collection = doc.DocumentNode.SelectNodes("//td[#" + TdSearchPattern + "]");
List<string> Results = new List<string>();
foreach (HtmlNode node in collection)
{
Results.Add(node.InnerText);
}
return Results;
}
I'm freakin' hating those stupid coded ui test -.-
btw, thanks for the help

Categories