如何使用 Selenuim/Watir 自动化 DevExpress 组合框?
How do you automate DevExpress Combo Boxes with Selenuim/Watir?
DevExpress 以一种非常奇怪的方式构建组合框。 Selenuim 和 Watir(包括页面对象)内置的标准标识不会将其视为 Select 列表。
那么如何才能成功地实现这些自动化呢?
因此,事实证明,DevExpress 将组合框构建为文本框,其中有多个与之关联的分层 table,但不在 HTML 树中的文本框下方。
交互都是通过嵌入式脚本完成的。
我发现自动化此对象的最简单方法是识别文本框和包含项目列表的最低 table(第 3 个 table 向下)。
例如(使用 Watir 和页面对象)
table(:list,:id => 'ComboBoxValue_DDD_L_LBT')
text_field(:state, :id => 'ComboBoxValue_I') #:name => 'State')
我还没有找到在这些级别上获得更好 ID 的方法,但我们正在解决这个问题。
那么您的 select 代码如下所示:
self.state_element.click
row = list_element.find { |row| row[0].text == value }
row.click
请注意,使用 Selenium,您可以在客户端中执行任意 javascript 以查询和设置控件的状态(如果为控件启用了客户端)。以下是我如何从名为 localeSelectList 的组合框中提取(并设置)所选文本:
// unit test code, c#
[TestMethod]
public void SomeTestMethod()
{
IWebDriver ff = new FirefoxDriver();
ff.Navigate().GoToUrl(homeUrl);
// find the element as an iWebElement
IWebElement localeBox = ff.FindElement(By.CssSelector("#localeSelectList"));
Assert.IsTrue(localeBox.Enabled);
// get the text from the control via javascript
var locale = Util.GetControlText(ff, localeSelectList);
Assert.IsTrue(locale == "English");
// set the text in the control via javascript
Util.SetControlText(ff, localeSelectList, "German");
// verify the text was set
locale = Util.GetControlText(ff, localeSelectList);
Assert.IsTrue(locale == "German");
}
// helper methods, Util class
static public string GetControlText(IWebDriver driver, string controlName)
{
string script = string.Format("return {0}.GetText();", controlName);
var controlText = ((IJavaScriptExecutor)driver).ExecuteScript(script);
return controlText.ToString();
}
static public void SetControlText(IWebDriver driver, string controlName, string controlText)
{
string script = string.Format("{0}.SetValue('{1}');", controlName, controlText);
((IJavaScriptExecutor)driver).ExecuteScript(script);
}
这与通过原语(点击、击键等)与扩展交互并不完全相同,因为它不会触发这些事件的事件处理程序,但如果您的扩展使用 'valueChanged' 事件原始处理程序非常接近相同。
另请注意:您可以使用客户端 javascript 使用 jquery/css 选择器和 ID 查找和 return 元素,如下所示:
IWebElement element = (IWebElement) ((IJavaScriptExecutor)driver).ExecuteScript("return $('#.myElementId');")
几个分层表是正确的,但我想补充一点,它们仅在单击组合框时可见。第一
var cmbParameterGruppen = webDriver.FindElement(By.Id("phContent_ParameterGruppenComboBox_I"));
cmbParameterGruppen.Click();
然后
var tblItems = webDriver.FindElement(By.Id("phContent_ParameterGruppenComboBox_DDD_L_LBT"));
var parameterGruppen = tblItems.FindElements(By.XPath(".//*"));
var count = parameterGruppen.Count;
Debug.WriteLine($"Count = {count}");
if(count > 0)
parameterGruppen[count - 1].Click();
我 select 最后一行。
DevExpress 以一种非常奇怪的方式构建组合框。 Selenuim 和 Watir(包括页面对象)内置的标准标识不会将其视为 Select 列表。 那么如何才能成功地实现这些自动化呢?
因此,事实证明,DevExpress 将组合框构建为文本框,其中有多个与之关联的分层 table,但不在 HTML 树中的文本框下方。 交互都是通过嵌入式脚本完成的。
我发现自动化此对象的最简单方法是识别文本框和包含项目列表的最低 table(第 3 个 table 向下)。
例如(使用 Watir 和页面对象)
table(:list,:id => 'ComboBoxValue_DDD_L_LBT')
text_field(:state, :id => 'ComboBoxValue_I') #:name => 'State')
我还没有找到在这些级别上获得更好 ID 的方法,但我们正在解决这个问题。 那么您的 select 代码如下所示:
self.state_element.click
row = list_element.find { |row| row[0].text == value }
row.click
请注意,使用 Selenium,您可以在客户端中执行任意 javascript 以查询和设置控件的状态(如果为控件启用了客户端)。以下是我如何从名为 localeSelectList 的组合框中提取(并设置)所选文本:
// unit test code, c#
[TestMethod]
public void SomeTestMethod()
{
IWebDriver ff = new FirefoxDriver();
ff.Navigate().GoToUrl(homeUrl);
// find the element as an iWebElement
IWebElement localeBox = ff.FindElement(By.CssSelector("#localeSelectList"));
Assert.IsTrue(localeBox.Enabled);
// get the text from the control via javascript
var locale = Util.GetControlText(ff, localeSelectList);
Assert.IsTrue(locale == "English");
// set the text in the control via javascript
Util.SetControlText(ff, localeSelectList, "German");
// verify the text was set
locale = Util.GetControlText(ff, localeSelectList);
Assert.IsTrue(locale == "German");
}
// helper methods, Util class
static public string GetControlText(IWebDriver driver, string controlName)
{
string script = string.Format("return {0}.GetText();", controlName);
var controlText = ((IJavaScriptExecutor)driver).ExecuteScript(script);
return controlText.ToString();
}
static public void SetControlText(IWebDriver driver, string controlName, string controlText)
{
string script = string.Format("{0}.SetValue('{1}');", controlName, controlText);
((IJavaScriptExecutor)driver).ExecuteScript(script);
}
这与通过原语(点击、击键等)与扩展交互并不完全相同,因为它不会触发这些事件的事件处理程序,但如果您的扩展使用 'valueChanged' 事件原始处理程序非常接近相同。 另请注意:您可以使用客户端 javascript 使用 jquery/css 选择器和 ID 查找和 return 元素,如下所示:
IWebElement element = (IWebElement) ((IJavaScriptExecutor)driver).ExecuteScript("return $('#.myElementId');")
几个分层表是正确的,但我想补充一点,它们仅在单击组合框时可见。第一
var cmbParameterGruppen = webDriver.FindElement(By.Id("phContent_ParameterGruppenComboBox_I"));
cmbParameterGruppen.Click();
然后
var tblItems = webDriver.FindElement(By.Id("phContent_ParameterGruppenComboBox_DDD_L_LBT"));
var parameterGruppen = tblItems.FindElements(By.XPath(".//*"));
var count = parameterGruppen.Count;
Debug.WriteLine($"Count = {count}");
if(count > 0)
parameterGruppen[count - 1].Click();
我 select 最后一行。