硒:在没有输入标签的字段中输入文字-如何找到它?

时间:2019-01-09 13:35:15

标签: selenium selenium-webdriver xpath webdriver robotframework

我需要将文本输入到没有输入标签的表中的字段中。该XPath唯一地指出了该字段

//div[@id="contentBody"]//div[@row="0"]/div[contains(@class, "l4") and contains(@class, "r4")]

(一个人可以在此XPath上添加尾随/div,这没有区别)

我可以使用此XPath来读取此字段,但是当我尝试在同一字段中插入一些文本时,会出现错误消息:

InvalidElementStateException: Message: invalid element state: Element must be user-editable in order to clear it.

这是单元格的HTML

<div class="slick-cell l4 r4  alignRight uppercase highint editable-cell active selected" aria-describedby="inforDataGrid731693C5" tabindex="-1" role="gridcell">
    <div class="edit-cell">2,0</div></div>

我发现了这个问题(顺便说一句,它似乎被错误地标记为重复项)

Element must be user-editable in order to clear it exception in selenium

这里的注释似乎对我的情况有意义:我的XPath指向div,而不是输入字段(但您可以看到,div的类是“ edit-cell”,所以...),但我没有认为我可以选择指向输入字段。我该如何解决-如何找到要定位的元素,以便我可以成功设置其文本,而不会遇到异常?

2 个答案:

答案 0 :(得分:2)

您得出的结论是已更正的结论-您无法将输入发送到<div>标记,这不是浏览器通常的工作方式(该规则的例外情况在“ 编辑2”中给出”)。代码异常清楚地指出了这一点-“元素必须是用户可编辑的才能清除它”。不管div的类值为“ edit-cell”,还是开发人员选择的名称(用于说明性提议);这并不意味着div将能够接受输入。

应用程序使用的用户界面很可能使用此<div>来对用户设置的值进行样式化表示。有一个隐藏的<input>元素可以接收实际的键盘输入,而javascript代码则用它们来更新<div>
您必须找到该输入标签,并将其定位为您的更改。

edit1:使用JS通过输入标签的值查找它们。

以下是查找输入标签的方法-在浏览器中(手动)将值设置为该页面唯一的字符串-例如“ myMegaSpecialString”。然后在控制台中运行以下js:

[...document.getElementsByTagName("input")].forEach(function(el){ if (el.value == "myMegaSpecialString"){console.log(el);} })

它将打印具有该“特殊”值的<input>元素。

edit2:使用JS通过其值查找 any 标记。

根据评论中的讨论,没有发现<input>元素具有此值。正如@Andersson正确纠正的那样,在特殊情况下,其他元素(输入除外)可以接收khm输入-它们应具有contenteditable属性,并且该属性是从父元素继承的,例如如果设置在<body>标签上,则可以在页面中的任何元素上键入内容。

所以-用于查找“谁拥有我们的价值”的javascript的修改版本;幸运的是,getElementsByTagName()支持通配符作为参数-它将匹配任何元素:

[...document.getElementsByTagName("*")].forEach(function(el){ if (el.value == "myMegaSpecialString"){console.log(el);} })

这可能会慢一些-但它必须打印具有value属性等于“ myMegaSpecialString”的元素。

edit3:使用JS通过其文本内容查找任何标签。

任务继续-您输入的文本不会在任何元素的value属性中出现吗?没问题,让我们在元素的文本内容中查找它。
当您实际上在编辑<span><div>或类似标签(手指交叉...:))的内容时,可能就是这种情况。

这是先前版本的变体-手动将文本设置为整个页面上唯一的值(以限制输出),然后在控制台中运行它:

[...document.getElementsByTagName("*")].forEach(function(el){ if (el.textContent.indexOf("myMegaSpecialString") !== -1){console.log(el);} })

,它将(应该吗?可能?我不确定什么了吗:D)在控制台中打印所有具有该字符串作为其文本一部分的DOM元素。

请分解javascript中的内容,以备将来更改:

  • document.getElementsByTagName("*")]返回具有该标签名称的所有元素作为数组;参数星号(*)-任何标签名称。
  • forEach-遍历集合元素,将每个元素传递给其中的匿名函数。
  • el.textContent-返回节点(及其子节点)的文本内容。
  • indexOf()-返回参数在字符串-1中的位置(如果不存在)(出于兼容性考虑,使用了indexOf()contains(),后者在ES6中出现) )。
  • 如果条件返回true,则console.log(el)将在控制台中将其打印出来。

答案 1 :(得分:-1)

此错误消息...

InvalidElementStateException: Message: invalid element state: Element must be user-editable in order to clear it.

...表示 WebElement 处于无法对其执行操作的状态。示例包括一个元素在单击时被另一个元素遮挡,或者在DOM上不可见。

解决方案

由于该元素是启用了JavaScript的元素,因此需要使 WebDriverWait 成为可点击的元素,并且可以使用以下任一解决方案:

  • Wait Until Element Is Visible

    Wait Until Element Is Visible    xpath=//div[contains(@class, 'slick-cell') and starts-with(@aria-describedby,'inforDataGrid')]/div[@class='edit-cell']    20  seconds
    Set Focus To Element    xpath=//div[contains(@class, 'slick-cell') and starts-with(@aria-describedby,'inforDataGrid')]/div[@class='edit-cell']
    # invoke click
    
  • Wait Until Element Is Enabled

    Wait Until Element Is Enabled    xpath=//div[contains(@class, 'slick-cell') and starts-with(@aria-describedby,'inforDataGrid')]/div[@class='edit-cell']    20  seconds
    Set Focus To Element    xpath=//div[contains(@class, 'slick-cell') and starts-with(@aria-describedby,'inforDataGrid')]/div[@class='edit-cell']
    # invoke click