使用 Selenium webdriver 处理 Select2
Posted
技术标签:
【中文标题】使用 Selenium webdriver 处理 Select2【英文标题】:Handling Select2 with Selenium webdriver 【发布时间】:2013-07-19 04:56:27 【问题描述】:我一直在努力尝试使用 selenium webdriver 从启用 ajax 的 select2 选择列表中选择一个选项。我已经设法让它与 IE webdriver 但不是 Firefox 一起工作。这是我针对 IE 的 hacky 解决方案
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 并获得类似的结果。
以前有没有人遇到过类似的问题?
【问题讨论】:
【参考方案1】:能否请您也向我们展示定位器?这是我测试的没有任何问题。
注意
-
要打开选择框,请使用 css 选择器
#s2id_e1 .select2-choice
或等效的 XPath。
通过 css 选择器 #select2-drop:not([style*='display: none'])
或等效的 XPath 确保 #select2-drop
是可见的。
确保使用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();
【讨论】:
FWIW,我不得不使用 'ClickAt' 5,5 而不是点击来让它工作。 @Daniel:你更有可能有其他元素重叠。什么版本?哪个浏览器? 这是在 FF 的 Selenium 2.4.0 中。我正在使用 IDE,但希望行为相似。我是 Selenium 的新手,但是当 clickAt 发生时,我无法想象是什么导致点击不起作用。单击的行为是不出现 select2 下拉菜单。不过,您的回答有助于我找到正确的元素...... 我还必须等待与select2Product
相对应的元素显示出来。否则,测试会随机失败并返回 Elementnotvisibleexception
。【参考方案2】:
我花了一些时间让它在 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();
【讨论】:
【参考方案3】:这是我的代码(获取/显示):
获取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());
【讨论】:
【参考方案4】:我使用下面的代码来选择所需的选项并且它有效。这也必须比执行多次点击更快。
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)
【讨论】:
【参考方案5】:这是一个可靠的、可重复使用的解决方案,可以处理与一个页面上的多个 select2 下拉菜单交互的额外问题。
由于某种原因,webdriver 没有考虑将搜索值发送到的元素是可见的,即使您可以在屏幕上看到它并且光标在其中。这就是“如果显示”测试检查的内容。然后它使用不同的选择器。
它是一个函数,您可以发送要与之交互的字段的 ID(减去标准 s2id_)和要选择的值(或至少足以进行选择。)
额外的 thread.sleep()s 只是为了帮助我观看它。我认为它们不会影响结果。
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);
【讨论】:
@HappyBird,我们都在这里学习。你能提出改进建议吗?我的解决方案可能并不完美,但我觉得它提供了很多有用的信息。 对不起,我不需要粗鲁。我的意思是应该尽量避免Thread.Sleep()
。
啊,感谢您的回复。我同意。如原始帖子中所述,这些只是故障排除的剩余部分,而不是实际解决方案的一部分。我想我应该删除它们并保持简单。再次感谢并祝您编码愉快。【参考方案6】:
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);
【讨论】:
【参考方案7】:尝试选择 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);
【讨论】:
以上是关于使用 Selenium webdriver 处理 Select2的主要内容,如果未能解决你的问题,请参考以下文章
使用 selenium webdriver chrome 处理“选择数字证书”
如何使用 Selenium WebDriver 处理登录弹出窗口?
在 Python 中使用 Selenium WebDriver 时处理 Firefox 无响应?
如何使用 selenium 或 webdriver 在测试自动化中处理文件上传