626fb73a58
- Add CrawlerConfig with ProxyConfig, delay, and retry settings - Support HTTP_PROXY/HTTPS_PROXY environment variable parsing - Add proxy_required validation with clear error message - Add get_crawler_config singleton for configuration access Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
126 lines
4.6 KiB
Python
126 lines
4.6 KiB
Python
"""Tests for Crawler Proxy Configuration"""
|
|
|
|
import os
|
|
import pytest
|
|
from unittest.mock import patch
|
|
|
|
from kb_workflow.crawler.config import (
|
|
CrawlerConfig,
|
|
ProxyConfig,
|
|
get_crawler_config,
|
|
reset_crawler_config,
|
|
)
|
|
|
|
|
|
class TestProxyConfig:
|
|
"""Tests for ProxyConfig model."""
|
|
|
|
def test_parse_proxy_from_https_env(self):
|
|
"""Parse proxy from HTTPS_PROXY environment variable."""
|
|
reset_crawler_config()
|
|
with patch.dict(os.environ, {"HTTPS_PROXY": "http://127.0.0.1:7890"}, clear=False):
|
|
os.environ.pop("HTTP_PROXY", None)
|
|
config = CrawlerConfig.from_env()
|
|
assert config.proxy is not None
|
|
assert config.proxy.server == "http://127.0.0.1:7890"
|
|
|
|
def test_parse_proxy_from_http_env(self):
|
|
"""Parse proxy from HTTP_PROXY (HTTPS_PROXY takes priority)."""
|
|
reset_crawler_config()
|
|
with patch.dict(os.environ, {
|
|
"HTTP_PROXY": "http://127.0.0.1:8080",
|
|
"HTTPS_PROXY": "http://127.0.0.1:7890"
|
|
}, clear=False):
|
|
config = CrawlerConfig.from_env()
|
|
assert config.proxy.server == "http://127.0.0.1:7890"
|
|
|
|
def test_parse_proxy_with_auth(self):
|
|
"""Parse proxy with authentication credentials."""
|
|
reset_crawler_config()
|
|
with patch.dict(os.environ, {
|
|
"HTTPS_PROXY": "http://user:pass@proxy.example.com:8080"
|
|
}, clear=False):
|
|
os.environ.pop("HTTP_PROXY", None)
|
|
config = CrawlerConfig.from_env()
|
|
assert config.proxy.username == "user"
|
|
assert config.proxy.password == "pass"
|
|
assert config.proxy.server == "http://proxy.example.com:8080"
|
|
|
|
def test_no_proxy_configured(self):
|
|
"""Handle case when no proxy is configured."""
|
|
reset_crawler_config()
|
|
# Save current values
|
|
old_http = os.environ.get("HTTP_PROXY")
|
|
old_https = os.environ.get("HTTPS_PROXY")
|
|
|
|
try:
|
|
os.environ.pop("HTTP_PROXY", None)
|
|
os.environ.pop("HTTPS_PROXY", None)
|
|
config = CrawlerConfig.from_env()
|
|
assert config.proxy is None
|
|
finally:
|
|
# Restore
|
|
if old_http:
|
|
os.environ["HTTP_PROXY"] = old_http
|
|
if old_https:
|
|
os.environ["HTTPS_PROXY"] = old_https
|
|
|
|
def test_proxy_required_validation_fails(self):
|
|
"""Raise ValueError when proxy required but not configured."""
|
|
config = CrawlerConfig(proxy=None, proxy_required=True)
|
|
with pytest.raises(ValueError, match="Proxy configuration missing"):
|
|
config.validate_proxy()
|
|
|
|
def test_proxy_required_validation_passes(self):
|
|
"""Pass validation when proxy is configured and required."""
|
|
config = CrawlerConfig(
|
|
proxy=ProxyConfig(server="http://127.0.0.1:7890"),
|
|
proxy_required=True
|
|
)
|
|
# Should not raise exception
|
|
config.validate_proxy()
|
|
|
|
def test_proxy_not_required(self):
|
|
"""Pass validation when proxy is not required."""
|
|
config = CrawlerConfig(proxy=None, proxy_required=False)
|
|
# Should not raise exception
|
|
config.validate_proxy()
|
|
|
|
def test_to_playwright_format(self):
|
|
"""Convert to Playwright proxy format."""
|
|
proxy = ProxyConfig(
|
|
server="http://127.0.0.1:7890",
|
|
username="user",
|
|
password="pass"
|
|
)
|
|
result = proxy.to_playwright_format()
|
|
assert result == {
|
|
"server": "http://127.0.0.1:7890",
|
|
"username": "user",
|
|
"password": "pass"
|
|
}
|
|
|
|
def test_to_playwright_format_no_auth(self):
|
|
"""Convert to Playwright format without authentication."""
|
|
proxy = ProxyConfig(server="http://127.0.0.1:7890")
|
|
result = proxy.to_playwright_format()
|
|
assert result == {"server": "http://127.0.0.1:7890"}
|
|
|
|
def test_get_crawler_config_singleton(self):
|
|
"""Test that get_crawler_config returns cached instance."""
|
|
reset_crawler_config()
|
|
with patch.dict(os.environ, {"HTTPS_PROXY": "http://127.0.0.1:7890"}, clear=False):
|
|
os.environ.pop("HTTP_PROXY", None)
|
|
config1 = get_crawler_config()
|
|
config2 = get_crawler_config()
|
|
assert config1 is config2
|
|
|
|
def test_default_values(self):
|
|
"""Test default configuration values."""
|
|
config = CrawlerConfig(proxy=None, proxy_required=False)
|
|
assert config.min_delay == 1.0
|
|
assert config.max_delay == 3.0
|
|
assert config.max_retries == 3
|
|
assert config.retry_min_wait == 2.0
|
|
assert config.retry_max_wait == 10.0
|