Reputation: 1339
I'm using Selenium
for download some data from the site, in particular this is the url.
As you can see there are two tabs:
I'm trying to access to the 1st Half
content by simulating a click on it through Selenium
, this is my 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/usa/mls/chicago-fire-new-york-city-CAl0LCJs/?r=1#ah;2"));
driver.FindElement(By.XPath("//*[contains(text(),'1st') and contains(text(),'Half')]")).Click();
string html = driver.PageSource;
the problem is that I get this error:
OpenQA.Selenium.ElementNotVisibleException: 'element not visible
I though that my XPath
is wrong, but I tried with other tabs and works, also the html
structure is correct.
What's happening?
Upvotes: 0
Views: 913
Reputation: 445
You have the unique ID bettype-tabs-scope
, and there is ul
and 3 li
elements.
<div id="bettype-tabs-scope" class="tab-nav-detail">
<ul class="sub-menu subactive" style="display: block;">
<li class=" active"><span class="topleft_corner"></span><span class="topright_corner"></span><strong><span>Full Time</span></strong></li>
<li class=""><a onmousedown="uid(28)._onClick();return false;" title="1st Half" href=""><span>1st Half</span></a></li>
<li class="last"><a onmousedown="uid(29)._onClick();return false;" title="2nd Half" href=""><span>2nd Half</span></a></li>
</ul>
</div>
You can pretty easily do:
//Find the unique element and the get all children list items.
var listItems = driver.FindElement(By.Id("bettype-tabs-scope")).FindElements(By.TagName("li"));
//Click the list items that has "1st Half" as it's text.
listItems.Where(li => li.Text == "1st Half").Single().Click();
Otherwise, you can also do driver.FindElement(By.Id("bettype-tabs-scope")).FindElements(By.TagName("li"))[1].Click();
if you are certain that the "1st half" button will always be second in the results (first being the Full Time).
Upvotes: 1
Reputation: 2334
There are two elements are found with same xpath and the first element is invisible. In your code, you have used the FindElement
method and hence it is finding the invisible element returning an error.
Solution: You can perform the click action in two ways.
Option 1:
Change the Xpath as //*[contains(text(),'1st') and contains(text(),'Half')][1]
driver.FindElement(By.XPath("//*[contains(text(),'1st') and contains(text(),'Half')][1]")).Click();
Option 2:
Find all the matched elements using FindElements
method and then perform the click action only, If the particular element is disaplyed
var halfElementList = driver.FindElements(By.XPath("//*[contains(text(),'1st') and contains(text(),'Half')]"));
string html = "";
foreach(var element in halfElementList)
{
if (element.Displayed)
{
element.Click();
html = driver.PageSource;
}
}
Upvotes: 0
Reputation: 732
It should work as it works fine on my machine. Maybe page load is taking time on your machine. You can use expected condition wait for checking the visibility of the element. Make sure you've installed both the Selenium. Webdriver and Selenium.Support NuGet packages for your project. You'll need the Selenium. Support package to use ExpectedConditions.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60));
IWebElement element = wait.Until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'1st') and contains(text(),'Half')]")));
element.Click();
Upvotes: 0