C# 使用Selenium webdriver处理Select2

C# 使用Selenium webdriver处理Select2,c#,selenium,selenium-webdriver,jquery-select2,C#,Selenium,Selenium Webdriver,Jquery Select2,我一直在用SeleniumWebDriver从支持ajax的select2选择列表中选择一个选项。我已经设法让它与IE webdriver一起工作,但不是firefox。这是我的黑客IE解决方案 public static void SetSelect2Option(this IWebDriver driver, By locator, string subContainerClass, string searchTerm, TimeSpan? ajaxWaitTimeSpan = null)

我一直在用SeleniumWebDriver从支持ajax的select2选择列表中选择一个选项。我已经设法让它与IE webdriver一起工作,但不是firefox。这是我的黑客IE解决方案

 public static void SetSelect2Option(this IWebDriver driver, By locator, string subContainerClass, string searchTerm, TimeSpan? ajaxWaitTimeSpan = null)
    {
        var select2Product = driver.FindElement(locator);
        select2Product.Click();
        var searchBox = driver.FindElement(By.CssSelector(subContainerClass + " .select2-input"));
        searchBox.SendKeys(searchTerm);
        if (ajaxWaitTimeSpan != null)
        {
            driver.Manage().Timeouts().ImplicitlyWait(ajaxWaitTimeSpan.Value);
        }
        var selectedItem = driver.FindElements(By.CssSelector(subContainerClass + " .select2-results li")).First();
        selectedItem.Click();
        selectedItem.SendKeys(Keys.Enter);
    }
在Firefox中,此解决方案一直工作到SendKeys调用挂起并进入下一步,而没有实际触发select2的事件来填充所选项目

我也厌倦了使用具有类似结果的api


以前有人遇到过类似的问题吗?

您能给我们看一下定位器吗?以下是我测试的内容,没有任何问题

要打开选择框,请使用css选择器s2id_e1.select2 choice或等效的XPath。 通过css选择器select2 drop:not[style*='display:none']或等效的XPath,确保select2 drop是可见的。 确保使用SubcainerClass+单击可选项。选择2 results li.select2-result-selected或等效XPath。 var-driver=新的FirefoxDriver; 驱动程序Url=http://ivaynberg.github.io/select2/; var select2Product=driver.FindElementBy.CssSelectors2id_e1.select2选项; 选择2产品。单击; string subcainerclass=select2 drop:not[style*='display:none'; var searchBox=driver.FindElementBy.cssselector子容器类+。选择2输入; searchBox.SendKeysOhio; var selectedItem=driver.FindElementsBy.CssSelectorsubContainerClass+。select2 results li.select2-result-selectable.First; 选择编辑项。单击;
这是一个可靠的、可重用的解决方案,可以解决在一个页面上与多个select2下拉列表交互的额外问题

出于某种原因,webdriver没有考虑将搜索值发送到的元素是否可见,即使您可以在屏幕上看到它并且光标在其中。这就是“如果显示”测试检查的内容。然后它使用不同的选择器

它的一个功能是,您可以发送想要与之交互的字段的ID,而不是标准的s2id和要选择的值,或者至少发送足够的值来进行选择

额外的线程。睡眠只是为了帮助我看它。我认为它们不会影响结果

public void SelectDropDownOption(string dropDownID, string option)
    {
        for (int second = 0; ; second++)
        {
            if (second >= 60) Assert.Fail("timeout");
            try
            {
                if (driver.FindElement(By.CssSelector("div[ID^=s2id_" + dropDownID + "]>a.select2-choice")).Displayed) break;
            }
            catch (Exception)
            { }
            Thread.Sleep(1000);
        }

        driver.FindElement(By.CssSelector("div[ID^=s2id_" + dropDownID + "]>a.select2-choice")).Click();
        Thread.Sleep(1000);

        if (driver.FindElement(By.CssSelector("input.select2-input.select2-focused")).Displayed == true)
        {
            driver.FindElement(By.CssSelector("input.select2-input.select2-focused")).SendKeys(option);
            Thread.Sleep(500);
            driver.FindElement(By.CssSelector("input.select2-input.select2-focused")).SendKeys(Keys.Enter);
            Thread.Sleep(500);
        }
        else
        {
            driver.FindElement(By.CssSelector("input.select2-focusser.select2-offscreen")).SendKeys(option);
            Thread.Sleep(500);
            driver.FindElement(By.CssSelector("input.select2-focusser.select2-offscreen")).SendKeys(Keys.Enter);
            Thread.Sleep(500);
        }

    }

