Page Object — это паттерн проектирования, позволяющий изолировать работу с элементами страницы от логики тестов. Для каруселей и слайдеров использование Page Object особенно оправдано, так как такие компоненты имеют динамическое поведение: элементы появляются и исчезают, а действия могут зависеть от состояния слайдера.
Ключевые цели Page Object для слайдеров:
Page Object обычно включает:
Пример структуры 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 для проверки
кликабельности кнопок и видимости слайдов.Для тестирования правильности работы слайдера полезны методы, которые возвращают состояние компонента:
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'), если слайдеров несколько на
странице.console.log для переходов слайдов при отладке нестабильных
тестов.Использование Page Object для каруселей и слайдеров значительно упрощает поддержку и масштабирование тестов в Protractor, обеспечивая стабильность и повторяемость автоматизации.