Reputation: 2402
There is HTML table on web page. I am trying to go through each link it has and find certain words inside href elements. Let's say I need to find "car", "house", "city". If any of these words exist in links text I want selenium to proceed to each link that will match the criteria and perform some other things on sub pages (I have the rest of the code for sub pages operations).
HTML Table XPath: //*[@id="datatable"]
I probably need to use something like?
List<string> matchingLinks = new List<string>();
ReadOnlyCollection<IWebElement> links = driver.FindElements(By.TagName("a"));
// LINQ is better?
foreach (IWebElement link in links)
{
string text = link.Text;
if (Regex.IsMatch("car", text))
{
matchingLinks.Add(text);
}
}
foreach (string linkText in matchingLinks)
{
IWebElement element = driver.FindElement(By.LinkText(linkText));
element.Click();
driver.Navigate().Back();
}
However this does not take in consideration my table. Also how to assign more "search words" in addition to "car"?
Links XPath (as you can see only tr[7] is changing according to row):
//*[@id="datatable"]/tbody/tr[1]/td[3]/a
...
//*[@id="datatable"]/tbody/tr[7]/td[3]/a
...
//*[@id="datatable"]/tbody/tr[11]/td[3]/a
//*[@id="datatable"]/tbody/tr[12]/td[3]/a
EDIT:
Example:
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using System;
namespace Tenders_Collection_Robot
{
public static class WebDriverExtensions
{
public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
return wait.Until(drv => drv.FindElement(by));
}
return driver.FindElement(by);
}
}
class Program
{
static void Main(string[] args)
{
// declare chrome options with prefs
var options = new ChromeOptions();
// options.AddArguments("headless"); // we add headless here
options.AddUserProfilePreference("download.default_directory", "C:\\temp\\downloadfolder");
options.AddUserProfilePreference("plugins.always_open_pdf_externally", true);
var r = new Random();
// Initialize the Chrome Driver // chromeOptions
using (var driver = new ChromeDriver(options))
{
// Go to the home page
driver.Navigate().GoToUrl("https://html.com/tables/");
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(15);
ClickTableLink("col");
}
}
public static void ClickTableLink(String value)
{
var driver = new ChromeDriver();
var table = driver.FindElement(By.ClassName("related-elements"));
foreach (var tr in table.FindElements(By.TagName("tr")))
{
var tds = tr.FindElements(By.TagName("a"));
for (var i = 0; i < tds.Count; i++)
{
if (tds[i].Text.Trim().Contains(value))
{
tds[i].Click();
break;
}
}
}
}
}
}
Upvotes: 0
Views: 209
Reputation: 1551
Throwing some ideas out at you Hatman.
In reference to your first function....
You could pass the value for "name" and then...
using System.Linq;
using System.Collections.Generic;
List<String> item = new List<string>();
IReadOnlyList<IWebElement> cells = driver.FindElements(By.TagName("a"));
foreach (IWebElement cell in cells)
{
item.Add(cell.Text);
}
Then run an assert that any of the found "a" values contain the text?
Assert.IsTrue(item.Any(itm => itm.Contains(name)));
Also here is something else you could try? In the below, "value" could be any unique value you search on like, email, name, account number. "Value" is = i. So if your link is two columns to the right of i, you could say click on tds[i+2].Click();. If the link you want to click is three columns to the left of i, tds[i-3].Click(); You could also grab the text from here and assert accordingly.
public void ClickTableLink(String value)
{
var table = driver.FindElement(By.Id("table"));
foreach (var tr in table.FindElements(By.TagName("tr")))
{
var tds = tr.FindElements(By.TagName("a"));
for (var i = 0; i < tds.Count; i++)
{
if (tds[i].Text.Trim().Contains(value))
{
tds[i].Click();
break;
}
}
}
}
Here is another example.....
<table id="mytable">
<tr>
<th>Name</th> <th> Link1</th> <th>Favorite Color</th> <th>Link2</th>
</tr>
<tr>
<td>Bob</td>
<td><a href="https://foxnews.com">Fox</a></td>
<td>Yellow</td>
<td><a href="https://cnn.com">CNN</a> </td>
</tr>
<tr>
<td>Jim</td>
<td><a href="https://foxnews.com">News1</a></td>
<td>Blue</td>
<td><a href="https://cnn.com">News2</a> </td>
</tr>
<tr>
</tr>
</table>
This will look for "Bob" and grab the text off of the link and verify it matches value2.
var value = "Bob";
var value2 = "Fox";
var table = Browser.FindElement_byId("mytable");
foreach (var tr in table.FindElements(By.TagName("tr")))
{
var tds = tr.FindElements(By.TagName("td"));
for (var i = 0; i < tds.Count; i++)
{
if (tds[i].Text.Trim().Contains(value))
{
var test = tds[i + 1].Text.Trim();
Assert.IsTrue(test.Contains(value2));
break;
}
}
}
Upvotes: 1