Angular Protractor-正在验证页面重定向



我正在Angular应用程序中编写一些E2E测试。我遇到的一个问题是,每当我重定向到新的路由时,我都想验证是否显示了正确的组件。由于某些原因,这总是导致以下错误的故障:

- Failed: script timeout

我一直在网上搜索,试图找到一个解决方案,但我找到的所有解决方案都不适合我。

示例

  • 等待Angular

browser.waitForAngular();

参考

  • 检查浏览器当前URL并与预期URL进行比较:
browser.driver.wait(() => {
browser.driver.getCurrentUrl().then((url) => {
return /expected-url/.test(url);
});
}, 10000);

参考


代码示例

以下是测试登录功能的代码示例。

登录页面对象类

import { browser, element, by } from 'protractor';
export class LoginPage {
private credentials: { username: string, password: string } = {
username: 'admin',
password: 'admin'
};
navigateTo() {
return browser.get(browser.baseUrl) as Promise<any>;
}
getLoginComponent() {
return element(by.css('ra-login'));
}
getUsernameTextbox() {
return element(by.css('ra-login [data-test-id="username"]'));
}
getPasswordTextbox() {
return element(by.css('ra-login [data-test-id="password"]'));
}
getLoginButton() {
return element(by.css('ra-login [data-test-id="login-btn"]'));
}
getSecurePage() {
return element(by.css('ra-secure-content'));
}
login(credentials: { username: string, password: string } = this.credentials) {
this.getUsernameTextbox().sendKeys(credentials.username);
this.getPasswordTextbox().sendKeys(credentials.password);
this.getLoginButton().click();
}
getErrorMessage() {
return element(by.css('ra-login [data-test-id="login-error"]'));
}
}

登录E2E规范文件

describe('Login Functionality', () => {
let loginPage: LoginPage;
beforeEach(() => {
loginPage = new LoginPage();
});
// Test runs successfully
it('should display login', () => {
loginPage.navigateTo();
expect(loginPage.getLoginComponent().isPresent()).toBeTruthy();
});
// Test runs successfully
it('should have the login button disabled', () => {
loginPage.navigateTo();
expect(loginPage.getLoginButton().isEnabled()).toBe(false);
});
// Test runs fails
it('should redirect to a secure page', () => {
loginPage.navigateTo();
loginPage.login();
expect(loginPage.getSecurePage().isPresent()).toBeTruthy();
});
afterEach(async () => {
// Assert that there are no errors emitted from the browser
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
expect(logs).not.toContain(jasmine.objectContaining({
level: logging.Level.SEVERE,
} as logging.Entry));
});
});

使用上面的代码,测试'should redirect to a secure page'失败。此测试试图验证成功登录后是否显示"安全内容"组件。该组件是一个包装组件,用于承载只有用户登录时才能显示的页面

页面重定向总是成功的,并且显示正确的页面。我的怀疑是,不知何故,测试试图在实际重定向之前获得元素?

我是E2E的新手,所以我不完全确定这是否是问题所在。


以防万一,这里是重要软件包的版本号:

  • 角度:8.2.14
  • Angular CLI:8.2.2
  • 白内障患者:5.4.2
  • 茉莉花:2.8.0

我建议您使用async/await语句结构。你的怀疑似乎是正确的,你面临的问题是因为承诺处理不当。

您可以尝试将规范编写为:

it('should redirect to a secure page', async() => {
await loginPage.navigateTo();
await loginPage.login();
expect(await(await loginPage.getSecurePage()).isPresent()).toBeTruthy();
});

还将导航和登录功能更改为:

async navigateTo() {
return await browser.get(browser.baseUrl);
}

只要有浏览器交互,就可以添加await,如果有任何await语句,就可以使函数异步。

参考:[1]:https://hackernoon.com/should-i-use-promises-or-async-await-126ab5c98789

u必须将promise与运算符then一起使用此解决方案对我有效如果你知道响应时间,你可以使用

browser.driver.sleep(1000)

但是一种糟糕的做法

注意:如果应用程序非常慢,那么是时候报告性能问题了。

在我的情况下,除了等待某些Promise对象外,我还有其他原因导致错误。长话短说我有一个间隔,负责向用户显示当前时间。由于间隔是一个异步函数,Protractor会假设Angular仍在运行某个函数,因此会一直等待Angular"响应"。

在Angular 2+中,为了满足这种情况,setInterval()函数需要在Angular区域之外运行。

示例

ngOnInit() {
this.now = new Date();
setInterval(() => {
this.now = new Date();
}, 1000);
}

只要页面上存在间隔为的组件,上述代码就会导致Protractor超时。

为了解决这个问题,我们可以使用NgZone

示例

import { NgZone } from '@angular/core';
constructor(private ngZone: NgZone) { }
ngOnInit() {
this.now = new Date();
// running setInterval() function outside angular
// this sets the asynchronous call to not run within the angular zone
this.ngZone.runOutsideAngular(() => {
setInterval(() => {
// update the date within angular, so that change detection is triggered
this.ngZone.runTask(() => {
this.now = new Date();
});
}, 1000);
});
}

参考

  • https://github.com/angular/protractor/issues/3349
  • https://www.youtube.com/watch?v=DltUEDy7ItY(谈zone.js及其在Angular中的作用(
  • https://christianliebel.com/2016/11/angular-2-protractor-timeout-heres-fix/

在我的测试中,我还添加了一个实用程序函数,它有助于等待元素在屏幕上显示。

import { ElementFinder, ExpectedConditions, browser } from 'protractor';
const until = ExpectedConditions;
export const waitForElement = (elementToFind: ElementFinder, timeout = 10000) => {
return browser.wait(until.presenceOf(elementToFind), timeout, 'Element not found');
};

然后在这样的测试中使用:

it('should redirect to a secure page', async () => {
loginPage.navigateTo();
loginPage.login();
const secureContent = loginPage.getSecureContentComponent();
waitForElement(secureContent);
expect(secureContent.isPresent()).toBe(true);
});

参考

  • https://stackoverflow.com/a/30207361/2312637

最新更新