Заполнение полей, отправка форм, выпадающие списки, чекбоксы, радио-кнопки, drag-and-drop
Формы — главный способ ввода данных в веб-приложениях. Playwright предоставляет специализированные методы для каждого типа элементов формы, с встроенным auto-waiting.
Основной метод — fill(). Он очищает текущее значение поля и вводит новый текст за одну атомарную операцию:
# Заполнение поля ввода
await page.get_by_label('Email').fill('user@example.com')
# Заполнение textarea
await page.get_by_label('Комментарий').fill('Длинный текст комментария')
# По placeholder
await page.get_by_placeholder('Введите имя').fill('Иван')fill() работает с <input type="text">, <input type="email">, <input type="password">, <textarea> и <input type="search">.
Важно:
fill()устанавливает значение мгновенно. Если приложение реагирует на каждое нажатие клавиши (автодополнение, live-валидация) — используйтеtype()вместоfill().
type() имитирует реальную клавиатуру — вводит текст посимвольно с небольшой задержкой:
# Посимвольный ввод с задержкой 50мс
await page.get_by_label('Поиск').type('Playwright', delay=50)Когда нужен type():
Когда НЕ нужен type():
fill()fill() в 5-10 раз быстрее type(), потому что не генерирует события для каждого символа.
# Отметить чекбокс
await page.get_by_role('checkbox', name='Запомнить меня').check()
# Снять чекбокс
await page.get_by_role('checkbox', name='Запомнить меня').uncheck()
# Переключить (если не знаете текущее состояние)
await page.get_by_role('checkbox', name='Запомнить меня').click()
# Выбрать радио-кнопку
await page.get_by_role('radio', name='Мужской').check().check() гарантированно устанавливает состояние «отмечен», даже если чекбокс уже отмечен. .click() переключает — если чекбокс был отмечен, он снимется.
Проверка состояния:
from playwright.sync_api import expect
checkbox = page.get_by_role('checkbox', name='Подписка')
await expect(checkbox).to_be_checked()
await expect(checkbox).not_to_be_checked()Для <select> используйте select_option(). Он поддерживает выбор по value, label и индексу:
dropdown = page.get_by_label('Страна')
# По значению value
await dropdown.select_option('RU')
# По видимому тексту
await dropdown.select_option(label='Россия')
# По индексу (0-based)
await dropdown.select_option(index=2)
# Множественный выбор
await page.locator('#multiple-select').select_option(value=['RU', 'BY', 'KZ'])Рекомендация: выбирайте по
value, если он стабилен.labelможет измениться при локализации.
Самый реалистичный пользовательский сценарий — клик по кнопке отправки:
# Клик по кнопке submit
await page.get_by_role('button', name='Отправить').click()
# Или через Enter в активном поле
await page.get_by_label('Email').fill('user@example.com')
await page.keyboard.press('Enter')После отправки формы обычно происходит навигация или AJAX-запрос. Playwright автоматически ждёт завершения:
# Ожидание навигации после submit
async with page.expect_navigation():
await page.get_by_role('button', name='Отправить').click()
# Ожидание конкретного API-ответа
async with page.expect_response('**/api/register') as response_info:
await page.get_by_role('button', name='Отправить').click()
response = response_info.value
assert response.status == 200# Один файл
await page.get_by_label('Загрузить документ').set_input_files('document.pdf')
# Несколько файлов
await page.get_by_label('Загрузить фото').set_input_files([
'photo1.jpg',
'photo2.jpg',
'photo3.jpg',
])set_input_files() не открывает системный диалог — он напрямую устанавливает файл в <input type="file">. Это работает и в headless-режиме.
# Простое перетаскивание
await page.drag_and_drop('#draggable-item', '#drop-zone')
# С локаторами
source = page.locator('.task-card', has_text='Важная задача')
target = page.locator('.column', has_text='В работе')
await page.drag_and_drop(source, target)Для сложных сценариев (перетаскивание с промежуточными точками) используйте mouse:
# Ручное перетаскивание через mouse
source = page.locator('.slider-handle')
await source.hover()
await page.mouse.down()
await page.mouse.move(300, 0, steps=10) # 10 промежуточных шагов
await page.mouse.up()Параметр steps=10 создаёт 10 промежуточных позиций — это важно для компонентов, которые обрабатывают только mousemove события.
Иногда формы вызывают нативные диалоги (alert, confirm, prompt). Playwright перехватывает их:
# Обработка alert
with page.expect_event('dialog') as dialog_info:
await page.get_by_role('button', name='Удалить').click()
dialog = dialog_info.value
assert dialog.type == 'alert'
await dialog.accept()
# Обработка confirm
with page.expect_event('dialog') as dialog_info:
await page.get_by_role('button', name='Удалить').click()
dialog = dialog_info.value
assert dialog.type == 'confirm'
await dialog.accept() # или dialog.dismiss() для Отмена# Фокус на элементе
await page.get_by_label('Email').focus()
# Нажатие клавиш
await page.keyboard.press('Tab') # Следующий элемент
await page.keyboard.press('Enter') # Enter
await page.keyboard.press('Backspace') # Удаление символа
await page.keyboard.press('Control+A') # Выделить всё
await page.keyboard.press('Escape') # Закрыть/отменить
# Комбинации
await page.keyboard.press('Control+Shift+K')Важно:
keyboardработает на уровне страницы, а не элемента. Убедитесь, что фокус на нужном элементе перед нажатием.
❌ fill() для полей с автодополнением. fill() устанавливает значение мгновенно — событие input срабатывает один раз. Приложение не успеет показать подсказки. Используйте type().
❌ click() для чекбоксов вместо check(). Клик переключает состояние, а check() гарантированно отмечает. Если чекбокс уже отмечен, click() снимет его.
❌ Попытка выбрать файл через клик. Клик по <input type="file"> открывает системный диалог, который Playwright не контролирует. Используйте set_input_files().
✅ Правильный подход: fill() для обычных полей, type() для реактивных, check()/uncheck() для чекбоксов, select_option() для списков, set_input_files() для файлов.
set_input_files() и проверяет, что имя файла отображается на странице.Изучите навигацию и ожидание — переходы между страницами, работу с вкладками и фреймами, а также auto-waiting.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.