【问题标题】:Unable get options from a Select using Selenium无法使用 Selenium 从 Select 中获取选项
【发布时间】:2016-07-07 10:44:14
【问题描述】:

我在使用 Selenium Webdriver 从下拉列表中选择选项时遇到困难。下面是HTMLsn-p:

<span id="id14">
    <div class="stadium-input-row">
        <span class="inputContainer">
            <select id="id1f" class="departurePoint stadiumSelect" onchange="var wcall=..........">
            <option value="">Please select</option>
            <option value="BHX"> Birmingham - (BHX) </option>
            <option value="GLA"> Glasgow - (GLA) </option>
            <option value="LON"> London - (LON) </option>
            <option value="MAN"> Manchester - (MAN) </option>............

每次加载 DOM 时,选择标签 id 都会发生变化。

选择标签在与之交互之前是灰色的。

我的代码

Select oSelect = new Select(driver.findElement(By.xpath("(.//select)[1]"));
oSelect.selectByVisibleText("Birmingham");

错误

org.openqa.selenium.NoSuchElementException:找不到元素 带文字:伯明翰

在调试模式下,下拉菜单似乎没有被驱动程序激活(单击)。

【问题讨论】:

  • 使用.selectByVisibleText("Birmingham - (BHX)"); 作为我提供的答案......它对我有用......
  • 抱歉,因为该元素不可见,所以这不起作用
  • 但是根据您的例外情况,似乎 selenium 找到了选择框,但无法通过提供的文本选择选项..
  • 我尝试了相同的代码,我得到了同样的错误,但是当我将 oSelect.selectByVisibleText("Birmingham"); 更改为 oSelect.selectByVisibleText("Birmingham - (BHX)") 时,它工作正常......
  • 你为什么要点击下拉菜单...如果你想从下拉菜单中选择选项,这里不需要...你只需要找到下拉元素并将其传递给new Select()。 ..并使用它...它将自行选择您提供的选项..

标签: java selenium select xpath webdriver


【解决方案1】:

那个网站上发生了一件奇怪的事情(至少对我来说很奇怪)。您尝试访问的 SELECT 被永久隐藏(这意味着它不能与使用 Selenium 进行交互)。用户通过虚假下拉列表(不是SELECT)与DIVs 等进行交互,这些选择的结果存储在隐藏的SELECT 中。有两种方法可以完成您的任务。

  1. 处理你能看到的。

    这对这个网站来说真的很痛苦。我认为它最终可以完成,但我不想自己花更多的时间,所以我会带你开门,你必须从我离开的地方继续。下面的代码将打开出发下拉菜单。从那里,您可以找到出发机场并单击它。完毕。比听起来更难...

    driver.findElement(By.cssSelector("div.custom-select.departurePoint.airportSelect")).click();
    
  2. 欺骗和使用JavascriptExecutor

    注意:通过这样做,您不再执行真实的用户场景,因为用户无法单击隐藏元素或将 Javascript 命令注入页面。只要您对此没问题,这里有一个示例。

    此代码使用JavascriptExecutor 在页面上执行Javascript。您将在选项中查找的字符串传递给函数,例如您可以通过“EMA”或“East Midlands - (EMA)”或介于两者之间的任何地方。 JS 代码会抓取隐藏的 SELECT,搜索 OPTIONS,然后选择第一个匹配的。

    另请注意:您不会看到带有选择的 UI 更新。单击搜索后,它将起作用。我自己试过了,效果很好。

    另一个注意事项:我使用 Eclipse 作为我的编辑器,因此您在下面的代码中看到的 // @formatter:off 可以防止 Eclipse 包装/重新格式化包含 JS 代码的超长字符串。您可以根据需要保留或删除它。我喜欢那里,因为我仍然可以读取 JS 代码,它的格式和缩进就像它一样,我不希望 Eclipse 把它搞砸。

    selectOption("EMA");
    
    public void selectOption(String option)
    {
        // @formatter:off
        String script =
            "function selectOption(s) {\r\n" +
            "   var sel = document.querySelector('select.departurePoint.airportSelect');\r\n" +
            "   for (var i = 0; i < sel.options.length; i++)\r\n" +
            "   {\r\n" +
            "       if (sel.options[i].text.indexOf(s) > -1)\r\n" +
            "       {\r\n" +
            "           sel.options[i].selected = true;\r\n" +
            "           break;\r\n" +
            "       }\r\n" +
            "   }\r\n" +
            "}\r\n" +
            "return selectOption('" + option + "');";
    
        // @formatter:on
        ((JavascriptExecutor) driver).executeScript(script);
    }
    

【讨论】:

  • 我对这样的问题又爱又恨。我喜欢它的谜题方面,但有时我讨厌弄清楚它们需要多长时间。所以,你最好给这个 500x 投票,接受它作为答案,并为我在这个问题上所做的所有工作提供你的长子......哈哈。
  • 我在长时间的中断后回到这个问题。您提供的解决方案(Javascript 执行器) 工作,但现在我似乎无法让它工作。也许我将错误的 CSS 选择器传递给代码?我正在传递 select.selection-component 但我认为这不太正确,因为页面会在单击“搜索”时刷新并且不执行搜索。这是club18-30.com/club18-30
【解决方案2】:

你需要做什么:

List<WebElement> options = driver.findElement(By.xpath("//div[@class='stadium-input-row']//select")).findElements(By.tagName("option"));

这将为您创建选项标签列表作为 WebElement 对象

Select oSelect = new Select(driver.findElement(By.xpath("//div[@class='stadium-input-row']//select"));

或者只是将选择作为 WebElement 对象

WebElement selectElement = driver.findElement(By.xpath("//div[@class='stadium-input-row']//select"));

悬停元素

Actions action = new Actions(driver);
WebElement hoverElement = driver.findElement(By.xpath("//div[@class='stadium-input-row']//select"));
action.moveToElement(hoverElement);
action.click().build().perform();

【讨论】:

  • 使用第一种方法,它确实创建了一个标签列表,因为我在调试时可以看到列表中有41个元素。我遇到的问题是将元素暴露给 Selenium,以便它可以与之交互。例如,如果我这样做:options.get(1).click,我仍然会得到一个 org.openqa.selenium.ElementNotVisibleException 以及每个建议的方法。
  • 尝试将鼠标悬停在选择上,然后与之交互 - 我将添加代码
  • 悬停时不会激活下拉菜单,而是单击时
  • 您将鼠标悬停在选择元素上,然后单击您需要的选项,尝试一下。
  • 不幸的是我仍然得到一个元素不可见的异常
【解决方案3】:

正如您的exception 明确表示Cannot locate element with text: Birmingham 意味着它与整个可见文本选项进行比较,因此您应该尝试如下:-

WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement select = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("(.//select)[1]")));
Select oSelect = new Select(select);
oSelect.selectByVisibleText("Birmingham - (BHX)");

oSelect.selectByIndex(1);

oSelect.selectByValue("BHX");

已编辑 :- 如果不幸的是上述解决方案都不起作用,您应该尝试使用JavascriptExecutor,如下所示:-

((JavascriptExecutor)driver).executeScript("var select = arguments[0]; for(var i = 0; i < select.options.length; i++){ if(select.options[i].text.indexOf(arguments[1]) != -1){ select.options[i].selected = true; } }",
            driver.findElement(By.xpath("(.//select)[1]")),
            "Birmingham");

希望对你有帮助..:)

【讨论】:

    【解决方案4】:

    Select 并非在所有情况下都有效。试试这个代码

    List <WebElement> options = driver.findElements(By.xpath("Target Element with Options"));
        String element;
        for(int i=0;i<options.size();i++)
        {
            element = options[i].get(i).getAttribute("value");
            if(element.equals("BHX")){
                options.get(i).click();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多