Protractor中Async/Await失效,禁用Promise Manager仍报错求助
嘿,我来帮你搞定这个问题!你遇到的报错根源是旧的ExpectedConditions和禁用Selenium Promise Manager(PM)后的Promise机制不兼容,再加上测试里的断言写法有问题,咱们一步步来修正:
1. 先搞懂报错原因
当你禁用PM后,Protractor不再使用旧的ManagedPromise,转而用原生ES6 Promise。但protractor.ExpectedConditions(也就是你代码里的EC)返回的是依赖旧PM的预期条件对象,直接传给browser.wait就会触发那个TypeError,因为它还在尝试创建已被禁用的ManagedPromise。
另外,你测试里的expect(ec.isVisible(...))写法也不对——ec.isVisible是async函数,返回的是Promise,不能直接丢给expect,得先await拿到结果再断言。
2. 修正ExpectedCondition类的isVisible方法
咱们调整expectedCondition.js,让它适配原生Promise:
const EC = protractor.ExpectedConditions; class ExpectedCondition { constructor() { this.el = new objects.Element(); } async isVisible(selector) { // getElement是同步创建元素定位器,不需要await const targetElement = this.el.getElement(selector); // browser.wait在禁用PM后返回原生Promise,直接await等待元素可见 await browser.wait( EC.visibilityOf(targetElement), 5000, // 设置超时时间,按需调整 `元素 ${selector} 在5秒内未出现` ); // 返回元素实际的可见状态,方便后续断言 return targetElement.isDisplayed(); } }
3. 修正测试用例里的断言写法
把测试里的expect改成先await拿到可见状态,再断言:
it('should fail to log in without credentials', async () => { await loginPage.submit(); // 先等待元素可见,再断言状态为true const emailErrorIsVisible = await ec.isVisible(loginPage.selectors.login.errors.lblEmailValidation); expect(emailErrorIsVisible).toBe(true); const passwordErrorIsVisible = await ec.isVisible(loginPage.selectors.login.errors.lblPasswordValidation); expect(passwordErrorIsVisible).toBe(true); });
4. 更可靠地禁用Promise Manager
你现在是在spec文件里设置protractor.promise.USE_PROMISE_MANAGER = false;,这可能会因为加载顺序问题导致失效。建议直接在protractor.conf.js配置文件里设置:
exports.config = { // ...其他配置项 SELENIUM_PROMISE_MANAGER: false, // ... }
这样能确保PM在测试启动时就被禁用,避免环境变量未正确识别的问题(也就是报错里的SELENIUM_PROMISE_MANAGER environment variable: undefined)。
5. 额外检查点
element.js里的getElement方法是同步的,没问题——element(by.css(...))只是创建一个元素定位器对象,实际查找元素是在调用click()/isDisplayed()等方法时才发生,所以不需要加async。- 确保所有异步操作都加了
await,你代码里的submit()、clickElement()这些已经处理好了,这点没问题。
按上面的步骤改完后,你的Async/Await测试应该就能正常运行啦!
内容的提问来源于stack exchange,提问作者catch22

