Files
robotex/tests/unit/test_profile.py
T
protokeyandClaude Opus 5.5 0ae5b0c83f 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>
2026-10-13 18:10:21 +04:00

68 lines
2.3 KiB
Python

import json
import pytest
from api import profile
@pytest.fixture(autouse=True)
def chrome_155(monkeypatch):
monkeypatch.setattr(profile, "chrome_major", lambda: "155")
def test_passed_user_agent_is_saved_once(tmp_path):
first = profile.load_or_create(tmp_path, "First/1")
second = profile.load_or_create(tmp_path, "Second/2")
assert first == second == {"user_agent": "First/1"}
assert json.loads((tmp_path / profile.SETTINGS_FILE).read_text()) == {"user_agent": "First/1"}
def test_generated_fingerprint_without_user_agent(tmp_path):
settings = profile.load_or_create(tmp_path, None)
assert settings["user_agent"] == profile.UA_TEMPLATE.format(major="155")
screen = settings["fingerprint"]["screen"]
assert screen["width"] >= profile.MIN_SCREEN[0] and screen["height"] >= profile.MIN_SCREEN[1]
assert settings["fingerprint"]["device_scale_factor"] >= 1
def test_generated_fingerprint_is_stable_and_ignores_later_user_agent(tmp_path):
first = profile.load_or_create(tmp_path, None)
assert profile.load_or_create(tmp_path, None) == first
assert profile.load_or_create(tmp_path, "Later/1") == first
def test_profiles_get_independent_fingerprints(tmp_path):
"""Отпечатки генерируются независимо: из выборки профилей получается больше одного варианта."""
variants = set()
for i in range(30):
d = tmp_path / str(i)
d.mkdir()
fp = profile.load_or_create(d, None)["fingerprint"]
variants.add((fp["screen"]["width"], fp["screen"]["height"], fp["device_scale_factor"]))
assert len(variants) > 1
def test_generate_falls_back_when_browserforge_fails(monkeypatch):
class Failing:
def generate(self, **kwargs):
raise ValueError("Cannot generate headers")
monkeypatch.setattr(profile, "FingerprintGenerator", Failing)
fp = profile.generate_fingerprint(attempts=2)
assert fp["screen"] == {"width": 1920, "height": 1080}
assert fp["device_scale_factor"] == 1
def test_browser_kwargs():
assert profile.browser_kwargs({"user_agent": "UA/1"}) == {"useragent": "UA/1"}
kwargs = profile.browser_kwargs({
"user_agent": "UA/1",
"fingerprint": {"screen": {"width": 2560, "height": 1440}, "device_scale_factor": 1.25},
})
assert kwargs == {
"useragent": "UA/1",
"additional_args": {"screen": {"width": 2560, "height": 1440}, "device_scale_factor": 1.25},
}