✅ Решения практических заданий

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

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

# Alert: ждём через EC, затем работаем
alert = wait.until(EC.alert_is_present())
assert "Congrats" in Alert(browser).text

# Вкладки: запоминаем текущую, ищем новую
original = browser.current_window_handle
new = [h for h in browser.window_handles if h != original][0]
browser.switch_to.window(new)

# Hover: move_to_element каждый раз вызываем perform или цепочку
ActionChains(browser).move_to_element(el).perform()

# Drag-and-drop: один вызов
ActionChains(browser).drag_and_drop(src, tgt).perform()

# File upload: абсолютный путь
file_input.send_keys(os.path.abspath("test.txt"))

Решение 1: Заполнение huge_form + Alert

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


@pytest.fixture
def browser():
    driver = webdriver.Chrome()
    driver.maximize_window()
    yield driver
    driver.quit()


def test_fill_form_and_check_alert(browser):
    browser.get("http://suninjuly.github.io/huge_form.html")

    # Заполняем все поля: find_elements возвращает список
    input_fields = browser.find_elements(By.TAG_NAME, "input")
    for field in input_fields:
        field.clear()
        field.send_keys("Hello")

    browser.find_element(By.CLASS_NAME, "btn-default").click()

    # Ждём alert через EC — надёжнее, чем прямой switch_to.alert
    wait = WebDriverWait(browser, 10)
    alert = wait.until(EC.alert_is_present())

    alert_text = Alert(browser).text
    assert "Congrats, you've passed the task!" in alert_text
    alert.accept()

Логика: find_elements возвращает все input-теги, цикл заполняет каждый. EC.alert_is_present() гарантирует, что Alert уже появился перед чтением текста.

Решение 2: Math.html — вычисление + чекбокс + radio + Alert

# test_math_form.py
import pytest
import math
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


@pytest.fixture
def browser():
    driver = webdriver.Chrome()
    driver.maximize_window()
    yield driver
    driver.quit()


def calc(x):
    return str(math.log(abs(12 * math.sin(int(x)))))


def test_math_form(browser):
    browser.get("https://suninjuly.github.io/math.html")

    x_value = browser.find_element(By.ID, "input_value").text
    result = calc(x_value)

    browser.find_element(By.ID, "answer").send_keys(result)
    browser.find_element(By.ID, "robotCheckbox").click()
    browser.find_element(By.ID, "robotsRule").click()
    browser.find_element(By.CLASS_NAME, "btn-default").click()

    wait = WebDriverWait(browser, 10)
    alert = wait.until(EC.alert_is_present())
    assert "Congrats, you've passed the task!" in Alert(browser).text
    alert.accept()

Решение 3: getAttribute + форма + Alert

# test_get_attribute.py
import pytest
import math
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


@pytest.fixture
def browser():
    driver = webdriver.Chrome()
    driver.maximize_window()
    yield driver
    driver.quit()


def calc(x):
    return str(math.log(abs(12 * math.sin(int(x)))))


def test_get_attribute_form(browser):
    browser.get("http://suninjuly.github.io/get_attribute.html")

    # Получаем x из атрибута элемента (не из .text!)
    x_value = browser.find_element(By.ID, "treasure").get_attribute("valuex")
    result = calc(x_value)

    browser.find_element(By.ID, "answer").send_keys(result)
    browser.find_element(By.ID, "robotCheckbox").click()
    browser.find_element(By.ID, "robotsRule").click()
    browser.find_element(By.CSS_SELECTOR, ".btn-default").click()

    wait = WebDriverWait(browser, 10)
    alert = wait.until(EC.alert_is_present())
    assert "Congrats, you've passed the task!" in Alert(browser).text
    alert.accept()

Ключевой момент: get_attribute("valuex") — не стандартный HTML-атрибут, а кастомный. Его нельзя получить через .text.

Решение 4: Переключение вкладок + math + Alert

# test_redirect_tab.py
import pytest
import math
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


@pytest.fixture
def browser():
    driver = webdriver.Chrome()
    driver.maximize_window()
    yield driver
    driver.quit()


def calc(x):
    return str(math.log(abs(12 * math.sin(int(x)))))


