💻 Примеры: ожидания и AJAX в Selenium

← К оглавлению урока

⚡ Ключевые паттерны

# AJAX: ждём появления текста
wait.until(EC.text_to_be_present_in_element(
    (By.CLASS_NAME, "bg-success"), "Data loaded"
))

# Авторизация OrangeHRM: URL после логина
wait.until(EC.url_contains("dashboard"))

# Load delay: появление кнопки
button = wait.until(EC.presence_of_element_located(
    (By.XPATH, "//button[text()='Button Appearing After Delay']")
))

# Slow calculator: ввод + ожидание результата
delay_input.clear()
delay_input.send_keys("45")
wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, ".screen"), "15"))

Пример 1: Базовый pytest с явным ожиданием

Шаблон теста с WebDriverWait. Используется как основа для всех следующих примеров.

# test_basic_wait.py
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

@pytest.fixture
def driver():
    driver = webdriver.Chrome()
    driver.implicitly_wait(10)  # Неявное ожидание
    yield driver
    driver.quit()

def test_example(driver):
    driver.get("https://example.com")
    wait = WebDriverWait(driver, 10)

    element = wait.until(EC.visibility_of_element_located((By.ID, "some_id")))
    assert element.is_displayed(), "Элемент не найден!"

Пример 2: AJAX — ожидание загрузки данных

Кнопка запускает AJAX-запрос. После ответа сервера появляется элемент <p class="bg-success"> с текстом ответа.

# test_ajax.py
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

@pytest.fixture
def driver():
    driver = webdriver.Chrome()
    driver.get("https://example.com")  # Заменить на реальный URL страницы
    yield driver
    driver.quit()

def test_ajax_request(driver):
    wait = WebDriverWait(driver, 15)

    # Нажимаем кнопку, запускающую AJAX-запрос
    ajax_button = driver.find_element(By.ID, "ajaxButton")
    ajax_button.click()

    # Ожидаем появления нужного текста в элементе с классом bg-success
    result = wait.until(
        EC.text_to_be_present_in_element(
            (By.CLASS_NAME, "bg-success"),
            "Data loaded with AJAX get request."
        )
    )
    assert result, "Текст 'Data loaded with AJAX get request.' не появился!"
Почему text_to_be_present_in_element? После клика элемент появляется в DOM с задержкой, а нам нужно убедиться не только в его наличии, но и в конкретном тексте. presence_of_element_located недостаточно — элемент мог появиться с другим содержимым.

Пример 3: Ожидание кнопки с задержкой (load delay)

Страница http://www.uitestingplayground.com/loaddelay показывает кнопку «Button Appearing After Delay» только после истечения задержки.

# test_load_delay.py
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service

@pytest.fixture
def driver():
    service = Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service)
    driver.get("http://www.uitestingplayground.com/loaddelay")
    yield driver
    driver.quit()

def test_wait_for_button(driver):
    wait = WebDriverWait(driver, 15)

    # Ждём появления кнопки
    button = wait.until(
        EC.presence_of_element_located(
            (By.XPATH, "//button[text()='Button Appearing After Delay']")
        )
    )
    assert button.is_displayed(), "Кнопка не появилась!"

Пример 4: Авторизация OrangeHRM (вариант 1 — заголовок)

Логинимся на https://opensource-demo.orangehrmlive.com и ждём заголовка «Dashboard».

# test_orangehrm_title.py
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service

@pytest.fixture
def driver():
    service = Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service)
    driver.get("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login")
    yield driver
    driver.quit()

def test_login_to_orangehrm(driver):
    wait = WebDriverWait(driver, 10)

    # Ввод логина
    username_field = driver.find_element(By.NAME, "username")
    username_field.send_keys("Admin")

    # Ввод пароля
    password_field = driver.find_element(By.NAME, "password")
    password_field.send_keys("admin123")

    # Клик по кнопке Login
    login_button = driver.find_element(By.XPATH, "//button[@type='submit']")
    login_button.click()

    # Ждём заголовок "Dashboard"
    dashboard_header = wait.until(
        EC.text_to_be_present_in_element((By.TAG_NAME, "h6"), "Dashboard")
    )
    assert dashboard_header, "Заголовок 'Dashboard' не появился"

Пример 5: Авторизация OrangeHRM (вариант 2 — URL)

Та же авторизация, но проверяем URL вместо заголовка.

# test_orangehrm_url.py
def test_login_and_check_url(driver):
    wait = WebDriverWait(driver, 10)

    driver.find_element(By.NAME, "username").send_keys("Admin")
    driver.find_element(By.NAME, "password").send_keys("admin123")
    driver.find_element(By.XPATH, "//button[@type='submit']").click()

    # Ждём, пока URL содержит "dashboard"
    wait.until(EC.url_contains("dashboard"))

    assert "dashboard" in driver.current_url, \
        f"URL не содержит 'dashboard': {driver.current_url}"

Пример 6: Slow Calculator — задержка и результат

Калькулятор на https://bonigarcia.dev/selenium-webdriver-java/slow-calculator.html вычисляет результат с задержкой. Вводим 7 + 8 с задержкой 45 секунд и ждём результат 15.

# test_slow_calculator.py
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service

@pytest.fixture
def driver():
    service = Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service)
    driver.get("https://bonigarcia.dev/selenium-webdriver-java/slow-calculator.html")
    yield driver
    driver.quit()

def test_slow_calculator(driver):
    wait = WebDriverWait(driver, 50)  # Ожидание результата до 50 секунд

    # Устанавливаем задержку 45 секунд в поле #delay
    delay_input = driver.find_element(By.CSS_SELECTOR, "#delay")
    delay_input.clear()
    delay_input.send_keys("45")

    # Нажимаем кнопки: 7, +, 8, =
    driver.find_element(By.XPATH, "//span[text()='7']").click()
    driver.find_element(By.XPATH, "//span[text()='+']").click()
    driver.find_element(By.XPATH, "//span[text()='8']").click()
    driver.find_element(By.XPATH, "//span[text()='=']").click()

    # Ждём появления результата "15" через 45 секунд
    result = wait.until(
        EC.text_to_be_present_in_element((By.CSS_SELECTOR, ".screen"), "15")
    )
    assert result, "Результат '15' не отобразился!"
Почему timeout=50, а задержка=45? Нужен запас — WebDriverWait должен ждать дольше, чем реальная задержка страницы, иначе получим TimeoutException раньше, чем появится результат.