Page Object для карусели и слайдеров

Основные принципы Page Object

Page Object — это паттерн проектирования, позволяющий изолировать работу с элементами страницы от логики тестов. Для каруселей и слайдеров использование Page Object особенно оправдано, так как такие компоненты имеют динамическое поведение: элементы появляются и исчезают, а действия могут зависеть от состояния слайдера.

Ключевые цели Page Object для слайдеров:

  • Централизация селекторов и действий с компонентом.
  • Обеспечение повторного использования кода в разных тестах.
  • Упрощение поддержки тестов при изменении верстки или логики слайдера.

Структура Page Object для слайдера

Page Object обычно включает:

  1. Селекторы элементов: кнопки навигации, элементы слайдов, индикаторы (точки).
  2. Методы действий: переход к следующему/предыдущему слайду, выбор конкретного слайда, получение текущего состояния.
  3. Методы проверок: проверка активного слайда, видимости элементов, корректности индикаторов.

Пример структуры Page Object для карусели:

const { element, by, browser, ExpectedConditions: EC } = require('protractor');

class Carousel {
    constructor(rootSelector) {
        this.root = element(by.css(rootSelector));
        this.slides = this.root.all(by.css('.slide'));
        this.nextButton = this.root.element(by.css('.carousel-next'));
        this.prevButton = this.root.element(by.css('.carousel-prev'));
        this.indicators = this.root.all(by.css('.carousel-indicator'));
    }

    async goToNextSlide() {
        await browser.wait(EC.elementToBeClickable(this.nextButton), 5000);
        await this.nextButton.click();
        await this.waitForSlideTransition();
    }

    async goToPrevSlide() {
        await browser.wait(EC.elementToBeClickable(this.prevButton), 5000);
        await this.prevButton.click();
        await this.waitForSlideTransition();
    }

    async goToSlide(index) {
        const indicator = this.indicators.get(index);
        await browser.wait(EC.elementToBeClickable(indicator), 5000);
        await indicator.click();
        await this.waitForSlideTransition();
    }

    async getActiveSlideIndex() {
        const activeSlide = this.slides.filter(async slide => {
            const classes = await slide.getAttribute('class');
            return classes.includes('active');
        }).first();
        return this.slides.indexOf(activeSlide);
    }

    async waitForSlideTransition(timeout = 5000) {
        const activeSlide = this.root.element(by.css('.slide.active'));
        await browser.wait(EC.visibilityOf(activeSlide), timeout);
    }
}

module.exports = Carousel;

Работа с динамическими элементами

Карусели часто используют анимации и асинхронную подгрузку контента. Для надежного тестирования необходимо:

  • Использовать ExpectedConditions для проверки кликабельности кнопок и видимости слайдов.
  • Встраивать ожидания после действий, чтобы тест ждал завершения анимации.
  • Обрабатывать возможные состояния: пустой слайд, дублирующиеся элементы, lazy loading.

Методы проверки состояния

Для тестирования правильности работы слайдера полезны методы, которые возвращают состояние компонента:

async isSlideVisible(index) {
    const slide = this.slides.get(index);
    return await slide.isDisplayed();
}

async getSlidesCount() {
    return await this.slides.count();
}

async getIndicatorState(index) {
    const indicator = this.indicators.get(index);
    const classes = await indicator.getAttribute('class');
    return classes.includes('active');
}

Эти методы позволяют создавать тесты без жесткой привязки к конкретной структуре DOM, концентрируясь на логике поведения слайдера.

Интеграция с тестами

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

const Carousel = require('./carousel.po');

describe('Тестирование карусели', () => {
    const carousel = new Carousel('.carousel-container');

    it('должен переключать слайды по кнопке "вперед"', async () => {
        await browser.get('/carousel-page');
        const initialIndex = await carousel.getActiveSlideIndex();
        await carousel.goToNextSlide();
        const newIndex = await carousel.getActiveSlideIndex();
        expect(newIndex).not.toEqual(initialIndex);
    });

    it('должен переключать слайд по индикатору', async () => {
        await browser.get('/carousel-page');
        await carousel.goToSlide(2);
        const activeIndex = await carousel.getActiveSlideIndex();
        expect(activeIndex).toEqual(2);
    });
});

Рекомендации по поддержке

  • Изоляция селекторов: не использовать глобальные селекторы by.css('.slide'), если слайдеров несколько на странице.
  • Унификация методов: одинаковые действия для всех слайдеров реализовывать в базовом классе, расширяя его для конкретных компонентов.
  • Обработка анимаций: при сложных переходах стоит использовать таймеры или проверку CSS-свойств, чтобы убедиться в завершении анимации.
  • Логирование: полезно добавлять console.log для переходов слайдов при отладке нестабильных тестов.

Использование Page Object для каруселей и слайдеров значительно упрощает поддержку и масштабирование тестов в Protractor, обеспечивая стабильность и повторяемость автоматизации.