Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f2c7839684 | ||
![]() |
90bed51df4 | ||
![]() |
4d10c1446f | ||
![]() |
97f6075658 |
8
README.md
Normal file
8
README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Итоговое задание для магазина "Регард" с использованием Cucumber.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
"Идеальная реализация должна позволить в теории создать третий похожий сценарий с другими категориями товаров, не написав ни единой дополнительной строчки Java кода."
|
||||||
|
- такого не получилось, пришлось добавить один степ для второго сценария
|
113
pom.xml
113
pom.xml
@ -1,22 +1,34 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||||
|
http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>ru.ibs</groupId>
|
<groupId>ru.ibs</groupId>
|
||||||
<artifactId>sel1</artifactId>
|
<artifactId>sel1</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
<name>Archetype - sel1</name>
|
<name>Archetype - sel1</name>
|
||||||
<url>https://git.goodtester.ru</url>
|
<url>https://git.goodtester.ru</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<aspectj.version>1.9.7</aspectj.version>
|
||||||
|
<allure.version>2.13.5</allure.version>
|
||||||
|
<cucumber.version>7.15.0</cucumber.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
|
<!-- Selenium -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.seleniumhq.selenium</groupId>
|
<groupId>org.seleniumhq.selenium</groupId>
|
||||||
<artifactId>selenium-java</artifactId>
|
<artifactId>selenium-java</artifactId>
|
||||||
<version>4.33.0</version>
|
<version>4.33.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/junit/junit -->
|
<!-- JUnit -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
@ -24,7 +36,98 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Cucumber -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.cucumber</groupId>
|
||||||
|
<artifactId>cucumber-java</artifactId>
|
||||||
|
<version>${cucumber.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.cucumber</groupId>
|
||||||
|
<artifactId>cucumber-junit</artifactId>
|
||||||
|
<version>${cucumber.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Allure -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.qameta.allure</groupId>
|
||||||
|
<artifactId>allure-junit4</artifactId>
|
||||||
|
<version>${allure.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.qameta.allure</groupId>
|
||||||
|
<artifactId>allure-cucumber7-jvm</artifactId>
|
||||||
|
<version>2.25.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- AspectJ -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aspectj</groupId>
|
||||||
|
<artifactId>aspectjweaver</artifactId>
|
||||||
|
<version>${aspectj.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
<build>
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<!-- Компиляция -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${maven.compiler.source}</source>
|
||||||
|
<target>${maven.compiler.target}</target>
|
||||||
|
<encoding>${encoding}</encoding>
|
||||||
|
<parameters>true</parameters> <!-- для удобства рефлексии, если используешь -->
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- Запуск тестов + Allure -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>3.0.0-M5</version>
|
||||||
|
<configuration>
|
||||||
|
<testFailureIgnore>true</testFailureIgnore>
|
||||||
|
<argLine>
|
||||||
|
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
|
||||||
|
</argLine>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<allure.results.directory>${project.build.directory}/allure-results</allure.results.directory>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
<!-- Чтобы запускались все тесты, убери includes или добавь там все свои -->
|
||||||
|
<!-- <includes>
|
||||||
|
<include>**/CucumberRunner.java</include>
|
||||||
|
</includes> -->
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- Allure отчет -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>io.qameta.allure</groupId>
|
||||||
|
<artifactId>allure-maven</artifactId>
|
||||||
|
<version>2.10.0</version>
|
||||||
|
<configuration>
|
||||||
|
<reportVersion>2.10.0</reportVersion>
|
||||||
|
<resultsDirectory>${project.build.directory}/allure-results</resultsDirectory>
|
||||||
|
<reportDirectory>${project.build.directory}/allure-report</reportDirectory>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>report</id>
|
||||||
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>report</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
|
16
src/test/java/ru/ibs/framework/RegardTestRunner.java
Normal file
16
src/test/java/ru/ibs/framework/RegardTestRunner.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package ru.ibs.framework;
|
||||||
|
|
||||||
|
import io.cucumber.junit.Cucumber;
|
||||||
|
import io.cucumber.junit.CucumberOptions;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@RunWith(Cucumber.class)
|
||||||
|
@CucumberOptions(
|
||||||
|
features = "src/test/resources/features",
|
||||||
|
glue = "ru.ibs.tests",
|
||||||
|
plugin = {
|
||||||
|
"pretty",
|
||||||
|
"io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public class RegardTestRunner {}
|
@ -1,45 +1,46 @@
|
|||||||
package ru.ibs.framework.pages;
|
package ru.appline.framework.pages;
|
||||||
|
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.JavascriptExecutor;
|
import org.openqa.selenium.JavascriptExecutor;
|
||||||
|
import org.openqa.selenium.Keys;
|
||||||
import org.openqa.selenium.WebDriver;
|
import org.openqa.selenium.WebDriver;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.PageFactory;
|
|
||||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
import ru.ibs.framework.managers.DriverManager;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class BasePage {
|
public abstract class BasePage {
|
||||||
|
protected WebDriver driver;
|
||||||
|
protected WebDriverWait wait;
|
||||||
|
|
||||||
protected WebDriver driver = DriverManager.getDriverManager().getDriver();
|
public BasePage(WebDriver driver) {
|
||||||
protected WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
this.driver = driver;
|
||||||
|
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
||||||
public BasePage() {
|
|
||||||
PageFactory.initElements(driver, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fillInputField(By locator, String value) {
|
protected void click(By locator) {
|
||||||
WebElement el = waitUntilVisible(locator);
|
wait.until(ExpectedConditions.elementToBeClickable(locator)).click();
|
||||||
scrollToElement(el);
|
}
|
||||||
|
|
||||||
|
protected void type(By locator, String text) {
|
||||||
|
WebElement el = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
|
||||||
el.clear();
|
el.clear();
|
||||||
el.sendKeys(value);
|
el.sendKeys(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void scrollToElement(WebElement element) {
|
protected String getText(By locator) {
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
|
return wait.until(ExpectedConditions.visibilityOfElementLocated(locator)).getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected WebElement waitUntilVisible(By locator) {
|
protected List<WebElement> findElements(By locator) {
|
||||||
return wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
|
return wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(locator));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected WebElement waitUntilClickable(By locator) {
|
protected void waitForJSIdle() {
|
||||||
return wait.until(ExpectedConditions.elementToBeClickable(locator));
|
new WebDriverWait(driver, Duration.ofSeconds(15)).until(
|
||||||
}
|
wd -> ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete")
|
||||||
|
);
|
||||||
protected void waitUntilInvisible(By locator) {
|
|
||||||
wait.until(ExpectedConditions.invisibilityOfElementLocated(locator));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
55
src/test/java/ru/ibs/framework/pages/CatalogPage.java
Normal file
55
src/test/java/ru/ibs/framework/pages/CatalogPage.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package ru.ibs.framework.pages;
|
||||||
|
|
||||||
|
import org.openqa.selenium.*;
|
||||||
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
public class CatalogPage {
|
||||||
|
private final WebDriver driver;
|
||||||
|
private final WebDriverWait wait;
|
||||||
|
|
||||||
|
public CatalogPage(WebDriver driver) {
|
||||||
|
this.driver = driver;
|
||||||
|
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectCategory(String name) {
|
||||||
|
WebElement categoryLink = wait.until(ExpectedConditions.elementToBeClickable(
|
||||||
|
By.xpath("//a[text()='" + name + "']")));
|
||||||
|
categoryLink.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectCategoryMainMenu(String name) {
|
||||||
|
WebElement categoryLink = wait.until(ExpectedConditions.elementToBeClickable(
|
||||||
|
By.xpath("//a/div[text()='" + name + "']")));
|
||||||
|
categoryLink.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeCookieBannerIfPresent() {
|
||||||
|
try {
|
||||||
|
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
|
||||||
|
WebElement acceptButton = wait.until(ExpectedConditions.elementToBeClickable(
|
||||||
|
By.cssSelector("button.CookieBannerPopover_acceptBtn__VRuFj")));
|
||||||
|
acceptButton.click();
|
||||||
|
Thread.sleep(500);
|
||||||
|
} catch (TimeoutException | InterruptedException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectSubCategory(String name) {
|
||||||
|
closeCookieBannerIfPresent(); // Закрыть баннер если есть
|
||||||
|
|
||||||
|
WebElement subCategory = wait.until(ExpectedConditions.presenceOfElementLocated(
|
||||||
|
By.xpath("//p[contains(text(), '" + name + "')]/ancestor::a[1]")));
|
||||||
|
// Клик через JS:
|
||||||
|
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", subCategory);
|
||||||
|
((JavascriptExecutor) driver).executeScript("arguments[0].click();", subCategory);
|
||||||
|
|
||||||
|
// Ждём загрузки фильтра, чтобы убедиться, что перешли
|
||||||
|
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input[name='min']")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
54
src/test/java/ru/ibs/framework/pages/ListingPage.java
Normal file
54
src/test/java/ru/ibs/framework/pages/ListingPage.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package ru.ibs.framework.pages;
|
||||||
|
|
||||||
|
import org.openqa.selenium.*;
|
||||||
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ListingPage {
|
||||||
|
private final WebDriver driver;
|
||||||
|
private final WebDriverWait wait;
|
||||||
|
|
||||||
|
public ListingPage(WebDriver driver) {
|
||||||
|
this.driver = driver;
|
||||||
|
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinPrice(String price) {
|
||||||
|
WebElement minPrice = driver.findElement(By.cssSelector("input[name='min']"));
|
||||||
|
minPrice.clear();
|
||||||
|
minPrice.sendKeys(price);
|
||||||
|
minPrice.sendKeys(Keys.ENTER);
|
||||||
|
waitForJSIdle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<WebElement> getAllProducts() {
|
||||||
|
return driver.findElements(By.cssSelector("div.Card_wrap__hES44"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstProductTitle() {
|
||||||
|
return wait.until(ExpectedConditions.visibilityOfElementLocated(
|
||||||
|
By.cssSelector("a.CardText_link__C_fPZ > div.CardText_title__7bSbO"))).getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitForJSIdle() {
|
||||||
|
new WebDriverWait(driver, Duration.ofSeconds(10)).until(driver ->
|
||||||
|
((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectManufacturer(String name) {
|
||||||
|
|
||||||
|
WebElement checkbox = wait.until(ExpectedConditions.elementToBeClickable(
|
||||||
|
By.cssSelector("input[id*='" + name + "'] + label")));
|
||||||
|
checkbox.click();
|
||||||
|
waitForJSIdle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitForSearchResultsToUpdate(int expectedCount) {
|
||||||
|
wait.until(driver -> getAllProducts().size() <= expectedCount);
|
||||||
|
waitForJSIdle(); // если хочешь ещё чуть-чуть гарантии
|
||||||
|
}
|
||||||
|
}
|
19
src/test/java/ru/ibs/framework/pages/MainPage.java
Normal file
19
src/test/java/ru/ibs/framework/pages/MainPage.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// MainPage.java
|
||||||
|
package ru.ibs.framework.pages;
|
||||||
|
|
||||||
|
import org.openqa.selenium.By;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
|
||||||
|
public class MainPage {
|
||||||
|
private final WebDriver driver;
|
||||||
|
|
||||||
|
public MainPage(WebDriver driver) {
|
||||||
|
this.driver = driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openCatalog() {
|
||||||
|
WebElement catalogButton = driver.findElement(By.xpath("//span[text()='Каталог']/parent::button"));
|
||||||
|
catalogButton.click();
|
||||||
|
}
|
||||||
|
}
|
15
src/test/java/ru/ibs/framework/utils/AllureUtils.java
Normal file
15
src/test/java/ru/ibs/framework/utils/AllureUtils.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package ru.ibs.framework.utils;
|
||||||
|
|
||||||
|
import io.qameta.allure.Attachment;
|
||||||
|
import org.openqa.selenium.OutputType;
|
||||||
|
import org.openqa.selenium.TakesScreenshot;
|
||||||
|
import ru.ibs.framework.managers.DriverManager;
|
||||||
|
|
||||||
|
public class AllureUtils {
|
||||||
|
|
||||||
|
@Attachment(value = "Screenshot at step", type = "image/png")
|
||||||
|
public static byte[] attachScreenshot() {
|
||||||
|
return ((TakesScreenshot) DriverManager.getDriverManager().getDriver())
|
||||||
|
.getScreenshotAs(OutputType.BYTES);
|
||||||
|
}
|
||||||
|
}
|
22
src/test/java/ru/ibs/framework/utils/MyAllureListener.java
Normal file
22
src/test/java/ru/ibs/framework/utils/MyAllureListener.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package ru.ibs.framework.utils;
|
||||||
|
|
||||||
|
import io.qameta.allure.Attachment;
|
||||||
|
import org.junit.rules.TestWatcher;
|
||||||
|
import org.junit.runner.Description;
|
||||||
|
import org.openqa.selenium.OutputType;
|
||||||
|
import org.openqa.selenium.TakesScreenshot;
|
||||||
|
import ru.ibs.framework.managers.DriverManager;
|
||||||
|
|
||||||
|
public class MyAllureListener extends TestWatcher {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void failed(Throwable e, Description description) {
|
||||||
|
takeScreenshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Attachment(value = "Screenshot on failure", type = "image/png")
|
||||||
|
public byte[] takeScreenshot() {
|
||||||
|
return ((TakesScreenshot) DriverManager.getDriverManager().getDriver())
|
||||||
|
.getScreenshotAs(OutputType.BYTES);
|
||||||
|
}
|
||||||
|
}
|
@ -1,53 +0,0 @@
|
|||||||
package ru.ibs.tests;
|
|
||||||
|
|
||||||
import org.junit.*;
|
|
||||||
import org.openqa.selenium.By;
|
|
||||||
import ru.ibs.framework.managers.DriverManager;
|
|
||||||
|
|
||||||
public class ApplineBusinessTripTest extends BaseTests {
|
|
||||||
|
|
||||||
private LoginPage loginPage;
|
|
||||||
private DashboardPage dashboardPage;
|
|
||||||
private BusinessTripPage businessTripPage;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
// Получаем драйвер из DriverManager (инициализирован в BaseTests)
|
|
||||||
loginPage = new LoginPage(DriverManager.getDriverManager().getDriver());
|
|
||||||
|
|
||||||
// Открываем страницу логина
|
|
||||||
DriverManager.getDriverManager().getDriver().get("http://training.appline.ru/user/login");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void applineLoginScenario() {
|
|
||||||
dashboardPage = loginPage.login("Irina Filippova", "testing");
|
|
||||||
Assert.assertTrue("Dashboard not loaded", dashboardPage.isDashboardLoaded());
|
|
||||||
|
|
||||||
businessTripPage = dashboardPage.goToBusinessTrip();
|
|
||||||
Assert.assertTrue("Trips page not loaded", businessTripPage.isTripsPageLoaded());
|
|
||||||
|
|
||||||
businessTripPage.openCreateTripForm();
|
|
||||||
|
|
||||||
businessTripPage.selectDepartment("Отдел внутренней разработки");
|
|
||||||
businessTripPage.selectOrganization("Edge");
|
|
||||||
businessTripPage.setTicketsCheckbox(true);
|
|
||||||
businessTripPage.fillCity("Дмитров");
|
|
||||||
|
|
||||||
businessTripPage.fillDate(
|
|
||||||
By.xpath("//input[@placeholder='Укажите дату' and contains(@id, 'departureDatePlan')]"),
|
|
||||||
"01.01.2025"
|
|
||||||
);
|
|
||||||
|
|
||||||
businessTripPage.fillDate(
|
|
||||||
By.xpath("//input[@placeholder='Укажите дату' and contains(@id, 'returnDatePlan')]"),
|
|
||||||
"10.01.2025"
|
|
||||||
);
|
|
||||||
|
|
||||||
businessTripPage.saveAndClose();
|
|
||||||
|
|
||||||
Assert.assertTrue("Expected validation error not shown",
|
|
||||||
businessTripPage.isErrorDisplayed("Список командируемых сотрудников не может быть пустым"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package ru.ibs.tests;
|
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import ru.ibs.framework.managers.DriverManager;
|
|
||||||
|
|
||||||
public class BaseTests {
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void beforeAll() {
|
|
||||||
DriverManager.getDriverManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterAll() {
|
|
||||||
DriverManager.getDriverManager().quitDriver();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
package ru.ibs.tests;
|
|
||||||
|
|
||||||
import org.openqa.selenium.*;
|
|
||||||
import org.openqa.selenium.support.FindBy;
|
|
||||||
import org.openqa.selenium.support.PageFactory;
|
|
||||||
import org.openqa.selenium.support.ui.*;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
public class BusinessTripPage {
|
|
||||||
private final WebDriver driver;
|
|
||||||
private final WebDriverWait wait;
|
|
||||||
|
|
||||||
@FindBy(xpath = "//h1[contains(text(), 'Командировки')]")
|
|
||||||
private WebElement tripsHeader;
|
|
||||||
|
|
||||||
@FindBy(css = "div.pull-left.btn-group.icons-holder")
|
|
||||||
private WebElement createTripButton;
|
|
||||||
|
|
||||||
@FindBy(xpath = "//h1[@class='user-name' and contains(text(), 'Создать командировку')]")
|
|
||||||
private WebElement createTripHeader;
|
|
||||||
|
|
||||||
@FindBy(xpath = "//select[contains(@name,'businessUnit')]")
|
|
||||||
private WebElement departmentSelect;
|
|
||||||
|
|
||||||
@FindBy(id = "company-selector-show")
|
|
||||||
private WebElement companySelectorShow;
|
|
||||||
|
|
||||||
@FindBy(css = "span.select2-chosen")
|
|
||||||
private WebElement organizationSpan;
|
|
||||||
|
|
||||||
@FindBy(css = "input.select2-input")
|
|
||||||
private WebElement organizationInput;
|
|
||||||
|
|
||||||
@FindBy(xpath = "//label[contains(text(),'Заказ билетов')]/preceding-sibling::input")
|
|
||||||
private WebElement ticketsCheckbox;
|
|
||||||
|
|
||||||
@FindBy(xpath = "//button[contains(text(),'Сохранить и закрыть')]")
|
|
||||||
private WebElement saveAndCloseButton;
|
|
||||||
|
|
||||||
public BusinessTripPage(WebDriver driver) {
|
|
||||||
this.driver = driver;
|
|
||||||
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
|
||||||
PageFactory.initElements(driver, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTripsPageLoaded() {
|
|
||||||
return wait.until(ExpectedConditions.visibilityOf(tripsHeader)).isDisplayed();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void openCreateTripForm() {
|
|
||||||
wait.until(ExpectedConditions.elementToBeClickable(createTripButton)).click();
|
|
||||||
wait.until(ExpectedConditions.visibilityOf(createTripHeader));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void selectDepartment(String departmentName) {
|
|
||||||
Select select = new Select(departmentSelect);
|
|
||||||
select.selectByVisibleText(departmentName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void selectOrganization(String orgName) {
|
|
||||||
companySelectorShow.click();
|
|
||||||
wait.until(ExpectedConditions.elementToBeClickable(organizationSpan)).click();
|
|
||||||
wait.until(ExpectedConditions.visibilityOf(organizationInput)).sendKeys(orgName);
|
|
||||||
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//span[@class='select2-match' and text()='" + orgName + "']"))).click();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTicketsCheckbox(boolean checked) {
|
|
||||||
if (ticketsCheckbox.isSelected() != checked) {
|
|
||||||
ticketsCheckbox.click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fillCity(String city) {
|
|
||||||
By cityInputLocator = By.xpath("//input[contains(@id,'arrivalCity')]");
|
|
||||||
WebElement cityInput = wait.until(ExpectedConditions.visibilityOfElementLocated(cityInputLocator));
|
|
||||||
scrollToElement(cityInput);
|
|
||||||
cityInput.clear();
|
|
||||||
cityInput.sendKeys(city);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fillDate(By dateLocator, String dateValue) {
|
|
||||||
WebElement dateInput = wait.until(ExpectedConditions.elementToBeClickable(dateLocator));
|
|
||||||
scrollToElement(dateInput);
|
|
||||||
dateInput.clear();
|
|
||||||
dateInput.sendKeys(dateValue);
|
|
||||||
dateInput.sendKeys(Keys.TAB);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveAndClose() {
|
|
||||||
scrollToElement(saveAndCloseButton);
|
|
||||||
saveAndCloseButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isErrorDisplayed(String errorText) {
|
|
||||||
By errorLocator = By.xpath("//span[@class='validation-failed' and contains(text(), '" + errorText + "')]");
|
|
||||||
return wait.until(ExpectedConditions.visibilityOfElementLocated(errorLocator)).isDisplayed();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scrollToElement(WebElement element) {
|
|
||||||
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
package ru.ibs.tests;
|
|
||||||
|
|
||||||
import org.openqa.selenium.WebDriver;
|
|
||||||
import org.openqa.selenium.WebElement;
|
|
||||||
import org.openqa.selenium.interactions.Actions;
|
|
||||||
import org.openqa.selenium.support.FindBy;
|
|
||||||
import org.openqa.selenium.support.PageFactory;
|
|
||||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
|
||||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
public class DashboardPage {
|
|
||||||
private final WebDriver driver;
|
|
||||||
private final WebDriverWait wait;
|
|
||||||
|
|
||||||
@FindBy(xpath = "//h1[@class='oro-subtitle' and contains(text(), 'Панель быстрого запуска')]")
|
|
||||||
private WebElement dashboardTitle;
|
|
||||||
|
|
||||||
@FindBy(xpath = "//span[text()='Расходы']/ancestor::li")
|
|
||||||
private WebElement expensesMenu;
|
|
||||||
|
|
||||||
@FindBy(xpath = "//a[@href='/business-trip/']/span[text()='Командировки']")
|
|
||||||
private WebElement businessTripLink;
|
|
||||||
|
|
||||||
public DashboardPage(WebDriver driver) {
|
|
||||||
this.driver = driver;
|
|
||||||
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
|
||||||
PageFactory.initElements(driver, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDashboardLoaded() {
|
|
||||||
return wait.until(ExpectedConditions.visibilityOf(dashboardTitle)).isDisplayed();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BusinessTripPage goToBusinessTrip() {
|
|
||||||
Actions actions = new Actions(driver);
|
|
||||||
actions.moveToElement(expensesMenu).perform();
|
|
||||||
wait.until(ExpectedConditions.elementToBeClickable(businessTripLink)).click();
|
|
||||||
return new BusinessTripPage(driver);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package ru.ibs.tests;
|
|
||||||
|
|
||||||
import org.openqa.selenium.WebDriver;
|
|
||||||
import org.openqa.selenium.WebElement;
|
|
||||||
import org.openqa.selenium.support.FindBy;
|
|
||||||
import org.openqa.selenium.support.PageFactory;
|
|
||||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
|
||||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
public class LoginPage {
|
|
||||||
private final WebDriver driver;
|
|
||||||
private final WebDriverWait wait;
|
|
||||||
|
|
||||||
@FindBy(id = "prependedInput")
|
|
||||||
private WebElement usernameInput;
|
|
||||||
|
|
||||||
@FindBy(id = "prependedInput2")
|
|
||||||
private WebElement passwordInput;
|
|
||||||
|
|
||||||
@FindBy(xpath = "//button[@type='submit']")
|
|
||||||
private WebElement loginButton;
|
|
||||||
|
|
||||||
public LoginPage(WebDriver driver) {
|
|
||||||
this.driver = driver;
|
|
||||||
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
|
||||||
PageFactory.initElements(driver, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DashboardPage login(String username, String password) {
|
|
||||||
wait.until(ExpectedConditions.visibilityOf(usernameInput)).clear();
|
|
||||||
usernameInput.sendKeys(username);
|
|
||||||
wait.until(ExpectedConditions.visibilityOf(passwordInput)).clear();
|
|
||||||
passwordInput.sendKeys(password);
|
|
||||||
wait.until(ExpectedConditions.elementToBeClickable(loginButton)).click();
|
|
||||||
return new DashboardPage(driver);
|
|
||||||
}
|
|
||||||
}
|
|
109
src/test/java/ru/ibs/tests/SearchSteps.java
Normal file
109
src/test/java/ru/ibs/tests/SearchSteps.java
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
package ru.ibs.tests;
|
||||||
|
|
||||||
|
import io.cucumber.java.After;
|
||||||
|
import io.cucumber.java.ru.Дано;
|
||||||
|
import io.cucumber.java.ru.И;
|
||||||
|
import io.cucumber.java.ru.Тогда;
|
||||||
|
|
||||||
|
import org.openqa.selenium.By;
|
||||||
|
import org.openqa.selenium.Keys;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
|
||||||
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
import ru.ibs.framework.managers.DriverManager;
|
||||||
|
import ru.ibs.framework.pages.CatalogPage;
|
||||||
|
import ru.ibs.framework.pages.ListingPage;
|
||||||
|
import ru.ibs.framework.pages.MainPage;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class SearchSteps {
|
||||||
|
|
||||||
|
WebDriver driver = DriverManager.getDriverManager().getDriver();
|
||||||
|
MainPage mainPage = new MainPage(driver);
|
||||||
|
CatalogPage catalogPage = new CatalogPage(driver);
|
||||||
|
ListingPage listingPage = new ListingPage(driver);
|
||||||
|
String savedProductTitle;
|
||||||
|
|
||||||
|
@Дано("Открываем сайт regard")
|
||||||
|
public void openSite() {
|
||||||
|
driver.get("https://regard.ru/");
|
||||||
|
driver.manage().window().maximize();
|
||||||
|
catalogPage.closeCookieBannerIfPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@И("Открываем меню Каталог")
|
||||||
|
public void openCatalog() {
|
||||||
|
mainPage.openCatalog();
|
||||||
|
}
|
||||||
|
|
||||||
|
@И("Выбираем раздел {string}")
|
||||||
|
public void chooseCategory(String category) {
|
||||||
|
catalogPage.selectCategory(category);
|
||||||
|
}
|
||||||
|
|
||||||
|
@И("Выбираем раздел меню {string}")
|
||||||
|
public void chooseCategoryMainMenu(String category) {
|
||||||
|
catalogPage.selectCategoryMainMenu(category);
|
||||||
|
}
|
||||||
|
|
||||||
|
@И("Выбираем подраздел {string}")
|
||||||
|
public void chooseSubCategory(String sub) {
|
||||||
|
catalogPage.selectSubCategory(sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
@И("Задаем цену от {string}")
|
||||||
|
public void setPrice(String price) {
|
||||||
|
listingPage.setMinPrice(price);
|
||||||
|
}
|
||||||
|
|
||||||
|
@И("Фильтруем по производителю {string}")
|
||||||
|
public void filterByManufacturer(String name) {
|
||||||
|
listingPage.selectManufacturer(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@И("Проверяем, что товаров не более {int}")
|
||||||
|
public void checkNumberOfProducts(int max) {
|
||||||
|
assertTrue(listingPage.getAllProducts().size() <= max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@И("Сохраняем наименование первого товара")
|
||||||
|
public void saveFirstProductName() {
|
||||||
|
savedProductTitle = listingPage.getFirstProductTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@И("Ищем товар по сохраненному имени")
|
||||||
|
public void searchSavedProduct() {
|
||||||
|
WebElement searchInput = driver.findElement(By.id("searchInput"));
|
||||||
|
searchInput.clear();
|
||||||
|
searchInput.sendKeys(savedProductTitle);
|
||||||
|
searchInput.sendKeys(Keys.ENTER);
|
||||||
|
|
||||||
|
// Ждем, пока появится хотя бы один товар на странице результатов поиска
|
||||||
|
new WebDriverWait(driver, Duration.ofSeconds(10)).until(
|
||||||
|
ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div.Card_wrap__hES44"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Тогда("На странице только один товар")
|
||||||
|
public void waitForProductsCountChange() {
|
||||||
|
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
||||||
|
int oldCount = listingPage.getAllProducts().size();
|
||||||
|
wait.until(driver -> driver.findElements(By.cssSelector("div.Card_wrap__hES44")).size() != oldCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@И("Название товара соответствует сохраненному")
|
||||||
|
public void titleShouldMatchSaved() {
|
||||||
|
assertEquals(savedProductTitle, listingPage.getFirstProductTitle());
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
DriverManager.getDriverManager().quitDriver();
|
||||||
|
}
|
||||||
|
}
|
15
src/test/resources/features/regard_search.feature
Normal file
15
src/test/resources/features/regard_search.feature
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# language: ru
|
||||||
|
Функциональность: Поиск видеокарты на сайте regard.ru
|
||||||
|
|
||||||
|
Сценарий: Поиск видеокарты Gigabyte с фильтрами и проверкой результатов
|
||||||
|
Дано Открываем сайт regard
|
||||||
|
И Открываем меню Каталог
|
||||||
|
И Выбираем раздел "Комплектующие для ПК"
|
||||||
|
И Выбираем подраздел "Видеокарты"
|
||||||
|
И Задаем цену от "20000"
|
||||||
|
И Фильтруем по производителю "Gigabyte"
|
||||||
|
И Проверяем, что товаров не более 24
|
||||||
|
И Сохраняем наименование первого товара
|
||||||
|
И Ищем товар по сохраненному имени
|
||||||
|
Тогда На странице только один товар
|
||||||
|
И Название товара соответствует сохраненному
|
15
src/test/resources/features/regard_search_keyboard.feature
Normal file
15
src/test/resources/features/regard_search_keyboard.feature
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# language: ru
|
||||||
|
Функциональность: Поиск клавиатур с фильтрами и проверкой
|
||||||
|
|
||||||
|
Сценарий: Поиск клавиатуры A4Tech с фильтром по цене
|
||||||
|
Дано Открываем сайт regard
|
||||||
|
И Открываем меню Каталог
|
||||||
|
И Выбираем раздел меню "Периферия"
|
||||||
|
И Выбираем подраздел "Клавиатуры"
|
||||||
|
И Задаем цену от "2000"
|
||||||
|
И Фильтруем по производителю "A4Tech"
|
||||||
|
И Проверяем, что товаров не более 24
|
||||||
|
И Сохраняем наименование первого товара
|
||||||
|
И Ищем товар по сохраненному имени
|
||||||
|
Тогда На странице только один товар
|
||||||
|
И Название товара соответствует сохраненному
|
Loading…
x
Reference in New Issue
Block a user