fix: письмо больше не попадает в вопрос скрининга — убран опасный fallback 'textarea' при наличии task_*, надёжный клик по переключателю письма, проверка ошибки валидации после отправки
This commit is contained in:
1 parent
6b2c7a0f09
commit
3179bac026
1 file changed
+33
-4
+33
-4
@@ -29,12 +29,13 @@ RESPONSE_BUTTONS = [
|
||||
]
|
||||
# hh.ru прячет поле письма за переключателем «Сопроводительное письмо / Добавить»:
|
||||
# до клика по нему на форме есть только textarea вопроса скрининга (task_*).
|
||||
# ВАЖНО: запасной селектор 'textarea' НЕ используется, если есть вопросы скрининга —
|
||||
# иначе текст письма попадёт в первый вопрос вместо поля письма.
|
||||
LETTER_TOGGLE = '[data-qa="vacancy-response-letter-toggle"]'
|
||||
MESSAGE_FIELDS = [
|
||||
'textarea[data-qa="vacancy-response-popup-form-letter-input"]',
|
||||
'textarea[data-qa="vacancy-response-letter"]',
|
||||
'textarea[data-qa="vacancy-response-popup-form"] textarea',
|
||||
'textarea',
|
||||
]
|
||||
SUBMIT_BUTTONS = [
|
||||
'[data-qa="vacancy-response-submit-popup"]',
|
||||
@@ -272,18 +273,18 @@ def open_response_page(account_dir, user, account, vacancy, message,
|
||||
return False, "Не нашёл кнопку «Откликнуться» — проверьте скриншот", shot
|
||||
|
||||
# Ждём модалку
|
||||
page.wait_for_timeout(2000)
|
||||
page.wait_for_timeout(2500)
|
||||
|
||||
# hh.ru прячет поле письма за переключателем «Сопроводительное письмо» —
|
||||
# раскрываем его, иначе заполнится textarea вопроса скрининга (task_*)
|
||||
try:
|
||||
toggle = page.locator(LETTER_TOGGLE).first
|
||||
if toggle.is_visible(timeout=2000):
|
||||
toggle.wait_for(state="visible", timeout=5000)
|
||||
toggle.click()
|
||||
page.wait_for_timeout(800)
|
||||
print(" ✓ Переключатель «Сопроводительное письмо» раскрыт")
|
||||
except Exception:
|
||||
pass
|
||||
print(" ⚠ Переключатель письма не найден — поле может отсутствовать")
|
||||
|
||||
# Выбор резюме (радио-кнопка name="resumeId" value="{hash}")
|
||||
if resume_id:
|
||||
@@ -307,6 +308,19 @@ def open_response_page(account_dir, user, account, vacancy, message,
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if not filled:
|
||||
# Запасной вариант: если вопросов скрининга НЕТ, единственная
|
||||
# textarea на форме — это поле письма (старая версия формы).
|
||||
# При наличии task_* НЕ заполняем — иначе письмо попадёт в вопрос.
|
||||
try:
|
||||
if page.locator('textarea[name^="task_"]').count() == 0:
|
||||
field = page.locator('textarea').first
|
||||
if field.is_visible(timeout=2000):
|
||||
field.fill(message)
|
||||
filled = True
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not filled:
|
||||
shot = _save_screenshot(page, screenshot_dir, vacancy["id"])
|
||||
return False, "Не нашёл поле сообщения — проверьте скриншот", shot
|
||||
@@ -336,7 +350,22 @@ def open_response_page(account_dir, user, account, vacancy, message,
|
||||
# ловим любые ошибки, но отклик уже отправлен.
|
||||
try:
|
||||
page.wait_for_timeout(2500)
|
||||
# Проверяем, не осталась ли форма открытой с ошибкой валидации
|
||||
# (например, не заполнены обязательные вопросы скрининга)
|
||||
form_open = page.locator('[data-qa="vacancy-response-popup-form"]').count()
|
||||
err_visible = False
|
||||
if form_open:
|
||||
for sel in ['[data-qa="vacancy-response-error"]',
|
||||
'[data-qa="vacancy-response-popup-form"] [class*="error"]']:
|
||||
try:
|
||||
if page.locator(sel).first.is_visible(timeout=1000):
|
||||
err_visible = True
|
||||
break
|
||||
except Exception:
|
||||
continue
|
||||
shot = _save_screenshot(page, screenshot_dir, vacancy["id"])
|
||||
if form_open and err_visible:
|
||||
return False, "hh.ru не принял отклик — проверьте скриншот (возможно, не заполнены обязательные вопросы)", shot
|
||||
except Exception:
|
||||
shot = None
|
||||
return True, "Отклик отправлен", shot
|
||||
|
||||
Reference in new issue
Block a user