我最近在使用 FirefoxDriver 时遇到了同样的问题。在我的特定设置中,我在 <html> 标签上有一个冒泡的委托“更改”事件处理程序,但没有触发:
document.documentElement.addEventListener("change", handleChange, false);
function handleChange(event) {
// do stuff
}
即使在下拉列表中,以下代码也没有触发 onchange:
SelectElement select = new SelectElement(element);
select.SelectByText("Foo");
该选项将被选中,但甚至没有触发任何更改——即使将焦点设置到另一个表单字段也是如此。在触发更改事件之前,我使用自己的鼠标在下拉列表中选择了一个新值。
我通过单击下拉菜单,然后单击其中的选项来解决此问题:
IWebElement element = // ...
element.Click();
element.FindElements(By.TagName("option"))
.Single(opt => opt.Text == Value)
.Click();
这是一个方便的扩展方法,可以做同样的事情:
public static class IWebElementExtensions
/// <summary>
/// Selects an option in a dropdown list by visible option text.
/// </summary>
/// <param name="element"></param>
/// <param name="optionText"></param>
public static void SelectOptionByText(this IWebElement element, string optionText)
{
if (element == null)
throw new ArgumentNullException("element");
if (element.TagName != "select")
throw new ArgumentException("The element must be a <select> tag");
if (optionText == null)
throw new ArgumentNullException("optionText");
var options = element.FindElements(By.TagName("option"))
.Where(opt => opt.Text == optionText);
if (options.Count() == 0)
throw new NoSuchElementException("Could not find <option>" + optionText + "</option> inside <select id=\"" + element.GetAttribute("id") + "\">");
if (options.Count() > 1)
throw new WebDriverException("Too many <option>" + optionText + "</option> tags inside <select id=\"" + element.GetAttribute("id") + "\">");
element.Click();
options.Single().Click();
element.Click();
}
}
并使用:
element.SelectOptionByText("Foo");
好处
- 没有 JavaScript hack
- 在 Selenium 中使用原生事件
缺点