7

The class Selenium Select has 3 methods of different option selection:

  1. selectByIndex
  2. selectByValue
  3. selectByVisibleText

Now, I have a situation where I want to select an option by some text that partially appear in one of the options visible text (don't want to expose myself to changes in the WHOLE text).

For example:

<option value="0" label="not-intresting">VERY-LONG-TEXT-THAT-I-NEED-TO-SELECT-DOLLAR</option>

And i want to select this option only by providing the "DOLLAR", something like:

select.selectByPartOfVisibleText("DOLLAR") 

How would you implement it effectively?

Johnny
  • 14,397
  • 15
  • 77
  • 118
  • If only partial text is visible and you can use regex then see this question - http://stackoverflow.com/questions/28817563/python-selenium-select-dropdown-option-with-value-matching-regex – LittlePanda Apr 21 '15 at 12:33

8 Answers8

8

My solution is to use xpath to find options that are children of the select. Any xpath method can be used to find the select; in this example I am finding the select by id.

List<WebElement> options = driver.findElements(By.xpath("//select[@id = 'selectId')]/option"));

for (WebElement option : options) {
    if (option.getText().contains("DOLLAR")) {
        option.click();
        break;
    }
}

After a little more thought I realize the option can be found entirely with xpath:

driver.findElements(By.xpath("//select[@id = 'selectId')]/option[contains(text(), 'DOLLAR')]")).click();
Cash_m
  • 81
  • 1
  • 4
  • Why there is a parenthesis after 'selectId'? – bfhaha Jul 01 '21 at 16:27
  • I used the following code in python. Note that the quotation marks. driver.find_element_by_xpath("//select[@id = 'selectId']/option[contains(text(), '" + myVariable + "')]").click() – bfhaha Jul 01 '21 at 16:53
5

You can try a logic like this hope this helps

List <WebElements> optionsInnerText= driver.findElements(By.tagName("option"));
for(WebElement text: optionsInnerText){
    String textContent = text.getAttribute("textContent");
    if(textContent.toLowerCase.contains(expectedText.toLowerCase))
           select.selectByPartOfVisibleText(expectedText);
    }
}
NarendraR
  • 7,577
  • 10
  • 44
  • 82
Zach
  • 986
  • 7
  • 19
  • This might work if the option had the `text-content` attribute but in the OP's case, it doesn't. – LittlePanda Apr 21 '15 at 12:46
  • Inspect the Element and view the DOM Panel you'll find all attributes including textContent – Zach Apr 21 '15 at 12:51
  • Thanks, that is something like what I needed. Just instead of text.getAttribute("textContent") part I think element.getText should be used. – Johnny Apr 21 '15 at 13:59
3

Using Java 8 Stream/Lambda:

protected void selectOptionByPartText(WebElement elementAttr, String partialText) {
        Select select = new Select(elementAttr);
        select.getOptions().parallelStream().filter(option -> option.getAttribute("textContent").toLowerCase().contains(partialText.toLowerCase()))
                .findFirst().ifPresent(option -> select.selectByVisibleText(option.getAttribute("textContent")));
    }
Saikat
  • 14,222
  • 20
  • 104
  • 125
  • 2
    Works great. Although if you don't want to filter through every option on the page, and just want to search inner text, you can try: `protected void selectOptionByPartText(WebElement select, String partialText) { Select s = new Select(select); s.getOptions() .stream() .filter(option -> option.getText().toLowerCase().contains(partialText.toLowerCase())) .findFirst() .ifPresent(option -> s.selectByValue(option.getAttribute("value"))); }` – Atom999 Feb 19 '19 at 21:14
2

In latest Selenium version 3.x or 4.x, Select class can be used to select an option from dropdown.

For example: There is a flavour dropdown where it require to select a flavour which contain name as Vanilla.

WebElement flavour = driver.findElement(By.id("attribute178"));
Select select = new Select(flavour);
String expectedFlavourName = "Vanilla";
List<WebElement> allFlavourList = select.getOptions();
for (WebElement option : allFlavourList) {
    String currentFlavourName = option.getText();
    if (currentFlavourName.contains(expectedFlavourName)) {
        select.selectByVisibleText(currentFlavourName);
        break;
    }
}
Alana
  • 27
  • 3
NarendraR
  • 7,577
  • 10
  • 44
  • 82
1

Eventually I combined the answers here and that's the result:

Select select = new Select(driver.findElement(By.xpath("//whatever")));

public void selectByPartOfVisibleText(String value) {
    List<WebElement> optionElements = driver.findElement(By.cssSelector("SELECT-SELECTOR")).findElements(By.tagName("option"));

    for (WebElement optionElement: optionElements) {
        if (optionElement.getText().contains(value)) {
            String optionIndex = optionElement.getAttribute("index");
            select.selectByIndex(Integer.parseInt(optionIndex));
            break;
        }
    }

    Thread.sleep(300);
}

And in Scala (need it eventually in Scala) it looks like:

  def selectByPartOfVisibleText(value: String) = {
    val optionElements: util.List[WebElement] = selectElement.findElements(By.tagName("option"))

    breakable {
      optionElements.foreach { elm =>
        if (elm.getText.contains(value)) {
          val optionIndex = elm.getAttribute("index")
          selectByIndex(optionIndex.toInt)
          break
        }
      }
    }
    Thread.sleep(300)
  }
Zoette
  • 1,241
  • 2
  • 18
  • 49
Johnny
  • 14,397
  • 15
  • 77
  • 118
  • I had an issue that the next action didn't happen because the dropdown closure hasn't rendered fast enough. – Johnny Feb 27 '20 at 09:29
0

Get a list of all the option values and then check if the value contains your partial text. Something like this:

List<WebElement> list = driver.findElements(By.tagName("option"));
Iterator<WebElement> i = list.iterator();
while(i.hasNext()) {
    WebElement wel = i.next();    
    if(wel.getText().contains("your partial text"))
    {
       //select this option
    }
} 
LittlePanda
  • 2,496
  • 1
  • 21
  • 33
  • Cool, thanks. I just don't really like working explicitly with Iterators, will do it a bit differently. – Johnny Apr 21 '15 at 13:53
0

This will work

WebElement element = driver.findEle(By.xpath(loc));
            Select select = new Select(element);
            for(int i=1;i<=select.getOptions().size();i++)
            {
                if(select.getOptions().get(i-1).getText().contains(containsTxt))
                {
                    select.selectByIndex(i-1);
                    break;
                }
                if(i==select.getOptions().size())
                {   
                    //"Fail"
                }
            }
Karthik
  • 113
  • 2
  • 15
-1

This is what I used to solve the issue in python.

I used this option, so it selects the text that uses the word DOLLAR instead of typing the whole word as the value.

Select(driver.find_element_by_name(ELEMENT)).select_by_value("DOLLAR")

instead of

Select(driver.find_element_by_name(ELEMENT)).select_by_visible_text(text)
Danny Buonocore
  • 3,731
  • 3
  • 24
  • 46