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を使用するのにも疲れましたが、同様の結果が得られました。
誰かが以前に同様の問題に遭遇したことがありますか?
ロケーターも見せていただけませんか?これが私が問題なくテストしたものです。
注
#s2id_e1 .select2-choice
_または同等のXPathを使用します。#select2-drop
_が、cssセレクター#select2-drop:not([style*='display: none'])
または同等のXPathによって、表示されていることを確認してください。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();
_
FF、ChromeおよびIE8-11で動作させるためにしばらく時間を費やしました。
これが私の簡略化されたコードです:
[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;
}
select2
の利用可能な要素の表示(結果)
select2
をid(属性)で使用:s2id_autogen1
:
List<WebElement> select2Results = getDataFromSelect2("//input[@id='s2id_autogen1']");
for(WebElement item: select2Results)
{
System.out.println(item.getText());
}
これは、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);
}
}
以下のコードを使用して目的のオプションを選択しましたが、機能しました。これは、複数のクリックを実行するよりも高速である必要があります。
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)
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);
}