def test_redirect_and_math(browser):
    browser.get("http://suninjuly.github.io/redirect_accept.html")

    # Запоминаем текущую вкладку
    original_tab = browser.current_window_handle

    # Кнопка "trollface" открывает новую вкладку
    browser.find_element(By.CLASS_NAME, "trollface").click()

    # Находим новую вкладку (та, которая не оригинальная)
    new_tab = [h for h in browser.window_handles if h != original_tab][0]
    browser.switch_to.window(new_tab)

    # На новой вкладке: считываем x и вычисляем
    x_value = browser.find_element(By.ID, "input_value").text
    result = calc(x_value)

    browser.find_element(By.ID, "answer").send_keys(result)
    browser.find_element(By.CLASS_NAME, "btn-primary").click()

    wait = WebDriverWait(browser, 10)
    alert = wait.until(EC.alert_is_present())
    assert "Congrats, you've passed the task!" in Alert(browser).text
    alert.accept()

Решение 5: Hover Menu с ActionChains

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


@pytest.fixture
def browser():
    driver = webdriver.Chrome()
    driver.maximize_window()
    yield driver
    driver.quit()


def test_hover_menu(browser):
    browser.get("https://crossbrowsertesting.github.io/hover-menu.html")

    actions = ActionChains(browser)

    # Hover на "Dropdown" — раскрывает выпадающее меню
    dropdown = browser.find_element(By.LINK_TEXT, "Dropdown")
    actions.move_to_element(dropdown).perform()

    # Hover на "Secondary Menu" — раскрывает вложенное меню
    secondary_menu = browser.find_element(By.LINK_TEXT, "Secondary Menu")
    actions.move_to_element(secondary_menu).perform()

    # Кликаем на скрытый пункт "Secondary Action"
    secondary_action = browser.find_element(By.LINK_TEXT, "Secondary Action")
    secondary_action.click()

    # Проверяем заголовок новой страницы
    wait = WebDriverWait(browser, 10)
    header = wait.until(EC.presence_of_element_located((By.TAG_NAME, "h1")))
    assert header.text == "Secondary Page", f"Заголовок: {header.text}"

Логика: каждый move_to_element().perform() раскрывает следующий уровень меню. Только после двух hover-ов становится доступен «Secondary Action».

Решение 6: Drag and Drop с ActionChains

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


@pytest.fixture
def browser():
    driver = webdriver.Chrome()
    driver.maximize_window()
    yield driver
    driver.quit()


def test_drag_and_drop(browser):
    browser.get("https://crossbrowsertesting.github.io/drag-and-drop.html")

    draggable = browser.find_element(By.ID, "draggable")
    droppable = browser.find_element(By.ID, "droppable")

    ActionChains(browser).drag_and_drop(draggable, droppable).perform()

    # Ждём изменения текста — подтверждение успешного drop
    wait = WebDriverWait(browser, 5)
    dropped = wait.until(
        EC.text_to_be_present_in_element((By.ID, "droppable"), "Dropped!")
    )
    assert dropped, "Текст не изменился на 'Dropped!'"

Решение 7: Загрузка файла

# test_file_upload.py
import pytest
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


@pytest.fixture
def browser():
    driver = webdriver.Chrome()
    driver.maximize_window()
    yield driver
    driver.quit()


def test_file_upload(browser):
    browser.get("http://suninjuly.github.io/file_input.html")

    # Заполняем поля формы
    browser.find_element(By.NAME, "firstname").send_keys("John")
    browser.find_element(By.NAME, "lastname").send_keys("Doe")
    browser.find_element(By.NAME, "email").send_keys("test@example.com")

    # Создаём временный файл для загрузки
    file_path = os.path.abspath("test_file.txt")
    with open(file_path, "w") as f:
        f.write("Hello, this is a test file.")

    # Передаём путь к файлу — send_keys умеет принять путь к файлу
    file_input = browser.find_element(By.ID, "file")
    file_input.send_keys(file_path)

    browser.find_element(By.CLASS_NAME, "btn-primary").click()

    # Проверяем Alert
    wait = WebDriverWait(browser, 10)
    alert = wait.until(EC.alert_is_present())
    alert_text = Alert(browser).text
    assert "Congrats, you've passed the task!" in alert_text
    alert.accept()

    # Удаляем временный файл
    os.remove(file_path)

Логика: send_keys() на input[type=file] работает как ввод пути в текстовое поле, но браузер интерпретирует его как путь к файлу. Никакого диалога открывать не нужно.