【问题标题】:Selenium: input text in field that hasn't an input tag - how to find which one is it?Selenium:在没有输入标签的字段中输入文本 - 如何找到它?
【发布时间】:2019-06-04 07:15:58
【问题描述】:

我需要在没有输入标签的表中的字段中输入文本。此 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

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

【问题讨论】:

    标签: selenium selenium-webdriver xpath webdriver robotframework


    【解决方案1】:

    您得出的结论是正确的 - 您不能将输入发送到 &lt;div&gt; 标签,这不是浏览器通常的工作方式(规则的例外情况在“edit 2强>")。代码异常清楚地说明了它 - “元素必须是用户可编辑的才能清除它”。不管 div 的类值是否为“edit-cell” - 这只是开发人员选择的名称,用于说明性建议;这并不意味着 div 将能够接受输入。

    应用程序使用的 UI 很可能使用此 &lt;div&gt; 来风格化表示用户设置的值;有一个隐藏的 &lt;input&gt; 元素接受实际的键盘输入,并且 javascript 代码用它们更新 &lt;div&gt;
    您必须找到该输入标记,并将其定位为您的更改。

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

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

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

    它将打印具有该“特殊”值的&lt;input&gt; 元素。

    edit2:用 JS 的值查找 any 标签。

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

    所以 - 一个修改版的 javascript 来定位“谁持有我们的价值”;谢天谢地,getElementsByTagName() 支持参数的通配符 - 这将匹配任何元素:

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

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

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

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

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

    [...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 中出现)。
    • 如果条件返回真,console.log(el) 将在控制台中打印出来。

    【讨论】:

    • 请注意,实际上divph1 等)可以表现为input 字段并使用相同的方法进行处理(例如使用clear()sendKeys()。 ..),但它应该将contenteditable 属性设置为true。我在 OP 共享的 HTML 示例的任何 div 中都没有看到该属性,所以是的,看来 OP 只是试图处理错误的元素......
    • 在页面上找到 16 个输入,但似乎没有一个与该字段相关。请注意,它是一个包含大量单元格的表格(6 x 15 = 90 个单元格)。那需要90个输入吗?任何其他建议如何找到这个领域? (我在 Chrome 的开发者工具中使用了元素检测器)。
    • @EmLi 我已经用示例步骤更新了答案,如何找到这样的&lt;input&gt; 标签。
    • 如果输入的文本不是存储在input标签中,而是另一种类型,那么它很可能不在“值”属性中,而是文本内容的一部分其他类型。等一下,我会更新答案... :)
    • @EmLi 更新了如何查找任何内容中包含我们的文本的元素。看看我已经投入了多少? :D
    【解决方案2】:

    此错误消息...

    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
      

    【讨论】:

    • 我尝试了您的两种解决方案,但仍然收到相同的错误消息。由于我的测试失败,Chrome 保持打开状态,手动单击此字段然后输入一个值没有问题。还有其他建议吗?
    • invoke click 是什么意思?
    • 能不能把Waits一个个都申请一下,然后点击试试?
    • 我应该在发送input text 之前发送click element 吗?我会尝试两种等待。
    • 这不是那个错误信息的意思。这意味着该元素不可编辑,因此无法清除。 .clear() 可以在 INPUT 上工作,但不能在 DIV 上工作,因为 INPUTs 可以在 DIV 通常不能编辑的地方进行编辑。
    猜你喜欢
    • 2021-06-16
    • 2020-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-11
    • 2019-02-08
    • 2011-10-14
    • 1970-01-01
    相关资源
    最近更新 更多