我正在Angular应用程序中编写一些E2E测试。我遇到的一个问题是,每当我重定向到新路由时,我都想验证是否显示了正确的组件。由于某些原因,这总是会导致失败并出现以下错误:
- Failed: script timeout
我一直在网上搜索以寻求解决方案,但是我发现的所有解决方案都不适用于我。
示例
browser.waitForAngular();
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的新手,所以我不确定这是否是问题所在。
以防万一,这是重要软件包的版本号:
答案 0 :(得分:0)
我建议您使用异步/等待语句结构。您的怀疑似乎已经纠正,并且您面临的问题是由于诺言处理不当。
您可以尝试将规范写为:
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
答案 1 :(得分:0)
u必须与操作符then
一起使用promise这个解决方案对我有用
如果您知道响应时间,可以使用
browser.driver.sleep(1000)
但这是一个坏习惯
注意:如果应用程序非常慢,则是时候报告性能问题了。
答案 2 :(得分:0)
就我而言,除了等待某些Promise对象外,我还有其他原因导致错误。长话短说,我有一个间隔,负责向用户显示当前时间。由于间隔是异步函数,因此量角器将假定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);
});
}
参考
zone.js
及其在Angular中的作用)在测试中,我还添加了一个实用程序功能,该功能有助于等待元素在屏幕上显示。
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);
});
参考