2

I have a html page that has a section which is structured like this:

<section id="fl-results" class="fl-results-revenue">
 <li data-tab="details" class="ui-state-default ui-corner-top" role="tab">
  <a class="toggle-flight-block-details ui-tabs-anchor" href="#flight-details-1" tabindex="-1" id="ui-id-3">Details</a>
 </li>
 <!-- Some html -->
 <li data-tab="details" class="ui-state-default ui-corner-top" role="tab">
  <a class="toggle-flight-block-details ui-tabs-anchor" href="#flight-details-2" tabindex="-1" id="ui-id-5">Details</a>
 </li>
 <!-- Some html -->
 <li data-tab="details" class="ui-state-default ui-corner-top" role="tab">
  <a class="toggle-flight-block-details ui-tabs-anchor" href="#flight-details-3" tabindex="-1" id="ui-id-8">Details</a>
 </li>
 <!-- Some html -->
 <li data-tab="details" class="ui-state-default ui-corner-top" role="tab">
  <a class="toggle-flight-block-details ui-tabs-anchor" href="#flight-details-4" tabindex="-1" id="ui-id-19">Details</a>
 </li>
</section>

Now i want to click all the links for details with the section with id fl-results. In my code, I wait for the elements to be clickable, which is working, then try to click them all:

wait.until(ExpectedConditions.elementToBeClickable(By.className("toggle-flight-block-details")));

When I tried the code below, it only opens clicks the first occurrence of the link:

driver.findElement(By.className("toggle-flight-block-details")).click();

I saw a post suggesting to use cssSelector

driver.findElement(By.cssSelector("a[href*='flight-details-1']")).click();

This requires me iterating through all the links with such a class. The iteration works but the clicking gives me an error

//loop through page and click all link details
List<WebElement> allLinksWebpage = driver.findElements(By.className(waitCondition));
int k = allLinksWebpage.size();
for(int i=0;i<k;i++)
{
    if(allLinksWebpage.get(i).getAttribute("href").contains("flight-details"))
    {
        String waitCondition = "flight-details-"+(i+1);
        String link = allLinksWebpage.get(i).getAttribute("href");
        driver.findElement(By.cssSelector("a[href*='"+waitCondition+"']")).click();
    }
}

Error given is:

Exception in thread "main" org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element ... is not clickable at point (392, 730). Other element would receive the click: ...

I saw a post regarding a similar error and it says to use javascript instead because it has something to do with chrome, but I do not know how to implement that in my case?

I am using google chrome driver Version 83.0.4103.97.

The HTML page I am viewing is that of flight search results from United Airline

gunner
  • 89
  • 4

2 Answers2

1

You can get all the web elements which contain class name toggle-flight-block-details within section web element using;

WebElement section = driver.findElement(By.id("fl-results"));
List<WebElement> detailsList = section.findElements(By.className("toggle-flight-block-details"));

Then you can iterate through the detailsList and click on them using JavascriptExecutor

JavascriptExecutor js = (JavascriptExecutor) driver;
for (int i = 0; i <detailsList.size(); i++) {
    js.executeScript("arguments[0].click();", detailsList.get(i));
}
kaweesha
  • 803
  • 6
  • 16
  • Thanks, this worked. At first it was not and I realized because the `detailsList.size()` was 0. So I added the wait condition `wait.until(ExpectedConditions.elementToBeClickable(By.className("toggle-flight-block-details")));` and it worked perfect! – gunner Jun 13 '20 at 16:18
1

Instead of this line:

List<WebElement> allLinksWebpage = driver.findElements(By.className(waitCondition));

#Update here

The other approach use this css selector : section#fl-results li a.toggle-flight-block-details, collect them into a list with wait using .visibilityOfAllElementsLocatedBy.

Extract with for each:

WebDriverWait wait = new WebDriverWait(driver, 20);
//update here
List<WebElement> allLinksWebpage = wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("section#fl-results li a.toggle-flight-block-details")));
for(WebElement element: allLinksWebpage) {
    if(element.getAttribute("href").contains("flight-details")) {
        ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
        wait.until(ExpectedConditions.elementToBeClickable(element));
        ((JavascriptExecutor) driver).executeScript("arguments[0].click();", element);
    }
}

See the above how to implement arguments[0].click(); using JavascriptExecutor.

You need following import:

import org.openqa.selenium.JavascriptExecutor;

But I imagine each click on the Details link, the detail information appear and make the page structure change, so the next Details go to bottom, before click put this argument arguments[0].scrollIntoView(true);

frianH
  • 7,295
  • 6
  • 20
  • 45
  • Hi, the answer looks interesting. but having tried it, it still gives me the error: _Expected condition failed: waiting for visibility of all elements located by By.cssSelector: section#fl-results > li > a_. See error details [here](https://ibb.co/bv8FKBQ). The html page i am viewing is that of flight search results from [United Airline](https://www.united.com/en/us) – gunner Jun 13 '20 at 16:00
  • @gunner You incorrectly showed the HTML structure in the question, unlike the original page, between `section` and `li` there are other tags, so the previous ccs selector will not work. I've updated answer, changed css selector **`section#fl-results > li > a`** to be **`section#fl-results li a.toggle-flight-block-details`**. Hope this helps. – frianH Jun 14 '20 at 00:32