我花了一些时间让它在FF、Chrome和IE8-11中工作

单击下拉箭头 单击所需的li 以下是我的简化代码:

[FindsBy(How = How.ClassName, Using = "select2-arrow")]
private IWebElement Selector { get; set; }

private void selectItem(string itemText)
{
    Selector.Click();  // open the drop
    var drop = Driver.FindElement(By.Id("select2-drop"));    // exists when open only
    var item = drop.FindElement(By.XPath(String.Format("//li[contains(translate(., '{0}', '{1}'), '{1}')]", itemText.ToUpper(), itemText.ToLower())));
    item.Click();
}

以下是我的代码获取/显示:

正在获取select2可用元素结果:

public List<WebElement> getDataFromSelect2(String elementXpath)
{       
    WebElement select2Element = driver.findElement(By.xpath(elementXpath));
    select2Element.click();     

    WebDriverWait webDriverWait = new WebDriverWait(driver, 90);
    webDriverWait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//ul[@class='select2-results']//div")));

    WebElement select2ElementResults=driver.findElement(By.xpath("//div[@id='select2-drop']/ul[@class='select2-results']"));
    List<WebElement> selectResultsAsListCollection = select2ElementResults.findElements(By.tagName("div"));

    return selectResultsAsListCollection; 
}

我使用下面的代码来选择所需的选项,它起了作用。这也必须比执行多次单击更快

String script = "$('select#yearSelector').trigger($.Event('change',{val:'" + year + "'}))";
((JavascriptExecutor) driver).executeScript(script);
在Python中,如果这一行程序不起作用,请尝试将其拆分为组件:

 value = ['a', 'b', 'c']
 script = "var elem = $('select#tradingMarketSelect'); "
 script += "elem.val(%s); " % value
 script += "elem.change();"
 self.driver.execute_script(script)

尝试选择webdriver javascript执行。下面是一个简便的C方法,我在苦苦挣扎了几周后,今天才开始使用

// usings
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;


// method
public static void SetSelect2Option_JSExample(this IWebDriver driver, string select2Id, string value)
{       
    IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
    string js = "$('#" + select2Id + "').val('" + value + "').trigger('change');";
    string jsOutput = (string)jsExecutor.ExecuteScript(js);
}

FWIW,我不得不用“ClickAt”5,5代替“clicks”来让它工作。@Daniel:这很可能是其他元素重叠。什么版本?哪个浏览器?这是FF中的Selenium 2.4.0。我正在使用IDE,但我希望其行为类似。我对Selenium还不熟悉,但无法想象当clickAt不工作时,是什么导致click不工作。单击的行为是不会显示select2下拉列表。您的回答有助于我找到正确的元素,但是…我还必须等待与select2Product相对应的案例中的元素显示出来。否则,测试会随机失败,出现Elementnotvisibleexception。@HappyBird,我们都是来学习的。你能提出改进建议吗?我的解决方案可能并不完美,但我觉得它提供了很多有用的信息。对不起,我不需要太粗鲁。我的意思是那条线。应该尽量避免睡觉。啊,谢谢你的回答。我同意。正如在最初的帖子中提到的,这些只是故障排除的遗留问题,而不是实际解决方案的一部分。我想我应该把它们去掉,保持简单。再次感谢您,祝您愉快。
protected void SelectOptionForSelect2(IWebDriver driver, string id, string text)
{
  var element = driver.FindElement(By.Id(id)).FindElement(By.XPath("following-sibling::*[1]"));
  element.Click();

  element = driver.FindElement(By.CssSelector("input[type=search]"));
  element.SendKeys(text);

  Thread.Sleep(1000);
  element.SendKeys(Keys.Enter);
}
// usings
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;


// method
public static void SetSelect2Option_JSExample(this IWebDriver driver, string select2Id, string value)
{       
    IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)driver;
    string js = "$('#" + select2Id + "').val('" + value + "').trigger('change');";
    string jsOutput = (string)jsExecutor.ExecuteScript(js);
}