Gunes K
Gunes K

Reputation: 21

Select items from 3 dropdowns with dependency of first one

What I want to do is: 1- Going to this site: http://www.emlakyonetim.com.tr/tr-TR/sitelerimiz , 2- Click on first dropdown - click a city, click second dropdown - click a county, click third dropdown.

At short, second dropdown items are dependant on first one and third dropdown items are dependant on second one.

Code (not complete):

@Test
public void SiteCek() throws InterruptedException
{
    driver.get("http://www.emlakyonetim.com.tr/tr-TR/sitelerimiz");
    Thread.sleep(2000);

    driver.findElement(By.id("select2-city-list-container")).click();

    List<WebElement> elm = driver.findElements(By.xpath("//*[@class='select2-results__option']"));

    for(int i = 1; i < elm.size(); i++) 
    {   
            By ID = By.id(driver.findElements(By.xpath("//*[@class='select2-results__option']")).get(i).getText());
            System.out.println(ID);         

            driver.findElements(By.xpath("//*[@class='select2-results__option']")).get(i).click();
            Thread.sleep(500);
    } 
}

I get java.lang.IndexOutOfBoundsException: Index: 2, Size: 0 error after city "ADANA". If I manage to handle first error, I will write second and third for loops, so code is this for now.

When the issue is solved I want to get all cities first. Then countys of each city. Then sites of each county. This must be done dynamically as the size of city list, county list and site list. To do that I need three nested for loops. After all of that, each value must be written in excel.

Upvotes: 1

Views: 345

Answers (1)

Vladimir Efimov
Vladimir Efimov

Reputation: 799

here is the code that worked for me

 public void testMethod() {
    driver.manage().window().maximize();

    WebElement firstDropDown = driver.findElement(By.id("select2-city-list-container"));
    firstDropDown.click();
    sleep();
    List<WebElement> citiesEls = getCitiesEls();
    Map<String, Map<String, List<String>>> cityData = new HashMap<>();
    for (int i = 0; i < citiesEls.size(); i++) {
        //we need to take this element every iteration, because it gets reloaded every time we open the dropdown
        WebElement cityEl = driver.findElement(By.id("select2-city-list-results")).findElements(By.xpath("//*[contains(@id,'select2-city-list-result')]")).get(i);
        String cityText = cityEl.getText();
        cityEl.click();
        sleep();

        cityData.put(cityText, getRegions());

        firstDropDown.click();
        sleep();
    }

    System.out.println(cityData);
}

private Map<String, List<String>> getRegions() {
    WebElement secondDropDown = driver.findElement(By.id("select2-region-list-container"));
    secondDropDown.click();
    sleep();
    List<WebElement> regionsEls = getRegionEls();
    Map<String, List<String>> regionData = new HashMap<>();
    for (int i = 0; i < regionsEls.size(); i++) {
        WebElement regionEl = driver.findElement(By.id("select2-region-list-results")).findElements(By.xpath("//*[contains(@id,'select2-region-list-result')]")).get(i);
        String regionText = regionEl.getText();
        regionEl.click();
        WebElement thirdDropDown = driver.findElement(By.id("select2-site-list-container"));
        thirdDropDown.click();
        List<WebElement> sitesEl = getSiteEls();
        List<String> sitesTexts = getSites(sitesEl);
        //populate region data
        regionData.put(regionText, sitesTexts);

        secondDropDown.click();
        sleep();
    }
    return regionData;
}

private List<String> getSites(List<WebElement> sitesEl) {
    List<String> sitesTexts = new ArrayList<>();
    for (WebElement siteEl : sitesEl) {
        sitesTexts.add(siteEl.getText());
    }
    return sitesTexts;
}

private List<WebElement> getSiteEls() {
    WebElement ulSites = driver.findElement(By.id("select2-site-list-results"));
    return ulSites.findElements(By.xpath("//*[contains(@id,'select2-site-list-result')]"));
}

private List<WebElement> getRegionEls() {
    return driver.findElement(By.id("select2-region-list-results")).findElements(By.xpath("//*[contains(@id,'select2-region-list-result')]"));
}

private List<WebElement> getCitiesEls() {
    return driver.findElement(By.id("select2-city-list-results")).findElements(By.xpath("//*[contains(@id,'select2-city-list-result')]"));
}

As data is dynamically changed after each click, you might need some delays after each click. The code below worked well on Mac+Chrome. Nevertheless, if it fails from you end do add a sleep method call after each click.

  private void sleep() {
      try {
          Thread.sleep(1000);
      } catch (InterruptedException e) {
          throw new IllegalStateException(e);
      }
    }

Important note: Sleeps are not recommended to use, and should be used only as the quick temporary workaround. More robust solution is to use smart waits

Upvotes: 1

Related Questions