test: юнит-тесты и сквозные тесты с Chrome (#21)

- tests/unit (make test, без браузера, ~5 с): схемы и валидация, /v1/solve с подменённым
  движком (коды ошибок, слоты, сессии, UA и cookies профиля, маскирование секретов в логах),
  действия, оркестратор антибота, профиль и отпечаток
- tests/browser (make test-browser, в Docker): example.com, UA один раз и замена cookies
  на httpbin, применение и стабильность отпечатка, прохождение Cloudflare
- requirements-dev.txt, make sync-dev; Makefile вызывает pip через python -m pip
  (у перенесённого .venv битый shebang bin/pip)
- fix: в CloudflareSolver вызов bounding_box() у неожиданной корутины — ветка без iframe
  всегда падала с AttributeError

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
protokeyandClaude Opus 5.5 committed 2026-10-13 18:10:21 +04:00
1 parent 58100fa45d
commit 0ae5b0c83f
13 files changed
+773 -85

No files matched your search

+4 -1
View File
@@ -195,9 +195,12 @@ class CloudflareSolver(Solver):
frame_el = await iframe.frame_element()
box = await frame_el.bounding_box()
else:
box = await page.query_selector("xpath=//input[@name='cf-turnstile-response']/../div").bounding_box()
container = await page.query_selector("xpath=//input[@name='cf-turnstile-response']/../div")
box = await container.bounding_box() if container else None
if info.stage == Stage.CHECKBOX:
if box is None:
raise RuntimeError("turnstile widget not found on the page")
# # Calculate the Captcha coordinates for any viewport
captcha_x, captcha_y = box["x"] + randint(26, 28), box["y"] + randint(25, 27)