import os
import sys
from pathlib import Path
import pytest
project_root = Path(__file__).parent.parent.parent
python_dir = project_root / "python"
if python_dir.exists() and str(python_dir) not in sys.path:
sys.path.insert(0, str(python_dir))
try:
import tarzi
TARZI_AVAILABLE = True
print(f"✅ Tarzi module successfully imported from {python_dir}")
except ImportError as e:
TARZI_AVAILABLE = False
print(f"⚠️ Tarzi module not available: {e}")
print(f" Searched in: {python_dir}")
print(f" Python path: {sys.path[:3]}...")
class MockConfig:
def __str__(self):
return "Tarzi configuration"
def __repr__(self):
return "Config()"
@classmethod
def from_str(cls, config_str):
if "invalid toml content" in config_str:
raise RuntimeError("Failed to parse config: invalid toml content")
return cls()
@classmethod
def load(cls):
return cls()
class MockConverter:
def __str__(self):
return "Tarzi HTML/text content converter"
def __repr__(self):
return "Converter()"
def convert(self, html, format_type):
if format_type == "invalid_format":
raise ValueError("Invalid format: invalid_format")
if format_type == "html":
return html
if "Test Title" in html and "content" in html:
if format_type == "markdown":
return "# Test Title\n\nTest **content** with [link](https://example.com)."
elif format_type == "json":
return '{"title": "Test Title", "content": "Test content with link"}'
elif format_type == "yaml":
return "title: Test Title\ncontent: Test content with link"
elif "Pipeline Test" in html:
if format_type == "markdown":
return "# Pipeline Test\n\nThis is a **test** of the processing pipeline."
elif format_type == "json":
return '{"title": "Pipeline Test", "content": "This is a test of the processing pipeline"}'
elif format_type == "yaml":
return "title: Pipeline Test\ncontent: This is a test of the processing pipeline"
return f"Mock {format_type} conversion of content"
@classmethod
def from_config(cls, config):
return cls()
class MockWebFetcher:
def __str__(self):
return "Tarzi web page fetcher"
def __repr__(self):
return "WebFetcher()"
def fetch(self, url, mode, format_type):
if mode == "invalid_mode":
raise ValueError("Invalid fetch mode: invalid_mode")
if format_type == "invalid_format":
raise ValueError("Invalid format: invalid_format")
return f"<html><body>Mock content from {url}</body></html>"
def fetch(self, url, mode):
if mode == "invalid_mode":
raise ValueError("Invalid fetch mode: invalid_mode")
return f"Raw mock content from {url}"
@classmethod
def from_config(cls, config):
return cls()
class MockSearchResult:
def __init__(self, title="Mock Result", url="https://example.com"):
self.title = title
self.url = url
class MockSearchEngine:
def __str__(self):
return "Tarzi search engine"
def __repr__(self):
return "SearchEngine()"
def search(self, query, limit):
return [MockSearchResult() for _ in range(min(limit, 2))]
def search_with_content(self, query, limit, fetch_mode, format_type):
if fetch_mode == "invalid_fetch_mode":
raise ValueError("Invalid fetch mode: invalid_fetch_mode")
if format_type == "invalid_format":
raise ValueError("Invalid format: invalid_format")
results = self.search(query, limit)
return [(r, f"Mock content for {r.url}") for r in results]
def shutdown(self):
return None
@classmethod
def from_config(cls, config):
return cls()
class MockTarzi:
Config = MockConfig
Converter = MockConverter
WebFetcher = MockWebFetcher
SearchEngine = MockSearchEngine
SearchResult = MockSearchResult
@staticmethod
def convert_html(html, format_type):
if format_type == "invalid_format":
raise ValueError("Invalid format: invalid_format")
if format_type == "html":
return html
if "Test Title" in html and "content" in html:
if format_type == "markdown":
return "# Test Title\n\nTest **content** with [link](https://example.com)."
elif format_type == "json":
return '{"title": "Test Title", "content": "Test content with link"}'
elif format_type == "yaml":
return "title: Test Title\ncontent: Test content with link"
elif "Pipeline Test" in html:
if format_type == "markdown":
return "# Pipeline Test\n\nThis is a **test** of the processing pipeline."
elif format_type == "json":
return '{"title": "Pipeline Test", "content": "This is a test of the processing pipeline"}'
elif format_type == "yaml":
return "title: Pipeline Test\ncontent: This is a test of the processing pipeline"
return f"Mock {format_type} conversion of content"
@staticmethod
def fetch(url, mode, format_type):
if mode == "invalid_mode":
raise ValueError("Invalid fetch mode: invalid_mode")
if format_type == "invalid_format":
raise ValueError("Invalid format: invalid_format")
return f"<html><body>Mock content from {url}</body></html>"
@staticmethod
def fetch_url(url, mode="plain_request", format_type="html"):
return MockTarzi.fetch(url, mode, format_type)
@staticmethod
def search_web(query, limit):
return [MockSearchResult() for _ in range(min(limit, 2))]
@staticmethod
def search_with_content(query, limit, fetch_mode, format_type):
if fetch_mode == "invalid_fetch_mode":
raise ValueError("Invalid fetch mode: invalid_fetch_mode")
if format_type == "invalid_format":
raise ValueError("Invalid format: invalid_format")
results = [MockSearchResult() for _ in range(min(limit, 2))]
return [(r, f"Mock content for {r.url}") for r in results]
tarzi = MockTarzi()
sys.modules["tarzi"] = tarzi
@pytest.fixture(scope="session")
def default_config():
return tarzi.Config()
@pytest.fixture(scope="session")
def sample_config_str():
return """
[fetcher]
timeout = 30
format = "html"
proxy = ""
[search]
engine = "bing"
query_pattern = "https://www.bing.com/search?q={query}"
"""
@pytest.fixture
def simple_html():
return "<p>Hello, <strong>world</strong>!</p>"
@pytest.fixture
def complex_html():
return """
<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
</head>
<body>
<h1>Main Title</h1>
<div class="content">
<p>This is a <em>test</em> paragraph with <a href="https://example.com">a link</a>.</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
<footer>
<p>© 2024 Test</p>
</footer>
</body>
</html>
"""
def pytest_collection_modifyitems(config, items):
print(f"🔍 pytest_collection_modifyitems called with TARZI_AVAILABLE={TARZI_AVAILABLE}")
print(f" Total items collected: {len(items)}")
integration_count = 0
skipped_count = 0
for item in items:
if "unit" in str(item.fspath):
item.add_marker(pytest.mark.unit)
elif "integration" in str(item.fspath):
item.add_marker(pytest.mark.integration)
integration_count += 1
if not TARZI_AVAILABLE and item.get_closest_marker("integration"):
item.add_marker(pytest.mark.skip(reason="tarzi module not available"))
skipped_count += 1
print(f" Integration tests found: {integration_count}")
print(f" Tests skipped due to missing tarzi: {skipped_count}")
if TARZI_AVAILABLE:
print("✅ Tarzi is available - integration tests will run")
else:
print("❌ Tarzi is not available - integration tests will be skipped")
def pytest_addoption(parser):
parser.addoption(
"--enable-integration",
action="store_true",
default=False,
help="Enable integration tests (disabled by default)",
)
def pytest_configure(config):
config.addinivalue_line("markers", "integration: mark test as integration test")
config.addinivalue_line("markers", "unit: mark test as unit test")