【问题标题】:Selenium webdriver returns false from isDisplayed() on newly added object in browser and then returns InvalidElementStateExceptionSelenium webdriver 在浏览器中新添加的对象上从 isDisplayed() 返回 false,然后返回 InvalidElementStateException
【发布时间】:2014-05-23 15:51:27
【问题描述】:

我的脚本中有一个方法,我在循环中使用该方法来确定对象在尝试与之交互之前是否已启用和显示,如下所示:-

public boolean isElementPresent(By myObject, individualThreadSession threadSesh) {
        try{
            if(threadSesh.driver.findElement(myObject).isEnabled() && threadSesh.driver.findElement(myObject).isDisplayed()) {
                return true;
            } else {
                return false;
            }
        } 
        catch (NoSuchElementException e){
            return(false);
        } 
    }

myobject 部分是从一行中传入的,内容如下:- isElementPresent(By.xpath(IDString),threadSesh)

所以我传入了相关的By(通过运行时指定的数据确定)

现在这对我来说已经很长一段时间了,直到现在。我试图在单击链接后单击插入到页面中的对象,问题是即使对象在屏幕上清晰可见,Selenium 的 threadSesh.driver.findElement(myObject).isDisplayed() 部分也会返回 false。

我可以手动与这个对象进行很好的交互,如果我使用 IDE 记录它,它似乎也可以正常工作......有人知道我该如何解决这个问题吗?还是强制 Selenium 认为对象已显示?

未添加对象时,我正在处理的区域的 HTML 如下:-

<td class="activecomment">
    <div data-bind="template: { name: 'commentControlPriorities', data: $data }" style="position: relative">
        <div style="margin-right: 10px" data-bind="with: $data.LatestComment, flash: $data.LatestComment">
            <div data-bind="style: { display: editMode() ? 'none' : 'block' }" style="display: block;">
                <!-- Highlighted comment -->
                <div class="comment labelgrey highlightcomment" data-bind="css: { highlightcomment: $parent.CommentSupportsApproving() && !CommentApproved() }">
                    <div style="word-wrap: break-word" data-bind="text: CommentView">No comment</div>
                    <div style="margin-top: 5px;">
                        <!-- ko if: $parent.isEnabled("Edit") -->
                        <a class="btn btn-small btn-info" data-bind="click: toggleEditMode, clickBubble: false" title="Leave Comment" href="#">
                        <img class="MYIcon" src="/Content/images/edit-icon.png"/>
                        </a>
                        <!-- ko if: $parent.CommentSupportsApproving() && CommentView() != "No comment" -->
                        <!-- /ko -->
                        <!-- /ko -->
                        <span class="lightergrey pull-right">
                            <span data-bind="cutSurname: User"/>
                            <span data-bind="relativeDateFormat: CommentDateView"/>
                        </span>
                    </div>
                </div>
            </div>
            <!-- Editable comment - temporarily hidden -->
            <!-- ko if: $parent.isEnabled("Edit") -->
            <div data-bind="template: { name: 'commentEditControl', data: $data }">
                <div class="labelgrey" style="background-color: rgb(255, 255, 255); padding: 1px; margin: 5px 0px; border: 1px solid rgb(110, 121, 131); display: none;" data-bind="style: { display: editMode() ? 'block' : 'none' }">
                    <textarea id="editcommenttext_0bf0e2db-0662-4b13-8a3c-1840cca79ba6" class="latestComment limitedText editCommentTextArea" data-bind="value: CommentUpdate, valueUpdate: 'afterkeydown', attr: {id: 'editcommenttext_'+$parentContext.$parent.Id()}" style="font-size: 12px; line-height: 18px; width: 100%; background-color: #FFF; border: 0px; resize: none; padding: 0px; margin: 0px; min-height: 54px"/>
                    <span class="validationMessage" style="display: none;"/>
                    <div style="background-color: #6E7983; padding: 5px;">
                        <a id="editcommentsave_0bf0e2db-0662-4b13-8a3c-1840cca79ba6" class="btn btn-small btn-info" data-bind="event: { click: function (data, parent) { saveComment($parentContext.$parent) } }, attr: {id: 'editcommentsave_'+$parentContext.$parent.Id()}" style="margin-right: 7px;" title="Save Comment" href="#">                 Save             </a>
                        <a id="cancelComment" class="cancel" data-bind="click: cancelComment" href="#">Cancel</a>
                        <div style="float: right; font-size: 10px; color: #FFF;">
                            <span class="limitedTextCharactersCount" data-bind="text: RemainingCharacterCount">240</span>
                             characters             
                        </div>
                    </div>
                </div>
            </div>
            <!-- /ko -->
        </div>
    </div>
</td>

一旦你点击对象 <a class="btn btn-small btn-info" data-bind="click: toggleEditMode, clickBubble: false" title="Leave Comment" href="#"> <img class="MYIcon" src="/Content/images/edit-icon.png"/> </a>

改为:

