Selenium webdriver在浏览器中新添加的对象上从isDisplayed()返回false,然后返回InvalidElementStateException

时间:2014-05-23 15:51:28

标签: java selenium webdriver

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

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中进行了变换,只是针对我想要的textarea,但没有成功。有什么建议? HTML有什么问题我可以让开发人员改变以使selenium在这里返回true吗?

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

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

关于这个对象的某些东西没有启用/可见但是我看不清楚它是什么(它在屏幕上清晰可见等等(当我调试时我给它足够的时间来加载页面然后再继续)。

由于

我认为我知道问题是什么! 当我使用Selenium IDE记录进程时,它将[3]附加到xpath,结果表明当我认为在运行时添加此对象时,实际上它被添加到所有行上然后只是隐藏,所以现在我需要在我的对象检查中添加一些东西来运行所有匹配XPATH / ID的对象,然后使用它首先遇到的那个既启用又可见....我会确认是否是这种情况

2 个答案:

答案 0 :(得分:7)

对此的答案令人沮丧地简单。我使用的XPATH不够具体,当我认为它只返回一个时返回多个对象,然后将Seleniums注意到数组中第一个不可见的(因为它正确报告)。

一旦我改变了我的方法以返回匹配对象的数组并直接循环直到找到一个既启用又显示使用罗伯特是我的母亲兄弟。

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

所以从这里学到的教训是,如果没有首先检查Selenium IDE,它似乎无法正常工作,则不信任通过firepath生成的XPATH ...!

答案 1 :(得分:0)

你是如何搜索这个对象的?例如:

FindElement(By.Id( “”);

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

或者,您是否尝试在控件可视化出现后使用显式等待,以确保代码在实际可见之前没有尝试抓取该元素?