test(11-02): add failing tests for stealth integration in ZhihuCrawler
- Test crawler accepts stealth_config parameter - Test default stealth enabled behavior - Test stealth can be disabled - Test _start_browser_with_proxy calls apply_stealth_sync - Test launch args include --disable-blink-features - Test backward compatibility Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
"""Integration tests for ZhihuCrawler stealth functionality.
|
||||
|
||||
Tests that stealth fingerprint masking is properly integrated
|
||||
into ZhihuCrawler's browser initialization.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import MagicMock, patch, call
|
||||
|
||||
|
||||
class TestZhihuCrawlerStealthIntegration:
|
||||
"""Tests for stealth integration in ZhihuCrawler."""
|
||||
|
||||
def test_crawler_has_stealth_config_param(self):
|
||||
"""Test that ZhihuCrawler accepts stealth_config parameter."""
|
||||
from kb_workflow.crawler.zhihu_crawler import ZhihuCrawler
|
||||
from kb_workflow.crawler.stealth import StealthConfig
|
||||
|
||||
config = StealthConfig(stealth_enabled=False)
|
||||
crawler = ZhihuCrawler(stealth_config=config)
|
||||
|
||||
assert crawler._stealth_config == config
|
||||
|
||||
def test_crawler_default_stealth_enabled(self):
|
||||
"""Test that stealth is enabled by default (None = use defaults)."""
|
||||
from kb_workflow.crawler.zhihu_crawler import ZhihuCrawler
|
||||
|
||||
crawler = ZhihuCrawler()
|
||||
|
||||
# None means use default stealth config (enabled)
|
||||
assert crawler._stealth_config is None
|
||||
|
||||
def test_crawler_can_disable_stealth(self):
|
||||
"""Test that stealth can be explicitly disabled."""
|
||||
from kb_workflow.crawler.zhihu_crawler import ZhihuCrawler
|
||||
from kb_workflow.crawler.stealth import StealthConfig
|
||||
|
||||
disabled_config = StealthConfig(stealth_enabled=False)
|
||||
crawler = ZhihuCrawler(stealth_config=disabled_config)
|
||||
|
||||
assert crawler._stealth_config.stealth_enabled is False
|
||||
|
||||
@patch('kb_workflow.crawler.zhihu_crawler.sync_playwright')
|
||||
@patch('kb_workflow.crawler.zhihu_crawler.apply_stealth_sync')
|
||||
def test_start_browser_applies_stealth(
|
||||
self,
|
||||
mock_apply_stealth,
|
||||
mock_sync_playwright,
|
||||
):
|
||||
"""Test that _start_browser_with_proxy calls apply_stealth_sync."""
|
||||
from kb_workflow.crawler.zhihu_crawler import ZhihuCrawler
|
||||
|
||||
# Setup mocks
|
||||
mock_playwright = MagicMock()
|
||||
mock_browser = MagicMock()
|
||||
mock_context = MagicMock()
|
||||
mock_sync_playwright.return_value.start.return_value = mock_playwright
|
||||
mock_playwright.chromium.launch.return_value = mock_browser
|
||||
mock_browser.new_context.return_value = mock_context
|
||||
|
||||
crawler = ZhihuCrawler()
|
||||
crawler._start_browser_with_proxy(cookie="test_cookie")
|
||||
|
||||
# Verify apply_stealth_sync was called
|
||||
mock_apply_stealth.assert_called_once()
|
||||
call_args = mock_apply_stealth.call_args
|
||||
assert call_args[0][0] == mock_context # First arg is context
|
||||
|
||||
@patch('kb_workflow.crawler.zhihu_crawler.sync_playwright')
|
||||
@patch('kb_workflow.crawler.zhihu_crawler.apply_stealth_sync')
|
||||
def test_start_browser_launch_args_include_disable_blink_features(
|
||||
self,
|
||||
mock_apply_stealth,
|
||||
mock_sync_playwright,
|
||||
):
|
||||
"""Test that launch includes --disable-blink-features=AutomationControlled."""
|
||||
from kb_workflow.crawler.zhihu_crawler import ZhihuCrawler
|
||||
|
||||
# Setup mocks
|
||||
mock_playwright = MagicMock()
|
||||
mock_browser = MagicMock()
|
||||
mock_context = MagicMock()
|
||||
mock_sync_playwright.return_value.start.return_value = mock_playwright
|
||||
mock_playwright.chromium.launch.return_value = mock_browser
|
||||
mock_browser.new_context.return_value = mock_context
|
||||
|
||||
crawler = ZhihuCrawler()
|
||||
crawler._start_browser_with_proxy(cookie="test_cookie")
|
||||
|
||||
# Verify launch was called with correct args
|
||||
launch_call = mock_playwright.chromium.launch
|
||||
launch_call.assert_called_once()
|
||||
call_kwargs = launch_call.call_args[1]
|
||||
|
||||
assert 'args' in call_kwargs
|
||||
assert '--disable-blink-features=AutomationControlled' in call_kwargs['args']
|
||||
|
||||
@patch('kb_workflow.crawler.zhihu_crawler.sync_playwright')
|
||||
@patch('kb_workflow.crawler.zhihu_crawler.apply_stealth_sync')
|
||||
def test_start_browser_stealth_disabled_no_blink_features_arg(
|
||||
self,
|
||||
mock_apply_stealth,
|
||||
mock_sync_playwright,
|
||||
):
|
||||
"""Test that --disable-blink-features is not added when stealth disabled."""
|
||||
from kb_workflow.crawler.zhihu_crawler import ZhihuCrawler
|
||||
from kb_workflow.crawler.stealth import StealthConfig
|
||||
|
||||
# Setup mocks
|
||||
mock_playwright = MagicMock()
|
||||
mock_browser = MagicMock()
|
||||
mock_context = MagicMock()
|
||||
mock_sync_playwright.return_value.start.return_value = mock_playwright
|
||||
mock_playwright.chromium.launch.return_value = mock_browser
|
||||
mock_browser.new_context.return_value = mock_context
|
||||
|
||||
disabled_config = StealthConfig(stealth_enabled=False)
|
||||
crawler = ZhihuCrawler(stealth_config=disabled_config)
|
||||
crawler._start_browser_with_proxy(cookie="test_cookie")
|
||||
|
||||
# Verify launch was called without args or with empty/None args
|
||||
launch_call = mock_playwright.chromium.launch
|
||||
call_kwargs = launch_call.call_args[1]
|
||||
|
||||
# When stealth disabled, args should be None or not contain the flag
|
||||
if 'args' in call_kwargs and call_kwargs['args']:
|
||||
assert '--disable-blink-features=AutomationControlled' not in call_kwargs['args']
|
||||
|
||||
# apply_stealth_sync should still be called but with disabled config
|
||||
mock_apply_stealth.assert_called_once()
|
||||
|
||||
|
||||
class TestZhihuCrawlerBackwardCompatibility:
|
||||
"""Tests for backward compatibility after stealth integration."""
|
||||
|
||||
def test_crawler_works_without_stealth_config(self):
|
||||
"""Test that ZhihuCrawler works without explicit stealth_config."""
|
||||
from kb_workflow.crawler.zhihu_crawler import ZhihuCrawler
|
||||
|
||||
# Should not raise any errors
|
||||
crawler = ZhihuCrawler(
|
||||
headless=True,
|
||||
timeout=30
|
||||
)
|
||||
assert crawler is not None
|
||||
|
||||
def test_crawler_accepts_all_existing_params(self):
|
||||
"""Test that all existing parameters still work."""
|
||||
from kb_workflow.crawler.zhihu_crawler import ZhihuCrawler
|
||||
from kb_workflow.crawler.config import CrawlerConfig
|
||||
|
||||
config = CrawlerConfig()
|
||||
crawler = ZhihuCrawler(
|
||||
headless=False,
|
||||
timeout=60,
|
||||
config=config
|
||||
)
|
||||
|
||||
assert crawler.headless is False
|
||||
assert crawler.timeout == 60
|
||||
assert crawler.config == config
|
||||
|
||||
|
||||
# Wave 0 completion marker
|
||||
WAVE_0_COMPLETE = True
|
||||
Reference in New Issue
Block a user