"陈旧元素引用"错误行为未定

Mor*_*bia 7 jasmine selenium-webdriver protractor

代码1:

element(by.id('myButtonId')).click();
return element(by.id('myValidationSummaryId')).getText().then(function (val) {
    return val;
});
Run Code Online (Sandbox Code Playgroud)

上面的代码工作很多次,然后它开始给出以下错误

"失败:陈旧元素引用:元素未附加到页面文档"

这个id"myValidationSummaryId"之前没有使用过,单击"myValidationSummaryId"中服务端提供的按钮发布表单和成功/失败消息.

代码2:

return element(by.id('myButtonId')).click().then(function () {
    return element(by.id('myValidationSummaryId')).getText().then(function (val) {
      return val;
    });
});
Run Code Online (Sandbox Code Playgroud)

修复代码如上所述固定原始问题并且它一直很好地工作很多次但后来它开始随机失败原始陈旧元素引用错误.

代码3:

return element(by.id('myButtonId')).click().then(function () {
    return element(by.id('myValidationSummaryId')).waitReady().then(function (isReady) {
        if (isReady) {
            return element(by.id('myValidationSummaryId')).getText().then(function (val) {
                return val;
            });
        } else {
            return 'Failed to check success/failure message';
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

然后我修复了上面的代码,现在它工作正常,waitReady函数主动等待一个元素存在并显示到指定的时间.

不应该是量角器/ WebdriverJS原本应该处理这个问题.

1>你能否解释为什么Code 1和Code 2有时会工作并且有时会失败?

2>您认为Code 3现在还好吗,并且每次都有效吗?

元素'myValidationSummaryId'只使用一次,然后点击,如果页面没有完全加载,如果元素尚未可用,它应该说没有找到元素,但为什么陈旧的元素引用?我使用pageLoadTimeout作为5分钟,页面加载几秒钟.这是非AngularJS应用程序和browser.ignoreSynchronization = true.

它到处谈论什么代码可以修复它,但没有发现为什么这种行为以及为什么WebdriverJS本身无法处理它.

wap*_*300 9

我认为我们不能确定为什么会发生这种情况,但你肯定并不孤单(1) (2).这可能是由于您的页面具体呈现的方式(例如您的应用程序/框架如何处理渲染DOM元素),或仅仅是Selenium /驱动程序.如果您对确切的解释感兴趣,如果使用Protractor错误报告系统,您可能会有更好的运气.

然而,一个很好的猜测可能是它与Selenium 定义陈旧元素的方式有关:

一个不太常见但仍然常见的原因是JS库删除了一个元素并将其替换为具有相同ID或属性的元素

有些库可以欺骗Selenium相信一个元素已经从DOM中消失了,但它实际上只是瞬间被替换了.在点击和放置在DOM中的元素(基本上是竞争条件)之间添加一个紧密,脆弱的时间 - 这可能是原因.您可能有兴趣在这里阅读更多相关内容.

无论如何,如果您遇到此类问题,我建议您使用browser.wait和预期条件.

预期的条件基本上是返回true或false的函数,并且您可以指定一个超时,如果在那段时间内没有返回true,则会导致测试失败 - 您可以看到它在类似问题中的使用方式.

基本上,您可能希望这样做:

var EC = protractor.ExpectedConditions;
var summaryId = element(by.id('myValidationSummaryId'));

browser.wait(EC.presenceOf(summaryId), 5000);
//rest of your code
Run Code Online (Sandbox Code Playgroud)