Select a Dropdown Option by Visible Text
Choose options in native select elements with the Select helper, and handle custom (non-select) dropdowns built from divs.
Problem
You need to pick “United Kingdom” from a country dropdown. Half the time it is a real <select>; the other half it is a styled <div> list from a component library, and Select throws UnexpectedTagNameException.
Solution
Detect the tag. Use the Select helper for native selects; for custom widgets, click the trigger and click the option by text.
import org.openqa.selenium.support.ui.Select;
public static void choose(WebDriver driver, By trigger, String visibleText) { WebElement el = driver.findElement(trigger); if ("select".equalsIgnoreCase(el.getTagName())) { new Select(el).selectByVisibleText(visibleText); return; } // Custom dropdown: open it, then click the matching option el.click(); By option = By.xpath("//*[@role='option' or contains(@class,'option')][normalize-space()='" + visibleText + "']"); new WebDriverWait(driver, Duration.ofSeconds(5)) .until(ExpectedConditions.elementToBeClickable(option)).click();}
choose(driver, By.id("country"), "United Kingdom");from selenium.webdriver.support.select import Select
def choose(driver, trigger, visible_text): el = driver.find_element(*trigger) if el.tag_name.lower() == "select": Select(el).select_by_visible_text(visible_text) return el.click() option = (By.XPATH, f"//*[@role='option' or contains(@class,'option')][normalize-space()='{visible_text}']") WebDriverWait(driver, 5).until(EC.element_to_be_clickable(option)).click()
choose(driver, (By.ID, "country"), "United Kingdom")const { Select } = require('selenium-webdriver/lib/select');
async function choose(driver, trigger, visibleText) {const el = await driver.findElement(trigger);if ((await el.getTagName()).toLowerCase() === 'select') { await new Select(el).selectByVisibleText(visibleText); return;}await el.click();const option = By.xpath(`//*[@role='option' or contains(@class,'option')][normalize-space()='${visibleText}']`);const opt = await driver.wait(until.elementLocated(option), 5000);await driver.wait(until.elementIsVisible(opt), 5000);await opt.click();}
await choose(driver, By.id('country'), 'United Kingdom');using OpenQA.Selenium.Support.UI;
public static void Choose(IWebDriver driver, By trigger, string visibleText){ var el = driver.FindElement(trigger); if (el.TagName.Equals("select", StringComparison.OrdinalIgnoreCase)) { new SelectElement(el).SelectByText(visibleText); return; } el.Click(); var option = By.XPath($"//*[@role='option' or contains(@class,'option')][normalize-space()='{visibleText}']"); new WebDriverWait(driver, TimeSpan.FromSeconds(5)) .Until(d => { var o = d.FindElement(option); return o.Displayed && o.Enabled ? o : null; }).Click();}
Choose(driver, By.Id("country"), "United Kingdom");Why It Works
Select manipulates the native element and fires change, which is what the app listens to. Custom dropdowns are just DOM: opening the trigger renders the options (often with role="option"), and clicking one runs the component’s handler. Matching by normalize-space() text tolerates padding whitespace.
Gotchas
- Some custom dropdowns render options in a portal at the end of
<body>, not inside the trigger; the document-wide XPath above handles that. - Searchable dropdowns need typing first:
sendKeys(visibleText)into the trigger’s input, then click the option. - For native selects,
selectByValueandselectByIndexexist too; visible text is the most readable in tests but couples to copy. - Verify the selection afterwards with
Select.getFirstSelectedOption()or the trigger’s displayed text; some components swallow the click if the list is still animating.