web-dev-qa-db-ja.com

SeleniumWebdriverでSelect2を処理する

Selenium Webドライバーを使用して、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のイベントを発生させて選択したアイテムにデータを入力することなく、ハングして次のステップに進みます。

http://code.google.com/p/Selenium/wiki/AdvancedUserInteractions apiを使用するのにも疲れましたが、同様の結果が得られました。

誰かが以前に同様の問題に遭遇したことがありますか?

22
Justen Martin

ロケーターも見せていただけませんか?これが私が問題なくテストしたものです。

  1. 選択ボックスを開くには、cssセレクター_#s2id_e1 .select2-choice_または同等のXPathを使用します。
  2. _#select2-drop_が、cssセレクター#select2-drop:not([style*='display: none'])または同等のXPathによって、表示されていることを確認してください。
  3. subContainerClass + _.select2-results li.select2-result-selectable_または同等のXPathを使用して、選択可能な項目をクリックしてください。
_var driver = new FirefoxDriver();
driver.Url = "http://ivaynberg.github.io/select2/";

var select2Product = driver.FindElement(By.CssSelector("#s2id_e1 .select2-choice"));
select2Product.Click();

string subContainerClass = "#select2-drop:not([style*='display: none'])";
var searchBox = driver.FindElement(By.CssSelector(subContainerClass + " .select2-input"));
searchBox.SendKeys("Ohio");

var selectedItem = driver.FindElements(By.CssSelector(subContainerClass + " .select2-results li.select2-result-selectable")).First();
selectedItem.Click();
_
28
Yi Zeng

FF、ChromeおよびIE8-11で動作させるためにしばらく時間を費やしました。

  1. ドロップ矢印をクリックします
  2. 必要な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();
}
6
Aleksandr

これが私のコードです(取得/表示):

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; 
}

select2の利用可能な要素の表示(結果)

select2をid(属性)で使用:s2id_autogen1

List<WebElement> select2Results = getDataFromSelect2("//input[@id='s2id_autogen1']");

for(WebElement item: select2Results)
{
    System.out.println(item.getText());
}
3
L.Weiss

これは、1つのページで複数のselect2ドロップダウンを操作するという追加の問題を処理する、堅実で再利用可能なソリューションです。

何らかの理由で、Webドライバーは、検索値を送信する要素を、画面に表示されていてカーソルがその中にあるにもかかわらず、表示されているとは見なしていませんでした。これが、「表示された場合」のテストでチェックされるものです。次に、別のセレクターを使用します。

対話するフィールドのID(標準のs2id_を除く)と選択する値(または少なくとも選択を行うのに十分な値)を送信できる関数です。

余分なthread.sleep()は、私がそれを見るのを助けるためだけのものでした。それらが結果に影響を与えるとは思わない。

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);
        }

    }
2
KyleK

以下のコードを使用して目的のオプションを選択しましたが、機能しました。これは、複数のクリックを実行するよりも高速である必要があります。

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)
2
Balaji
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);
}
1
czlatea