This commit is contained in:
240
tests/test_exporter.py
Normal file
240
tests/test_exporter.py
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
"""Tests for the exporter module."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from src.exporter import Exporter
|
||||||
|
from src.models import SearchResult, MatchLocation
|
||||||
|
|
||||||
|
|
||||||
|
class TestExporter:
|
||||||
|
"""Tests for Exporter class."""
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def sample_results(self):
|
||||||
|
"""Create sample search results."""
|
||||||
|
matches = [
|
||||||
|
MatchLocation(
|
||||||
|
file_path="src/main.py",
|
||||||
|
line_number=10,
|
||||||
|
line_content="def hello():" ,
|
||||||
|
match_start=0,
|
||||||
|
match_end=11,
|
||||||
|
),
|
||||||
|
MatchLocation(
|
||||||
|
file_path="src/main.py",
|
||||||
|
line_number=20,
|
||||||
|
line_content="def world():" ,
|
||||||
|
match_start=0,
|
||||||
|
match_end=11,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
return [
|
||||||
|
SearchResult(
|
||||||
|
repo_name="test/repo1",
|
||||||
|
repo_url="https://github.com/test/repo1",
|
||||||
|
stars=100,
|
||||||
|
description="Test repository 1",
|
||||||
|
language="Python",
|
||||||
|
matches=matches,
|
||||||
|
total_matches=2,
|
||||||
|
score=50.5,
|
||||||
|
),
|
||||||
|
SearchResult(
|
||||||
|
repo_name="test/repo2",
|
||||||
|
repo_url="https://github.com/test/repo2",
|
||||||
|
stars=200,
|
||||||
|
description="Test repository 2",
|
||||||
|
language="Python",
|
||||||
|
matches=[],
|
||||||
|
total_matches=0,
|
||||||
|
score=0.0,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_export_to_json(self, sample_results):
|
||||||
|
"""Test exporting results to JSON."""
|
||||||
|
with tempfile.NamedTemporaryFile(suffix=".json", delete=False) as f:
|
||||||
|
output_path = Path(f.name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
Exporter.export_to_json(sample_results, output_path)
|
||||||
|
|
||||||
|
with open(output_path, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
assert "total_repositories" in data
|
||||||
|
assert "total_matches" in data
|
||||||
|
assert "results" in data
|
||||||
|
assert data["total_repositories"] == 2
|
||||||
|
assert data["total_matches"] == 2
|
||||||
|
|
||||||
|
finally:
|
||||||
|
output_path.unlink()
|
||||||
|
|
||||||
|
def test_export_to_json_with_metadata(self, sample_results):
|
||||||
|
"""Test exporting with metadata."""
|
||||||
|
with tempfile.NamedTemporaryFile(suffix=".json", delete=False) as f:
|
||||||
|
output_path = Path(f.name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
Exporter.export_to_json(
|
||||||
|
sample_results,
|
||||||
|
output_path,
|
||||||
|
include_metadata=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(output_path, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
assert "metadata" in data
|
||||||
|
assert "exported_at" in data["metadata"]
|
||||||
|
assert "version" in data["metadata"]
|
||||||
|
|
||||||
|
finally:
|
||||||
|
output_path.unlink()
|
||||||
|
|
||||||
|
def test_export_results_json_format(self, sample_results):
|
||||||
|
"""Test export results with JSON format."""
|
||||||
|
with tempfile.NamedTemporaryFile(suffix=".json", delete=False) as f:
|
||||||
|
output_path = Path(f.name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
Exporter.export_results(sample_results, output_path, format="json")
|
||||||
|
|
||||||
|
assert output_path.exists()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
output_path.unlink()
|
||||||
|
|
||||||
|
def test_export_raises_on_unsupported_format(self, sample_results):
|
||||||
|
"""Test that unsupported format raises error."""
|
||||||
|
with tempfile.NamedTemporaryFile(suffix=".txt", delete=False) as f:
|
||||||
|
output_path = Path(f.name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
Exporter.export_results(
|
||||||
|
sample_results,
|
||||||
|
output_path,
|
||||||
|
format="unsupported",
|
||||||
|
)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
output_path.unlink()
|
||||||
|
|
||||||
|
def test_format_summary(self, sample_results):
|
||||||
|
"""Test formatting results as summary."""
|
||||||
|
summary = Exporter.format_summary(sample_results)
|
||||||
|
|
||||||
|
assert "test/repo1" in summary
|
||||||
|
assert "test/repo2" in summary
|
||||||
|
assert "2 matches" in summary
|
||||||
|
assert "100 stars" in summary
|
||||||
|
|
||||||
|
def test_prepare_export_data(self, sample_results):
|
||||||
|
"""Test preparing export data structure."""
|
||||||
|
data = Exporter._prepare_export_data(sample_results, include_metadata=False)
|
||||||
|
|
||||||
|
assert data["total_repositories"] == 2
|
||||||
|
assert data["total_matches"] == 2
|
||||||
|
assert len(data["results"]) == 2
|
||||||
|
assert "metadata" not in data
|
||||||
|
|
||||||
|
def test_prepare_export_data_with_metadata(self, sample_results):
|
||||||
|
"""Test preparing export data with metadata."""
|
||||||
|
data = Exporter._prepare_export_data(sample_results, include_metadata=True)
|
||||||
|
|
||||||
|
assert "metadata" in data
|
||||||
|
|
||||||
|
def test_get_timestamp_format(self):
|
||||||
|
"""Test timestamp format."""
|
||||||
|
timestamp = Exporter._get_timestamp()
|
||||||
|
|
||||||
|
assert "Z" in timestamp
|
||||||
|
assert "-" in timestamp
|
||||||
|
|
||||||
|
|
||||||
|
class TestSearchResultToDict:
|
||||||
|
"""Tests for SearchResult.to_dict()."""
|
||||||
|
|
||||||
|
def test_to_dict_basic(self):
|
||||||
|
"""Test converting SearchResult to dictionary."""
|
||||||
|
result = SearchResult(
|
||||||
|
repo_name="test/repo",
|
||||||
|
repo_url="https://github.com/test/repo",
|
||||||
|
stars=50,
|
||||||
|
)
|
||||||
|
|
||||||
|
data = result.to_dict()
|
||||||
|
|
||||||
|
assert data["repo_name"] == "test/repo"
|
||||||
|
assert data["repo_url"] == "https://github.com/test/repo"
|
||||||
|
assert data["stars"] == 50
|
||||||
|
|
||||||
|
def test_to_dict_with_matches(self):
|
||||||
|
"""Test converting SearchResult with matches."""
|
||||||
|
matches = [
|
||||||
|
MatchLocation(
|
||||||
|
file_path="test.py",
|
||||||
|
line_number=1,
|
||||||
|
line_content="test",
|
||||||
|
match_start=0,
|
||||||
|
match_end=4,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
result = SearchResult(
|
||||||
|
repo_name="test/repo",
|
||||||
|
repo_url="https://github.com/test/repo",
|
||||||
|
stars=50,
|
||||||
|
matches=matches,
|
||||||
|
total_matches=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
data = result.to_dict()
|
||||||
|
|
||||||
|
assert len(data["matches"]) == 1
|
||||||
|
assert data["matches"][0]["file_path"] == "test.py"
|
||||||
|
|
||||||
|
def test_get_match_summary(self):
|
||||||
|
"""Test getting match summary by file."""
|
||||||
|
matches = [
|
||||||
|
MatchLocation(
|
||||||
|
file_path="main.py",
|
||||||
|
line_number=1,
|
||||||
|
line_content="test",
|
||||||
|
match_start=0,
|
||||||
|
match_end=4,
|
||||||
|
),
|
||||||
|
MatchLocation(
|
||||||
|
file_path="main.py",
|
||||||
|
line_number=2,
|
||||||
|
line_content="test",
|
||||||
|
match_start=0,
|
||||||
|
match_end=4,
|
||||||
|
),
|
||||||
|
MatchLocation(
|
||||||
|
file_path="utils.py",
|
||||||
|
line_number=1,
|
||||||
|
line_content="test",
|
||||||
|
match_start=0,
|
||||||
|
match_end=4,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
result = SearchResult(
|
||||||
|
repo_name="test/repo",
|
||||||
|
repo_url="https://github.com/test/repo",
|
||||||
|
stars=50,
|
||||||
|
matches=matches,
|
||||||
|
total_matches=3,
|
||||||
|
)
|
||||||
|
|
||||||
|
summary = result.get_match_summary()
|
||||||
|
|
||||||
|
assert summary["main.py"] == 2
|
||||||
|
assert summary["utils.py"] == 1
|
||||||
Reference in New Issue
Block a user