|
|
|
@ -0,0 +1,262 @@
|
|
|
|
|
package org.example.page;
|
|
|
|
|
|
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
|
|
|
|
|
|
import org.example.utils.Waiters;
|
|
|
|
|
import org.openqa.selenium.By;
|
|
|
|
|
import org.openqa.selenium.Keys;
|
|
|
|
|
import org.openqa.selenium.WebDriver;
|
|
|
|
|
|
|
|
|
|
import io.qameta.allure.Attachment;
|
|
|
|
|
import io.qameta.allure.Step;
|
|
|
|
|
import ru.yandex.qatools.ashot.AShot;
|
|
|
|
|
import ru.yandex.qatools.ashot.Screenshot;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Класс HomePage, в котором происходит взаимодействие со страницей Avito.
|
|
|
|
|
*/
|
|
|
|
|
public class HomePage {
|
|
|
|
|
private WebDriver driver;
|
|
|
|
|
private Waiters waiters;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Конструктор класса HomePage, который инициализирует драйвер WebDriver и объект Waiters.
|
|
|
|
|
* Конструктор используется для создания экземпляра класса HomePage, который представляет
|
|
|
|
|
* домашнюю страницу веб-сайта и предоставляет методы для взаимодействия с элементами на этой странице.
|
|
|
|
|
*
|
|
|
|
|
* @param driver экземпляр WebDriver, используемый для взаимодействия с веб-страницей.
|
|
|
|
|
*/
|
|
|
|
|
public HomePage(WebDriver driver) {
|
|
|
|
|
// Инициализация драйвера WebDriver для использования в текущем экземпляре класса
|
|
|
|
|
this.driver = driver;
|
|
|
|
|
// Создание нового объекта Waiters с переданным драйвером для ожидания элементов
|
|
|
|
|
this.waiters = new Waiters(driver);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Метод для перехода на главную страницу сайта Avito, используя WebDriver.
|
|
|
|
|
* Метод выполняет переход на указанный URL, который соответствует странице с объявлениями о транспортных средствах в Пензе.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@Step("Переход на главную страницу")
|
|
|
|
|
public void openAvito() {
|
|
|
|
|
// Переход на указанный URL с помощью WebDriver
|
|
|
|
|
driver.get("https://www.avito.ru/penza/transport?cd=1");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Выбор категории "Оргтехника и расходники" в пользовательском интерфейсе.
|
|
|
|
|
* Метод выполняет последовательность действий для выбора категории и подкатегории.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@Step("Выбор категории 'Оргтехника и расходники'")
|
|
|
|
|
public void selectCategory(String category) {
|
|
|
|
|
// Селектор для элемента, представляющего все категории
|
|
|
|
|
final var allCategoriesSelector = "[data-marker='top-rubricator/all-categories']";
|
|
|
|
|
// Ожидание, пока элемент с селектором allCategoriesSelector станет кликабельным
|
|
|
|
|
waiters.waitForElementToBeClickable(allCategoriesSelector);
|
|
|
|
|
// Нахождение элемента по селектору и выполнение клика
|
|
|
|
|
driver.findElement(By.cssSelector(allCategoriesSelector)).click();
|
|
|
|
|
|
|
|
|
|
// Селектор для элемента, представляющего конкретную категорию
|
|
|
|
|
final var categortySelector = "[data-marker='top-rubricator/root-category-26195']";
|
|
|
|
|
// Ожидание, пока элемент с селектором categorySelector станет кликабельным
|
|
|
|
|
waiters.waitForElementToBeClickable(categortySelector);
|
|
|
|
|
// Нахождение элемента по селектору и выполнение клика
|
|
|
|
|
driver.findElement(By.cssSelector(categortySelector)).click();
|
|
|
|
|
|
|
|
|
|
// Селектор для элемента, представляющего подкатегорию
|
|
|
|
|
final var subCategorySelector = String.format("[data-marker='top-rubricator/sub-category-%s']", category);
|
|
|
|
|
// Ожидание, пока элемент с селектором subCategorySelector станет кликабельным
|
|
|
|
|
waiters.waitForElementToBeClickable(subCategorySelector);
|
|
|
|
|
// Нахождение элемента по селектору и выполнение клика
|
|
|
|
|
driver.findElement(By.cssSelector(subCategorySelector)).click();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Метод для ввода запроса "Принтер" в поле поиска на веб-странице.
|
|
|
|
|
* Метод выполняет последовательность действий, включая ожидание доступности поля поиска,
|
|
|
|
|
* ввод запроса и подтверждение ввода с помощью клавиши Enter.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@Step("В поле поиска написать “Принтер”")
|
|
|
|
|
public void setSearchQuery(String searchString) {
|
|
|
|
|
// Селектор для элемента поля поиска
|
|
|
|
|
final var suggestFieldSelector = "[data-marker='search-form/suggest']";
|
|
|
|
|
// Ожидание, пока элемент с селектором suggestFieldSelector станет кликабельным
|
|
|
|
|
waiters.waitForElementToBeClickable(suggestFieldSelector);
|
|
|
|
|
// Нахождение элемента по селектору и сохранение его в переменную suggestField
|
|
|
|
|
final var suggestField = driver.findElement(By.cssSelector(suggestFieldSelector));
|
|
|
|
|
// Ввод запроса в поле поиска и подтверждение ввода с помощью клавиши Enter
|
|
|
|
|
suggestField.sendKeys(searchString, Keys.ENTER);
|
|
|
|
|
// Ожидание, пока значение в поле поиска станет равным введенному запросу
|
|
|
|
|
waiters.waitInputValueToBe(suggestFieldSelector, searchString);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Метод для активации чекбокса "Новые" на веб-странице.
|
|
|
|
|
* Метод выполняет последовательность действий, включая ожидание доступности чекбокса и его активацию.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@Step("Активировать чекбокс “Новые”")
|
|
|
|
|
public void setOnlyNew() {
|
|
|
|
|
// Селектор для элемента чекбокса "Новые"
|
|
|
|
|
// final var checkBoxSelector = "[data-marker='params[110396](431243)']";
|
|
|
|
|
final var checkBoxSelector = "[data-marker='field'] ul li label";
|
|
|
|
|
// Ожидание, пока элемент с селектором checkBoxSelector станет кликабельным
|
|
|
|
|
waiters.waitForElementToBeClickable(checkBoxSelector);
|
|
|
|
|
// Нахождение элемента по селектору и выполнение клика для активации чекбокса
|
|
|
|
|
driver.findElement(By.cssSelector(checkBoxSelector)).click();
|
|
|
|
|
waiters.waitForElementToBeClickable(checkBoxSelector);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Метод для автоматизации действия по открытию выпадающего списка регионов на странице.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@Step("Кликнуть по выпадающему списку регионов")
|
|
|
|
|
public void openLocationChooser() {
|
|
|
|
|
// Определение селектора для элемента, представляющего выпадающий список регионов
|
|
|
|
|
final var changeLocationSelector = "[data-marker='search-form/change-location']";
|
|
|
|
|
// Ожидание, пока элемент станет кликабельным, чтобы избежать ошибок при попытке клика
|
|
|
|
|
waiters.waitForElementToBeClickable(changeLocationSelector);
|
|
|
|
|
// Нахождение элемента по селектору и выполнение клика по нему
|
|
|
|
|
driver.findElement(By.cssSelector(changeLocationSelector)).click();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Вводит регион "Владивосток" в соответствующее поле на странице.
|
|
|
|
|
* Метод автоматизирует процесс ввода региона "Владивосток" в поле поиска региона на странице,
|
|
|
|
|
* включая очистку поля, ввод нового значения и выбор предложенного варианта.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@Step("Ввести регион “Владивосток”")
|
|
|
|
|
public void setLocation(String location) {
|
|
|
|
|
// Селектор для поля ввода региона
|
|
|
|
|
final var locationSelector = "[data-marker='popup-location/region/search-input']";
|
|
|
|
|
// Значение региона, которое нужно ввести
|
|
|
|
|
|
|
|
|
|
// Кликнуть на кнопку с крестиком для очистки поля
|
|
|
|
|
final var cleanLocationSelector = "[data-marker='popup-location/region/clearButton']";
|
|
|
|
|
waiters.waitForElementToBeClickable(cleanLocationSelector);
|
|
|
|
|
driver.findElement(By.cssSelector(cleanLocationSelector)).click();
|
|
|
|
|
// Ожидание, пока поле ввода станет пустым
|
|
|
|
|
waiters.waitInputValueToBe(locationSelector, "");
|
|
|
|
|
|
|
|
|
|
// Подождать возможности ввода региона
|
|
|
|
|
waiters.waitForElementToBeClickable(locationSelector);
|
|
|
|
|
final var locationField = driver.findElement(By.cssSelector(locationSelector));
|
|
|
|
|
// Ввести новую локацию
|
|
|
|
|
locationField.sendKeys(location);
|
|
|
|
|
// Подождать появления выпадающего списка
|
|
|
|
|
final var suggestListSelector = "[data-marker='popup-location/region/dropdown']";
|
|
|
|
|
final var suggestFirstSelector = "[data-marker='popup-location/suggest-0']";
|
|
|
|
|
final var suggestSecondSelector = "[data-marker='popup-location/suggest-1']";
|
|
|
|
|
waiters.waitForElementToBeClickable(suggestListSelector);
|
|
|
|
|
waiters.waitForElementToBeClickable(suggestFirstSelector);
|
|
|
|
|
waiters.waitTextStartsWith(suggestFirstSelector, location);
|
|
|
|
|
final var firstValue = driver.findElement(By.cssSelector(suggestFirstSelector));
|
|
|
|
|
final var secondValue = driver.findElement(By.cssSelector(suggestSecondSelector));
|
|
|
|
|
|
|
|
|
|
if (!firstValue.getText().contains(location + ",")) {
|
|
|
|
|
secondValue.click();
|
|
|
|
|
} else {
|
|
|
|
|
firstValue.click();
|
|
|
|
|
}
|
|
|
|
|
// locationField.sendKeys(Keys.ENTER);
|
|
|
|
|
waiters.waitInputValueToBe(locationSelector, location);
|
|
|
|
|
|
|
|
|
|
// Перейти на вкладку районы
|
|
|
|
|
final var districtTabSelector = "[data-marker='tab-marker/tab(districtsTab)']";
|
|
|
|
|
waiters.waitForElementToBeClickable(districtTabSelector);
|
|
|
|
|
driver.findElement(By.cssSelector(districtTabSelector)).click();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Нажимает на кнопку "Показать n объявлений" на странице.
|
|
|
|
|
* Метод автоматизирует действие пользователя по нажатию на кнопку "Показать n объявлений".
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@Step("Нажать на кнопку “Показать n объявлений”")
|
|
|
|
|
public void saveLocation() {
|
|
|
|
|
// Селектор для кнопки "Показать n объявлений"
|
|
|
|
|
final var saveLocationSelector = "[data-marker='popup-location/save-button']";
|
|
|
|
|
// Ожидание, пока элемент с кнопкой станет доступным для поиска на странице
|
|
|
|
|
waiters.waitForElementToBeLocated(saveLocationSelector);
|
|
|
|
|
// Нахождение элемента по селектору и выполнение клика по нему
|
|
|
|
|
driver.findElement(By.cssSelector(saveLocationSelector)).click();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Выбирает "Дороже" в выпадающем списке сортировки на странице.
|
|
|
|
|
* Метод автоматизирует процесс выбора опции "Дороже" в выпадающем списке сортировки,
|
|
|
|
|
* что позволяет сортировать объявления по цене в порядке убывания.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@Step("В выпадающем списке сортировки выбрать “Дороже”")
|
|
|
|
|
public void sort(String selector) {
|
|
|
|
|
// Селектор для элемента управления сортировкой
|
|
|
|
|
final var sortControlSelector = "[data-marker='sort/title']";
|
|
|
|
|
waiters.waitForElementToBeClickable(sortControlSelector);
|
|
|
|
|
// Нахождение элемента управления сортировкой и выполнение клика по нему
|
|
|
|
|
driver.findElement(By.cssSelector(sortControlSelector)).click();
|
|
|
|
|
// Селектор для опции сортировки "Дороже"
|
|
|
|
|
final var sortTypeSelector = String.format("[data-marker='sort/custom-option(%s)']", selector);
|
|
|
|
|
waiters.waitForElementToBeClickable(sortTypeSelector);
|
|
|
|
|
// Нахождение элемента опции сортировки "Дороже" и выполнение клика по нему
|
|
|
|
|
driver.findElement(By.cssSelector(sortTypeSelector)).click();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Выводит в консоль значение цены первых 5 товаров на странице.
|
|
|
|
|
* Данный метод автоматизирует процесс вывода в консоль значений цен первых 5 товаров.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@Step("Вывести в консоль Значение цены первых 5 товаров")
|
|
|
|
|
public void printPrice(int itemsCount) {
|
|
|
|
|
// Селекторы для нахождения каталога товаров и отдельного товара
|
|
|
|
|
final var itemsSelector = "[data-marker='catalog-serp']";
|
|
|
|
|
final var itemSelector = "[data-marker='item']";
|
|
|
|
|
// Селекторы для нахождения имени и цены товара
|
|
|
|
|
final var nameSelector = "[itemprop='name']";
|
|
|
|
|
final var priceSelector = "[data-marker='item-price']";
|
|
|
|
|
|
|
|
|
|
// Нахождение каталога с товарами на странице
|
|
|
|
|
final var root = driver.findElement(By.cssSelector(itemsSelector));
|
|
|
|
|
// Поиск всех товаров внутри каталога
|
|
|
|
|
final var items = root.findElements(By.cssSelector(itemSelector));
|
|
|
|
|
// Цикл по первым n товарам
|
|
|
|
|
for (int i = 0; i < itemsCount; i++) {
|
|
|
|
|
// Получение текущего товара
|
|
|
|
|
final var item = items.get(i);
|
|
|
|
|
// Получение наименования и цены товара
|
|
|
|
|
final var name = item.findElement(By.cssSelector(nameSelector)).getText();
|
|
|
|
|
final var price = item.findElement(By.cssSelector(priceSelector)).getText();
|
|
|
|
|
// Вывод информации о товаре и цене в консоль
|
|
|
|
|
System.out.println("Товар: " + name + ", цена: " + price);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Создаёт скриншот веб-страницы для Allure отчёта.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@Attachment
|
|
|
|
|
@Step("Make screenshot")
|
|
|
|
|
public byte[] makeScreenshot() {
|
|
|
|
|
// Создание скриншота веб-страницы с использованием AShot
|
|
|
|
|
final Screenshot screenshot = new AShot().takeScreenshot(driver);
|
|
|
|
|
// Создание Стрим-потока для сохранения скриншота
|
|
|
|
|
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
|
|
|
|
try {
|
|
|
|
|
ImageIO.write(screenshot.getImage(), "PNG", buffer);
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
return buffer.toByteArray();
|
|
|
|
|
}
|
|
|
|
|
}
|