Fluent Page Object Pattern

Fluent Page Object Pattern — это расширение классического паттерна Page Object, в котором методы страниц возвращают сам объект страницы или другой объект, позволяя выстраивать цепочки вызовов. Такой подход повышает читаемость тестов и упрощает их поддержку.


Принципы Fluent Page Object

  1. Методы возвращают this или другой объект Каждый метод, который выполняет действие на странице, должен возвращать объект страницы. Это позволяет строить цепочки:
await loginPage
    .enterUsername('user')
    .enterPassword('password')
    .submit();
  1. Разделение логики действий и проверок Методы действия (enterUsername, clickButton) отделяются от методов проверок (verifyLoginSuccess). Это делает код более модульным и удобным для повторного использования.

  2. Минимизация дублирования селекторов Все селекторы инкапсулируются внутри Page Object. Изменение разметки страницы требует правок только в одном месте.


Структура Page Object

Типичный Fluent Page Object содержит три блока:

  1. Селекторы элементов Сохраняются как приватные свойства класса.
class LoginPage {
    constructor(page) {
        this.page = page;
        this.usernameInput = page.locator('#username');
        this.passwordInput = page.locator('#password');
        this.submitButton = page.locator('#login');
    }
}
  1. Методы действий Каждый метод выполняет конкретное действие и возвращает this.
enterUsername(username) {
    this.usernameInput.fill(username);
    return this;
}

enterPassword(password) {
    this.passwordInput.fill(password);
    return this;
}

submit() {
    this.submitButton.click();
    return this;
}
  1. Методы проверок (Assertions) Методы для проверки состояния страницы могут возвращать булевы значения или сами объекты для продолжения цепочки.
async verifyLoginSuccess() {
    await expect(this.page.locator('#welcome')).toBeVisible();
    return this;
}

Преимущества использования Fluent Page Object

  • Читаемость тестов Цепочки методов создают «историю действий», понятную без комментариев.

  • Уменьшение повторяющегося кода Повторно используемые действия инкапсулируются в методах Page Object.

  • Гибкость и расширяемость Методы легко комбинируются, добавляются новые действия без изменения тестов.


Пример полного теста с Fluent Page Object

import { test, expect } from '@playwright/test';
import { LoginPage } from './pages/LoginPage';

test('Авторизация пользователя', async ({ page }) => {
    const loginPage = new LoginPage(page);

    await loginPage
        .enterUsername('user1')
        .enterPassword('securePass')
        .submit()
        .verifyLoginSuccess();
});

В этом примере видно, как методы страницы создают цепочку действий, превращая тест в понятный сценарий.


Продвинутые техники Fluent Page Object

  1. Методы возвращают разные страницы Иногда после действия пользователь попадает на другую страницу. Метод может возвращать новый объект Page Object:
submit() {
    this.submitButton.click();
    return new DashboardPage(this.page);
}
  1. Асинхронные методы с await внутри Все действия Playwright асинхронные, поэтому методы часто должны использовать async/await:
async enterUsername(username) {
    await this.usernameInput.fill(username);
    return this;
}
  1. Композиция действий Сложные сценарии можно объединять в методы более высокого уровня:
async loginAs(user, password) {
    return this
        .enterUsername(user)
        .enterPassword(password)
        .submit();
}

Практические рекомендации

  • Названия методов должны описывать конкретное действие, а не внутренние детали реализации.
  • Возврат this применим только для методов действия; методы проверки могут возвращать объекты результатов.
  • Поддерживать единую точку управления селекторами для удобного рефакторинга.
  • Не использовать цепочки для операций, которые могут вызвать ошибки, если предыдущий шаг не выполнен — лучше разделять на логические блоки.

Fluent Page Object Pattern в Playwright позволяет писать короткие, читаемые и поддерживаемые тесты, где каждый шаг описан как часть единого сценария, а структура кода остается модульной и расширяемой.