我一直使用 protractor / Jasmine 2遇到过时元素引用异常的问题。
我的规格:
var LoginPage = require('../pages/login_page.js');
var WelcomePage = require('../pages/welcome_page.js');
describe('Test -> testing something', function () {
var loginPage;
var EC = protractor.ExpectedConditions;
var waitTimeout = 10000;
function logIn() {
loginPage.setUser('user');
loginPage.setPassword('password');
loginPage.login();
}
beforeEach(function () {
browser.ignoreSynchronization = true;
loginPage = new LoginPage();
browser.wait(EC.presenceOf(loginPage.userLogin), waitTimeout);
logIn();
var welcomePage = new WelcomePage();
browser.wait(EC.visibilityOf(welcomePage.usersButton), waitTimeout);
welcomePage.usersButton.click();
});
问题是,当我想单击usersButton时,StaleElementReferenceException随机发生在beforeEach函数的最后一行。
不知道为什么ExpectedCondition无法正常工作(尝试了不同的EC,例如presenceOf,elementToBeClickable等,但都没有解决问题)。
请参阅定义了usersButton的页面以供引用:
'use strict';
var WelcomePage = function () {
};
WelcomePage.prototype = Object.create({}, {
usersButton: {
get: function () {
return element(by.css('#users a'));
}
}
});
module.exports = WelcomePage;
我认为需要一些通用的retry_mechanism来处理它,有人有类似的问题吗?
最终这样写的功能
var clickOn = function (element) {
browser.wait(EC.visibilityOf(element), waitTimeout).then(function() {
element.click();
});}
像这样调用:
clickOn(welcomePage.usersButton);
更新:
已经测试了好几次,当我在硒网格上运行测试时,我仍然在这个确切的元素上收到Stale Element异常。因此提供的解决方案不起作用...
Failed: stale element reference: element is not attached to the page document (Session info: chrome=45.0.2454.93) (Driver info: chromedriver=2.19.346078 (6f1f0cde889532d48ce8242342d0b84f94b114a1),platform=Windows NT 6.1 SP1 x86_64) (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 15 milliseconds For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html Build info: version: '2.47.1', revision: '411b314', time: '2015-07-30 03:03:16' System info: host: 'ITHFPC17', ip: '10.98.0.48', os.name: 'Windows 7', os.arch: 'x86', os.version: '6.1', java.version: '1.8.0_40' Driver info: org.openqa.selenium.chrome.ChromeDriver Capabilities [{applicationCacheEnabled=false, rotatable=false, mobileEmulationEnabled=false, chrome={userDataDir=C:\Users\SELENI~1\AppData\Local\Temp\scoped_dir2384_11396}, takesHeapSnapshot=true, databaseEnabled=false, handlesAlerts=true, hasTouchScreen=false, version=45.0.2454.93, platform=XP, browserConnectionEnabled=false, nativeEvents=true, acceptSslCerts=true, locationContextEnabled=true, webStorageEnabled=true, browserName=chrome, takesScreenshot=true, javascriptEnabled=true, cssSelectorsEnabled=true}] Session ID: 3244710644015ee170986333564ab806
Failed: Wait timed out after 10032ms
下一种方法是等到元素存在,然后再显示它,然后再单击它,否则它不能正常工作。奇怪的是,在硒网格上一切正常,但是当我尝试在本地运行测试时,出现了前面提到的异常。
exports.clickOn = function (element) {
browser.wait(EC.presenceOf(element), waitTimeout).then(function () {
browser.wait(EC.visibilityOf(element), waitTimeout)
}).then(function () {
browser.wait(EC.elementToBeClickable(element), waitTimeout)
}).then(function () {
element.click();
});
};
有人知道如何处理吗? ...我被困住了。
最佳答案
通过解决等待elementToBeClickable()
函数返回的 promise ,等待直到该元素有资格被单击。还要确保在click()
之前完成您的操作,以便 protractor 可以按预期找到该元素。可能将所有 Action 彼此链接起来可能是一个很好的解决方案。这样就可以避免StaleElementReferenceException
错误。就是这样 -
browser.wait(EC.presenceOf(loginPage.userLogin), waitTimeout).then(function(){
logIn();
}).then(function(){
var welcomePage = new WelcomePage();
}).then(function(){
browser.wait(EC.elementToBeClickable(welcomePage.usersButton), waitTimeout).then(function(){
welcomePage.usersButton.click();
});
});
希望能帮助到你。