Асинхронный/ожидающий шаблон в транспортир
Я пытаюсь использовать async
/await
с protractor
в TypeScript
. Я следую примеру: https://github.com/angular/protractor/tree/master/exampleTypescript/asyncAwait
Он отлично работает в моих экспериментах. Тем не менее, я должен использовать await
для каждого вызова, связанного с взаимодействием браузера.
Например:
У меня есть страница для страницы входа:
login.ts:
import {browser, element, by, By, $, $$, ExpectedConditions} from "protractor";
import { DashboardPage } from "./dashboard";
export class LoginPage {
usernameInput = element(by.id("username"));
passwordInput = element(by.id("password"));
loginButton = element(by.id("login_button"));
async get() {
await browser.get(login_url);
return this;
}
async getTitle() {
let title = await browser.getTitle();
return title;
}
async typeUsername(username: string) {
await this.usernameInput.sendKeys(username);
}
async typePassword(password: string) {
await this.passwordInput.sendKeys(password);
}
async login() {
await this.loginButton.click();
return new DashboardPage();
}
}
LoginSpec.ts:
import {browser, element, by, By, $, $$, ExpectedConditions} from "protractor";
import { LoginPage } from "../pages/login";
describe("Login Page", function() {
beforeEach(() => {
// login page is not an angular page.
browser.ignoreSynchronization = true;
});
afterEach(() => {
browser.ignoreSynchronization = false;
});
it("should go to dashboard page after successfully login", async (): Promise<any> => {
let loginPage = new LoginPage();
await loginPage.get();
await loginPage.typeUsername(username);
await loginPage.typePassword(password);
let dashboard = await loginPage.login();
expect(await dashboard.getTitle()).toEqual(`Dashboard`);
});
});
В приведенной выше спецификации теста я должен использовать много await
для всех вызовов взаимодействия с браузером. Это вводит много шаблонов для await
.
Вопрос в том, есть ли идея или способ уменьшить шаблон? Кроме того, правильно ли это использовать async
/await
с protractor
?
Ответы
Ответ 1
К сожалению, все эти ожидания не ожидаются - ваш код не будет синхронизирован должным образом. Есть несколько случаев, когда вы можете пропустить вставку в ожидании - но в большинстве случаев это необходимо, так как ожидается, что ваш график promises будет один за другим.
Async/Await все еще полагается на Promises. Таким образом, ваш код ожидания работает идентично этому:
it("should go to dashboard page after successfully login", (): Promise<any> => {
let loginPage = new LoginPage();
return loginPage.get().then(() => {
return loginPage.typeUsername(username);
}).then(() => {
return loginPage.typePassword(password);
}).then(()=> {
return loginPage.login();
}).then((dashboard)=> {
return expect(dashboard.getTitle()).toEqual(`Dashboard`);
})
});
Так что подумайте, как приятный синтаксический сахар над обещанием цепочки:
https://github.com/SeleniumHQ/selenium/wiki/WebDriverJs#option-1-use-classic-promise-chaining
Но есть способ синхронизации, не помещая awaits\thens\generators\callbacks. Он назывался "волокнами". К сожалению, транспортир не поддерживает это, но WebdriverIO использует его для синхронизации кода:
https://www.facebook.com/ProtractorAngularJS/posts/1950761568515087
Ответ 2
Вы можете легко запускать их последовательно, не используя await
, но я рекомендую придерживаться ожиданий для чтения.
Вот как выглядит ваш код без await
.
import { LoginPage } from "../pages/login";
describe("Login Page", function() {
// mutable crap
it("should go to dashboard page after successfully login", () => {
const loginPage = new LoginPage();
const asyncs = [
() => loginPage.get(),
() => loginPage.typeUsername(username),
() => loginPage.typePassword(password),
() => loginPage.login(),
(dashboard: Dashboard) => dashboard.getTitle()
];
const tilePromise = asyncs.reduce((promised, next) => promised.then(next));
// note the return. this is required
return titlePromise.then(dashboardTitle => {
expect(dashboardTitle).toEqual('Dashboard');
});
});
});
Опять же, я думаю, что await
предпочтительнее с точки зрения удобочитаемости, но на языке, который требует, чтобы вы его использовали, нет ничего.