first commit
This commit is contained in:
commit
dc40c051b2
49
.gitignore
vendored
Normal file
49
.gitignore
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/java,maven
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=java,maven
|
||||||
|
|
||||||
|
### Java ###
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
replay_pid*
|
||||||
|
|
||||||
|
### Maven ###
|
||||||
|
target/
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
pom.xml.next
|
||||||
|
release.properties
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
buildNumber.properties
|
||||||
|
.mvn/timing.properties
|
||||||
|
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||||
|
.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
# Eclipse m2e generated files
|
||||||
|
# Eclipse Core
|
||||||
|
.project
|
||||||
|
# JDT-specific (Eclipse Java Development Tools)
|
||||||
|
.classpath
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/java,maven
|
BIN
chromedriver/chromedriver.exe
Normal file
BIN
chromedriver/chromedriver.exe
Normal file
Binary file not shown.
118
pom.xml
Normal file
118
pom.xml
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.example</groupId>
|
||||||
|
<artifactId>Homework-8</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version>
|
||||||
|
<aspectj.version>1.9.22</aspectj.version>
|
||||||
|
<allure-testng.version>2.27.0</allure-testng.version>
|
||||||
|
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testng</groupId>
|
||||||
|
<artifactId>testng</artifactId>
|
||||||
|
<version>7.10.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.qameta.allure</groupId>
|
||||||
|
<artifactId>allure-testng</artifactId>
|
||||||
|
<version>2.27.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.seleniumhq.selenium</groupId>
|
||||||
|
<artifactId>selenium-java</artifactId>
|
||||||
|
<version>4.20.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aspectj</groupId>
|
||||||
|
<artifactId>aspectjweaver</artifactId>
|
||||||
|
<version>1.9.22</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>ru.yandex.qatools.ashot</groupId>
|
||||||
|
<artifactId>ashot</artifactId>
|
||||||
|
<version>1.5.4</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aeonbits.owner</groupId>
|
||||||
|
<artifactId>owner</artifactId>
|
||||||
|
<version>1.0.12</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.qameta.allure</groupId>
|
||||||
|
<artifactId>allure-java-commons</artifactId>
|
||||||
|
<version>2.27.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- cucumber-testng -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.cucumber</groupId>
|
||||||
|
<artifactId>cucumber-testng</artifactId>
|
||||||
|
<version>7.17.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- cucumber-java -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.cucumber</groupId>
|
||||||
|
<artifactId>cucumber-java</artifactId>
|
||||||
|
<version>7.17.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- allure-cucumber-jvm -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.qameta.allure</groupId>
|
||||||
|
<artifactId>allure-cucumber-jvm</artifactId>
|
||||||
|
<version>2.20.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>3.2.5</version>
|
||||||
|
<configuration>
|
||||||
|
<argLine>-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/1.9.22/aspectjweaver-1.9.22.jar"</argLine>
|
||||||
|
<systemProperties>
|
||||||
|
<property>
|
||||||
|
<name>allure.results.directory</name>
|
||||||
|
<value>${project.build.directory}/allure-results</value>
|
||||||
|
</property>
|
||||||
|
</systemProperties>
|
||||||
|
</configuration>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aspectj</groupId>
|
||||||
|
<artifactId>aspectjweaver</artifactId>
|
||||||
|
<version>1.9.22</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>io.qameta.allure</groupId>
|
||||||
|
<artifactId>allure-maven</artifactId>
|
||||||
|
<version>2.12.0</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
7
src/main/java/org/example/Main.java
Normal file
7
src/main/java/org/example/Main.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package org.example;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello world!");
|
||||||
|
}
|
||||||
|
}
|
15
src/main/java/org/example/config/BaseCofig.java
Normal file
15
src/main/java/org/example/config/BaseCofig.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package org.example.config;
|
||||||
|
|
||||||
|
import org.aeonbits.owner.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Интерфейс с основной конфигурацией проекта
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Config.Sources({"classpath:config.properties"})
|
||||||
|
public interface BaseCofig extends Config {
|
||||||
|
|
||||||
|
String url();
|
||||||
|
String driverPath();
|
||||||
|
String driverProperty();
|
||||||
|
}
|
25
src/main/java/org/example/enums/Category.java
Normal file
25
src/main/java/org/example/enums/Category.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package org.example.enums;
|
||||||
|
|
||||||
|
public enum Category {
|
||||||
|
PRINTERS("26225"),
|
||||||
|
MONITORS("26309");
|
||||||
|
|
||||||
|
private String selector;
|
||||||
|
|
||||||
|
Category(String selector) {
|
||||||
|
this.selector = selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSelector() {
|
||||||
|
return selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Category findByName(String name) {
|
||||||
|
for (Category value : values()) {
|
||||||
|
if (name.equalsIgnoreCase(value.name())) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(String.format("Unknown category %s", name));
|
||||||
|
}
|
||||||
|
}
|
25
src/main/java/org/example/enums/Sort.java
Normal file
25
src/main/java/org/example/enums/Sort.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package org.example.enums;
|
||||||
|
|
||||||
|
public enum Sort {
|
||||||
|
PRICE_HIGH_TO_LOW( "2"),
|
||||||
|
PRICE_LOW_TO_HIGH("1");
|
||||||
|
|
||||||
|
private String selector;
|
||||||
|
|
||||||
|
Sort(String selector) {
|
||||||
|
this.selector = selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSelector() {
|
||||||
|
return selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Sort findByName(String name) {
|
||||||
|
for (Sort value : values()) {
|
||||||
|
if (name.equalsIgnoreCase(value.name())) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(String.format("Unknown sort type %s", name));
|
||||||
|
}
|
||||||
|
}
|
262
src/main/java/org/example/page/HomePage.java
Normal file
262
src/main/java/org/example/page/HomePage.java
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
33
src/main/java/org/example/utils/Waiters.java
Normal file
33
src/main/java/org/example/utils/Waiters.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package org.example.utils;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
import org.openqa.selenium.By;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
|
||||||
|
public class Waiters {
|
||||||
|
private WebDriver driver;
|
||||||
|
private WebDriverWait wait;
|
||||||
|
|
||||||
|
public Waiters(WebDriver driver) {
|
||||||
|
this.driver = driver;
|
||||||
|
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitForElementToBeClickable(String cssSelector) {
|
||||||
|
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(cssSelector)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitForElementToBeLocated(String cssSelector) {
|
||||||
|
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(cssSelector)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitInputValueToBe(String cssSelector, String text) {
|
||||||
|
wait.until(ExpectedConditions.textToBePresentInElementValue(By.cssSelector(cssSelector), text));
|
||||||
|
}
|
||||||
|
public void waitTextStartsWith(String cssSelector, String text) {
|
||||||
|
wait.until(ExpectedConditions.textToBePresentInElementLocated(By.cssSelector(cssSelector), text));
|
||||||
|
}
|
||||||
|
}
|
18
src/main/resources/logback.xml
Normal file
18
src/main/resources/logback.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>
|
||||||
|
%white(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1}): %msg%n%throwable
|
||||||
|
</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="info">
|
||||||
|
<appender-ref ref="Console" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
<logger name="org.example" level="debug" additivity="false">
|
||||||
|
<appender-ref ref="Console" />
|
||||||
|
</logger>
|
||||||
|
</configuration>
|
46
src/test/java/org/example/AvitoTest.java
Normal file
46
src/test/java/org/example/AvitoTest.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package org.example;
|
||||||
|
import org.example.page.HomePage;
|
||||||
|
import org.testng.annotations.BeforeMethod;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import io.qameta.allure.Description;
|
||||||
|
import io.qameta.allure.Feature;
|
||||||
|
import io.qameta.allure.Story;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Основной класс с тестами HomePage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Feature("Avito Test")
|
||||||
|
public class AvitoTest extends BaseTest {
|
||||||
|
private HomePage homePage;
|
||||||
|
|
||||||
|
@BeforeMethod
|
||||||
|
public void setUp() {
|
||||||
|
super.setUp();
|
||||||
|
homePage = new HomePage(driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(description = "Homework test")
|
||||||
|
@Description("My homework Avito test")
|
||||||
|
@Story("Search printers in Vladivostok")
|
||||||
|
public void testAvitoSearch() {
|
||||||
|
homePage.openAvito();
|
||||||
|
homePage.makeScreenshot();
|
||||||
|
homePage.selectCategory("26223");
|
||||||
|
homePage.makeScreenshot();
|
||||||
|
homePage.setSearchQuery("Принтер");
|
||||||
|
homePage.makeScreenshot();
|
||||||
|
homePage.setOnlyNew();
|
||||||
|
homePage.makeScreenshot();
|
||||||
|
homePage.openLocationChooser();
|
||||||
|
homePage.makeScreenshot();
|
||||||
|
homePage.setLocation("Владивосток");
|
||||||
|
homePage.makeScreenshot();
|
||||||
|
homePage.saveLocation();
|
||||||
|
homePage.makeScreenshot();
|
||||||
|
homePage.sort("2");
|
||||||
|
homePage.makeScreenshot();
|
||||||
|
homePage.printPrice(5);
|
||||||
|
}
|
||||||
|
}
|
54
src/test/java/org/example/BaseTest.java
Normal file
54
src/test/java/org/example/BaseTest.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package org.example;
|
||||||
|
import org.aeonbits.owner.ConfigFactory;
|
||||||
|
import org.example.config.BaseCofig;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.chrome.ChromeDriver;
|
||||||
|
import org.testng.annotations.AfterMethod;
|
||||||
|
import org.testng.annotations.BeforeMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Общий класс с настройками для всех тестов
|
||||||
|
*/
|
||||||
|
public abstract class BaseTest {
|
||||||
|
|
||||||
|
//создание экземпляра драйвера
|
||||||
|
/**
|
||||||
|
* Переменная с экземпляром драйвера
|
||||||
|
*/
|
||||||
|
protected WebDriver driver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Экземпляр конфигурации с общими параметрами
|
||||||
|
*/
|
||||||
|
|
||||||
|
private final BaseCofig config = ConfigFactory.create(BaseCofig.class, System.getenv());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Общие настройки для всех тестов, перед выполнением каждого
|
||||||
|
*/
|
||||||
|
@BeforeMethod
|
||||||
|
public void setUp(){
|
||||||
|
//Установка настройки с путём к Google драйверу
|
||||||
|
System.setProperty(config.driverProperty(), config.driverPath());
|
||||||
|
|
||||||
|
//Создание экземпляра драйвера
|
||||||
|
driver = new ChromeDriver();
|
||||||
|
|
||||||
|
//открытие страницы Google по url
|
||||||
|
driver.get(config.url());
|
||||||
|
|
||||||
|
//разворот окна на полный экран при открытии
|
||||||
|
driver.manage().window().maximize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Общие настройки для всех тестов, после выполнения каждого теста
|
||||||
|
*/
|
||||||
|
@AfterMethod
|
||||||
|
public void tearDown() throws InterruptedException {
|
||||||
|
|
||||||
|
//Остановка работы драйвера
|
||||||
|
driver.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
src/test/java/org/example/cucumber/RunCucumberTest.java
Normal file
23
src/test/java/org/example/cucumber/RunCucumberTest.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package org.example.cucumber;
|
||||||
|
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import io.cucumber.testng.AbstractTestNGCucumberTests;
|
||||||
|
import io.cucumber.testng.CucumberOptions;
|
||||||
|
import io.cucumber.testng.FeatureWrapper;
|
||||||
|
import io.cucumber.testng.PickleWrapper;
|
||||||
|
|
||||||
|
@CucumberOptions(
|
||||||
|
//папка, где хранится наша фича.
|
||||||
|
features = "src/test/resources/features",
|
||||||
|
//папка, где находятся наши стэпы (шаги).
|
||||||
|
glue = "org/example/cucumber/steps",
|
||||||
|
//задаём тип отчёта. Как именно он будет выглядеть.
|
||||||
|
plugin = {"pretty"}
|
||||||
|
)
|
||||||
|
public class RunCucumberTest extends AbstractTestNGCucumberTests {
|
||||||
|
@Test(groups = "cucumber", description = "Runs Cucumber Scenarios", dataProvider = "scenarios")
|
||||||
|
public void runScenario(PickleWrapper pickleWrapper, FeatureWrapper featureWrapper) {
|
||||||
|
super.runScenario(pickleWrapper, featureWrapper);
|
||||||
|
}
|
||||||
|
}
|
79
src/test/java/org/example/cucumber/steps/MyStepdefs.java
Normal file
79
src/test/java/org/example/cucumber/steps/MyStepdefs.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package org.example.cucumber.steps;
|
||||||
|
|
||||||
|
import org.aeonbits.owner.ConfigFactory;
|
||||||
|
import org.example.config.BaseCofig;
|
||||||
|
import org.example.enums.Category;
|
||||||
|
import org.example.enums.Sort;
|
||||||
|
import org.example.page.HomePage;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.chrome.ChromeDriver;
|
||||||
|
|
||||||
|
import io.cucumber.java.After;
|
||||||
|
import io.cucumber.java.en.And;
|
||||||
|
import io.cucumber.java.en.Given;
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
|
||||||
|
public class MyStepdefs {
|
||||||
|
private WebDriver driver;
|
||||||
|
|
||||||
|
private final BaseCofig config = ConfigFactory.create(BaseCofig.class, System.getenv());
|
||||||
|
|
||||||
|
private HomePage homePage;
|
||||||
|
|
||||||
|
@Given("I am on the Avito homepage")
|
||||||
|
public void iAmOnTheAvitoHomepage() {
|
||||||
|
System.setProperty(config.driverProperty(), config.driverPath());
|
||||||
|
driver = new ChromeDriver();
|
||||||
|
driver.get(config.url());
|
||||||
|
driver.manage().window().maximize();
|
||||||
|
|
||||||
|
homePage = new HomePage(driver);
|
||||||
|
homePage.openAvito();
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("I select category {string}")
|
||||||
|
public void iSelectCategory(String category) {
|
||||||
|
homePage.selectCategory(Category.findByName(category).getSelector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("I enter {string} in the search field")
|
||||||
|
public void iEnterInTheSearchField(String searchString) {
|
||||||
|
homePage.setSearchQuery(searchString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("I click on the regions dropdown")
|
||||||
|
public void iClickOnTheRegionsDropdown() {
|
||||||
|
homePage.openLocationChooser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("I enter {string} in the region field")
|
||||||
|
public void iEnterInTheRegionField(String location) {
|
||||||
|
homePage.setLocation(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("I click on the 'Show n ads' button")
|
||||||
|
public void iClickOnTheButton() {
|
||||||
|
homePage.saveLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("I activate the 'Only with photos' checkbox")
|
||||||
|
public void iActivateTheCheckbox() {
|
||||||
|
homePage.setOnlyNew();
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("I select {string} in the sorting dropdown")
|
||||||
|
public void iSelectInTheSortingDropdown(String sortType) {
|
||||||
|
homePage.sort(Sort.findByName(sortType).getSelector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("I should see the prices of the first {string} items in the console")
|
||||||
|
public void iShouldSeeThePricesOfTheFirstItemsInTheConsole(String quantity) {
|
||||||
|
homePage.printPrice(Integer.parseInt(quantity));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void closeBrowser() throws InterruptedException {
|
||||||
|
driver.close();
|
||||||
|
}
|
||||||
|
}
|
1
src/test/resources/allure.properties
Normal file
1
src/test/resources/allure.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
allure.results.directory=target/allure-results
|
3
src/test/resources/config.properties
Normal file
3
src/test/resources/config.properties
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
url = https://www.google.com/
|
||||||
|
driverPath = .\\chromedriver\\chromedriver.exe
|
||||||
|
driverProperty = webdriver.chrome.driver
|
17
src/test/resources/features/avito.feature
Normal file
17
src/test/resources/features/avito.feature
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
Feature: Avito search
|
||||||
|
|
||||||
|
Scenario Outline: Search for items
|
||||||
|
Given I am on the Avito homepage
|
||||||
|
When I select category "<category>"
|
||||||
|
And I enter "<StringForSearch>" in the search field
|
||||||
|
And I click on the regions dropdown
|
||||||
|
And I enter "<city>" in the region field
|
||||||
|
And I click on the 'Show n ads' button
|
||||||
|
And I activate the 'Only with photos' checkbox
|
||||||
|
And I select "<sort>" in the sorting dropdown
|
||||||
|
Then I should see the prices of the first "<quantity>" items in the console
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| category | StringForSearch | city | sort | quantity |
|
||||||
|
| PRINTERS | принтер | Владивосток | PRICE_HIGH_TO_LOW | 10 |
|
||||||
|
| MONITORS | монитор | Иркутск | PRICE_LOW_TO_HIGH | 7 |
|
Loading…
Reference in New Issue
Block a user