Page Object — это шаблон проектирования, который помогает упрощать тестирование пользовательских интерфейсов, инкапсулируя взаимодействие с элементами страницы в отдельные объекты. В контексте тестирования с Playwright создание Page Object позволяет повысить читаемость, поддерживаемость и переиспользуемость кода тестов. Однако для того, чтобы достичь максимальной эффективности, необходимо использовать возможности типизации, предоставляемые TypeScript, чтобы избежать ошибок на ранних стадиях разработки.
Типизированные Page Objects обеспечивают несколько важных преимуществ:
Типизированный Page Object — это класс, в котором определены все элементы и методы для взаимодействия с ними. Вместо использования строковых селекторов или абстрактных методов, в таких объектах используются типы данных, которые явно указывают на ожидаемый результат.
Пример:
import { Page, Locator } from '@playwright/test';
class LoginPage {
readonly page: Page;
readonly usernameInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
constructor(page: Page) {
this.page = page;
this.usernameInput = page.locator('input[name="username"]');
this.passwordInput = page.locator('input[name="password"]');
this.submitButton = page.locator('button[type="submit"]');
}
async login(username: string, password: string) {
await this.usernameInput.fill(username);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
}
В этом примере LoginPage — это типизированный Page
Object, где элементы страницы (поля ввода и кнопка) инкапсулированы в
свойствах класса, а метод login выполняет действия на
странице.
Основная цель Page Object — скрыть детали реализации работы с элементами страницы. Это упрощает тесты и делает их более читабельными. В случае типизированного подхода можно дополнительно инкапсулировать логику обработки ошибок, ожидания и другие аспекты взаимодействия с элементами.
Пример:
class LoginPage {
readonly page: Page;
readonly usernameInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
constructor(page: Page) {
this.page = page;
this.usernameInput = page.locator('input[name="username"]');
this.passwordInput = page.locator('input[name="password"]');
this.submitButton = page.locator('button[type="submit"]');
}
async login(username: string, password: string) {
await this.fillUsername(username);
await this.fillPassword(password);
await this.submitForm();
}
private async fillUsername(username: string) {
await this.usernameInput.fill(username);
await this.usernameInput.press('Tab');
}
private async fillPassword(password: string) {
await this.passwordInput.fill(password);
await this.passwordInput.press('Enter');
}
private async submitForm() {
await this.submitButton.click();
}
}
В этой реализации логика для ввода имени пользователя и пароля была вынесена в отдельные методы. Это упрощает повторное использование методов и делает их более изолированными и тестируемыми.
Playwright позволяет выполнять асинхронные операции, такие как ожидание появления элементов или успешного выполнения действия. В Page Object можно инкапсулировать эти операции, а типизация помогает четко определять, когда и как ожидаются результаты.
Пример использования ожиданий:
class LoginPage {
readonly page: Page;
readonly usernameInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
readonly errorMessage: Locator;
constructor(page: Page) {
this.page = page;
this.usernameInput = page.locator('input[name="username"]');
this.passwordInput = page.locator('input[name="password"]');
this.submitButton = page.locator('button[type="submit"]');
this.errorMessage = page.locator('div.error-message');
}
async login(username: string, password: string) {
await this.usernameInput.fill(username);
await this.passwordInput.fill(password);
await this.submitButton.click();
await this.page.waitForSelector(this.errorMessage, { state: 'visible' });
}
async getErrorMessage(): Promise<string> {
return await this.errorMessage.textContent();
}
}
Здесь добавлено ожидание появления сообщения об ошибке после отправки
формы. Типизация позволяет четко указать, что метод
getErrorMessage возвращает строку, а login
вызывает асинхронные операции, которые необходимо ожидать.
Типизированные Page Objects хорошо подходят для параметризации тестов. Вместо того чтобы дублировать логику во многих местах, можно создавать универсальные методы и переиспользовать их в разных тестах.
Пример параметризированного метода:
class FormPage {
readonly page: Page;
readonly textField: Locator;
readonly submitButton: Locator;
constructor(page: Page) {
this.page = page;
this.textField = page.locator('input[type="text"]');
this.submitButton = page.locator('button[type="submit"]');
}
async submitForm(value: string) {
await this.textField.fill(value);
await this.submitButton.click();
}
}
В этом примере метод submitForm можно использовать для
различных форм, передавая разные значения в качестве параметров.
Когда тесты требуют взаимодействия с несколькими страницами, типизированные Page Objects помогают структурировать код и избежать путаницы при управлении несколькими объектами. Для этого можно создать отдельные классы для каждой страницы.
Пример работы с несколькими страницами:
class HomePage {
readonly page: Page;
readonly navigateButton: Locator;
constructor(page: Page) {
this.page = page;
this.navigateButton = page.locator('button.navigate');
}
async goToLoginPage() {
await this.navigateButton.click();
}
}
class LoginPage {
readonly page: Page;
readonly usernameInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
constructor(page: Page) {
this.page = page;
this.usernameInput = page.locator('input[name="username"]');
this.passwordInput = page.locator('input[name="password"]');
this.submitButton = page.locator('button[type="submit"]');
}
async login(username: string, password: string) {
await this.usernameInput.fill(username);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
}
В этом примере взаимодействие между страницами инкапсулировано в
методах классов HomePage и LoginPage. Это
помогает четко разделить логику для каждой страницы и упростить переход
между ними.
Типизированные Page Objects в Playwright позволяют создавать чистый, поддерживаемый и масштабируемый код для автоматизации тестирования. Использование TypeScript повышает безопасность и удобство работы с тестами, делая взаимодействие с элементами страницы явным и легко поддерживаемым.