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:
1 parent
58100fa45d
commit
0ae5b0c83f
13 files changed
+773
-85
No files matched your search
@@ -0,0 +1,67 @@
|
||||
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},
|
||||
}
|
||||
Reference in new issue
Block a user