This commit is contained in:
2026-02-14 21:56:07 +03:00
parent 895bea43d2
commit b414beb6fb
23 changed files with 694 additions and 250 deletions

View File

@@ -4,18 +4,31 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.WebDriverWait;
import ru.kovbasa.elements.Button;
import ru.kovbasa.utils.PageUtils;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CoursePage {
private static final Pattern PRICE_PATTERN = Pattern.compile("(\\d[\\d\\s\\u00A0]*)\\s*₽");
private final WebDriver driver;
private final By enrollButton = By.cssSelector("button[data-testid='enroll-button']");
private final By fullPriceTab = By.xpath("//div[normalize-space()='Полная']/parent::div");
private final By fullDiscountLabel = By.xpath("//p[contains(normalize-space(),'Полная стоимость со скидкой')]");
private final By anyPriceText = By.xpath("//*[contains(normalize-space(),'₽')]");
public CoursePage(WebDriver driver) {
this.driver = driver;
@@ -59,4 +72,68 @@ public class CoursePage {
public void clickEnroll() {
getEnrollButton().click();
}
}
public int getDiscountedFullPrice() {
PageUtils.removeBottomBanner(driver);
final WebDriverWait wait = new WebDriverWait(driver, java.time.Duration.ofSeconds(10));
final WebElement tab = wait.until(drv -> drv.findElements(fullPriceTab).stream()
.filter(WebElement::isDisplayed)
.findFirst()
.orElse(null));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView({block:'center'});", tab);
try {
tab.click();
} catch (RuntimeException ignored) {
new Actions(driver).moveToElement(tab).click().perform();
}
final WebElement label = wait.until(drv -> drv.findElements(fullDiscountLabel).stream()
.filter(WebElement::isDisplayed)
.findFirst()
.orElse(null));
final WebElement priceElement = findPriceElementNearLabel(label);
final String rawPrice = priceElement.getText();
return parsePrice(rawPrice);
}
public int getPriceForComparison() {
if (hasDisplayed(fullPriceTab)) {
try {
return getDiscountedFullPrice();
} catch (RuntimeException ignored) { }
}
final WebDriverWait wait = new WebDriverWait(driver, java.time.Duration.ofSeconds(10));
final WebElement priceElement = wait.until(drv -> drv.findElements(anyPriceText).stream()
.filter(WebElement::isDisplayed)
.filter(el -> PRICE_PATTERN.matcher(el.getText()).find())
.findFirst()
.orElse(null));
return parsePrice(priceElement.getText());
}
private WebElement findPriceElementNearLabel(WebElement label) {
try {
return label.findElement(By.xpath("following-sibling::div[1]"));
} catch (NoSuchElementException ignored) {
return label.findElement(By.xpath("following::div[contains(normalize-space(),'₽')][1]"));
}
}
private int parsePrice(String rawPrice) {
final Matcher matcher = PRICE_PATTERN.matcher(rawPrice);
if (!matcher.find()) {
throw new IllegalArgumentException("Не удалось распарсить цену из строки: " + rawPrice);
}
final String normalized = matcher.group(1).replace('\u00A0', ' ').replace(" ", "");
return Integer.parseInt(normalized);
}
private boolean hasDisplayed(By by) {
return driver.findElements(by).stream().anyMatch(WebElement::isDisplayed);
}
}