- 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>
68 lines
2.3 KiB
Python
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},
|
|
}
|