<td class="activecomment">
    <div data-bind="template: { name: 'commentControlPriorities', data: $data }" style="position: relative">
        <div style="margin-right: 10px" data-bind="with: $data.LatestComment, flash: $data.LatestComment">
            <div data-bind="style: { display: editMode() ? 'none' : 'block' }" style="display: none;">
                <!-- Highlighted comment -->
                <div class="comment labelgrey highlightcomment" data-bind="css: { highlightcomment: $parent.CommentSupportsApproving() && !CommentApproved() }">
                    <div style="word-wrap: break-word" data-bind="text: CommentView">No comment</div>
                    <div style="margin-top: 5px;">
                        <!-- ko if: $parent.isEnabled("Edit") -->
                        <a class="btn btn-small btn-info" data-bind="click: toggleEditMode, clickBubble: false" title="Leave Comment" href="#">
                        <img class="MYIcon" src="/Content/images/edit-icon.png"/>
                        </a>
                        <!-- ko if: $parent.CommentSupportsApproving() && CommentView() != "No comment" -->
                        <!-- /ko -->
                        <!-- /ko -->
                        <span class="lightergrey pull-right">
                            <span data-bind="cutSurname: User"/>
                            <span data-bind="relativeDateFormat: CommentDateView"/>
                        </span>
                    </div>
                </div>
            </div>
            <!-- Editable comment - temporarily hidden -->
            <!-- ko if: $parent.isEnabled("Edit") -->
            <div data-bind="template: { name: 'commentEditControl', data: $data }">
                <div class="labelgrey" style="background-color: rgb(255, 255, 255); padding: 1px; margin: 5px 0px; border: 1px solid rgb(110, 121, 131); display: block;" data-bind="style: { display: editMode() ? 'block' : 'none' }">
                    <textarea id="editcommenttext_0bf0e2db-0662-4b13-8a3c-1840cca79ba6" class="latestComment limitedText editCommentTextArea" data-bind="value: CommentUpdate, valueUpdate: 'afterkeydown', attr: {id: 'editcommenttext_'+$parentContext.$parent.Id()}" style="font-size: 12px; line-height: 18px; width: 100%; background-color: #FFF; border: 0px; resize: none; padding: 0px; margin: 0px; min-height: 54px"/>
                    <span class="validationMessage" style="display: none;"/>
                    <div style="background-color: #6E7983; padding: 5px;">
                        <a id="editcommentsave_0bf0e2db-0662-4b13-8a3c-1840cca79ba6" class="btn btn-small btn-info" data-bind="event: { click: function (data, parent) { saveComment($parentContext.$parent) } }, attr: {id: 'editcommentsave_'+$parentContext.$parent.Id()}" style="margin-right: 7px;" title="Save Comment" href="#">                 Save             </a>
                        <a id="cancelComment" class="cancel" data-bind="click: cancelComment" href="#">Cancel</a>
                        <div style="float: right; font-size: 10px; color: #FFF;">
                            <span class="limitedTextCharactersCount" data-bind="text: RemainingCharacterCount">240</span>
                             characters             
                        </div>
                    </div>
                </div>
            </div>
            <!-- /ko -->
        </div>
    </div>
</td>

我尝试使用 .//textarea[contains(@id,'editcommenttext')] 的 XPATH,我在 firepath 中将其验证为仅针对我想要的文本区域,但没有成功。有什么建议么?我可以让开发人员更改以使 selenium 在这里返回 true 的 HTML 是否有问题?

如果我删除 isDisplayed 检查然后继续使用我的代码,当我尝试输入单元格等时,我会收到一条错误消息,指出 .InvalidElementStateException: Element must not be hidden, disabled or read-only p>

我还尝试让开发人员给它一个 ID,这样我就可以通过 ID 找到对象并且没有区别。

所以关于这个对象的某些东西没有启用/可见,但我看不到什么(它在屏幕上清晰可见等(当我调试时,我给了它足够的时间在继续之前加载页面。

谢谢

我想我知道问题所在了! 当我使用 Selenium IDE 记录该过程时,它会将[3] 附加到 xpath,事实证明,当我认为这个对象是在运行时添加时,它实际上是被添加到所有行然后只是隐藏,所以现在我需要在我的对象检查中添加一些内容以运行与 XPATH/ID 匹配的所有对象,然后使用它首先遇到的既启用又可见的对象......我会确认是否是这种情况。

【问题讨论】:

    标签: java selenium webdriver


    【解决方案1】:

    这个问题的答案非常简单。我使用的 XPATH 不够具体,当我认为它只返回一个时返回多个对象,然后它将 Seleniums 的注意力引导到数组中不可见的第一个对象(因为它正确报告)。

    一旦我更改了返回匹配对象数组的方法并简单地循环,直到我找到一个既启用并显示为使用的对象,罗伯特是我母亲的兄弟。

    狡猾的 XPATH 问题来自这样一个事实,即我在 firepath 中检查了 XPATH(在 firefox 中),这正确地突出了我想要的对象 但是 selenium 可以以某种方式实际上是同一对象的倍数(尽管页面源没有显示超过 1 个对象),直到我使用 firefox Selenium 插件记录我的操作,我才突出显示。

    因此,这里学到的教训是,如果不先检查 Selenium IDE 就无法正常工作,则不要 100% 信任通过 firepath 生成的 XPATH...!

    【讨论】:

    • 谢谢!我一次又一次地验证,当我使用的选择器被传递给 jQuery 时,我只得到了一个结果,我不明白为什么相同的选择器会从 Selenium 中找到不可见的元素。就我而言(使用 .NET API),我没有使查询更具体,而是使用了browser.FindElementsById("an-input-field").First(e =&gt; e.Displayed).SendKeys("some input"); 等。
    【解决方案2】:

    您是如何搜索此对象的?例如:

    FindElement(By.Id("");
    

    我遇到了一个听起来与此相同的问题,解决方法是使用备用“By”。找到页面上的元素。这听起来很傻,实际上并没有解释问题的原因,但这为我解决了这个问题。

    或者,您是否尝试过在控件出现后显式等待片刻,以确保代码不会在元素实际可见之前尝试抓取它?

    【讨论】:

    • 我已经更新了我的帖子,但总结一下我正在传递By
    • 我也尝试过手动运行,并且可以 100% 确认该对象在尝试抓取它之前绝对可见:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多