HTML5 input+datalist控件选择selenium

HTML5 input+datalist control item selection with Selenium

用例是 select 在 selenium 的帮助下从下拉列表中选择一个项目。我尝试了以下但无法实现我的目标。输入标签指的是数据列表。

    String baseUrl = "https://angular-cwmwke.stackblitz.io" ; 
    driver.get(baseUrl); // opens the webpage
    // Put some wait for the page to load the dropdown
    driver.findElement(By.xpath("//input[@list='id-car']")).click(); // clicks on the dropdown
    driver.findElement(By.xpath("//*[@id='id-car']/option[1]")).click(); // Does not works.

它失败了,这是个例外。 JavascriptException: javascript 错误:选项元素不在 select

Selenium 版本:3.14.0 和 Chrome 版本:78.0.3904.108

这里是HTML(请忽略选项值):

<input _ngcontent-c0="" list="id-car" ng-reflect-model="[object Object]" class="ng-pristine ng-valid ng-touched">
<datalist _ngcontent-c0="" id="id-car">
<!--bindings={
 "ng-reflect-ng-for-of": "[object Object],[object Object"
   }-->
 <option _ngcontent-c0="" value="[object Object]" ng-reflect-value="[object Object]">Ford-GTX</option>
 <option _ngcontent-c0="" value="[object Object]" ng-reflect-value="[object Object]">Ferarri - Enzo</option>
 <option _ngcontent-c0="" value="[object Object]" ng-reflect-value="[object Object]">VW - Amarok</option>
</datalist>

关于 datalist 标签最初需要注意的一些事情,这与 select 的不同之处在于 select 元素将选择限制为预定义的集合,而 datalist 提供 建议的 选项,但可以接受任何输入。此外,datalist 选项通常与 value 属性一起使用,因此在这种情况下(您也可以手动测试)当您单击任何选项时,显示的值是相同的([object Object ]).

请注意,您收到 JavascriptException: javascript 错误:选项元素不在 select 中的原因是,我想一想,Selenium 期望 option 标签位于 select 元素下。 datalist 标签比 select 更像一个普通的输入文本框,使用 Selenium.

时必须这样对待

因此,首先,如果您可以访问该 html 代码,我会将值更新为现在的文本。它看起来像这样:

<option _ngcontent-c0="" value="Ford-GTX" ng-reflect-value="Ford-GTX"/>
<option _ngcontent-c0="" value="Ferarri - Enzo" ng-reflect-value="Ferarri - Enzo"/>
<option _ngcontent-c0="" value="VW - Amarok" ng-reflect-value="VW - Amarok"/>

"selecting" 某个选项的 Selenium 代码将是这样的:

var input = driver.findElement(By.xpath("//input[@list='id-car']"));
var option = driver.findElement(By.xpath("//*[@id='id-car']/option[1]"));
var value = option.getAttribute("value");
input.clear();
input.SendKeys(value);

如果这不是您想要实现的行为,并且您又可以访问 html,您可以考虑改用 select 元素。

如果您无权访问 html,并且确实想使用内部 html 文本,您可以简单地修改上面的代码以引用 innerHTMLvalue

var input = driver.findElement(By.xpath("//input[@list='id-car']"));
var option = driver.findElement(By.xpath("//*[@id='id-car']/option[1]"));
var text = option.getAttribute("innerHTML");
input.clear();
input.SendKeys(text);

但是请记住,这可能会导致表单提交时出现一些奇怪的行为,因为真正的用户点击会显示 value,而不是 text