Files
dl-organizer/tests/test_reports_integration.py
T
windyboyandClaude Sonnet 4.5 fe03a31dd4 refactor: DLO-16/17/18/20 — CLI simplification, config Pydantic, planner split, type system unification
DLO-16: Reduce cli.py from 1073 to 83 lines by registering Click commands from commands/*.py modules
DLO-17: Migrate Config to Pydantic BaseModel for validation
DLO-18: Split planner.py (826 lines) into orchestration, path rendering, and duplicate handling modules
DLO-20: Unify type system — convert 14 dataclasses to Pydantic BaseModel, keep TypedDicts as JSON schema hints

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-09-27 10:47:04 +08:00

181 lines
6.7 KiB
Python

"""Integration tests for report generation with analysis engine.
Tests the complete workflow from analysis to report generation.
"""
import json
from datetime import datetime, timezone
from pathlib import Path
from vlm.analysis import analyze_series_completeness, detect_duplicates
from vlm.models import MovieIdentity, SeriesIdentity, VideoFile
from vlm.reports import (
generate_completeness_report,
generate_duplicate_report,
generate_summary_report,
)
def _movie(title="Movie", year=2020, **kw):
return MovieIdentity(
title=title, year=year, confidence=kw.pop("confidence", 0.9),
needs_review=kw.pop("needs_review", False),
original_filename=kw.pop("original_filename", f"{title}.{year}.mkv"),
**kw,
)
def _series(title="Show", season=1, episodes=None, **kw):
if episodes is None:
episodes = [1]
return SeriesIdentity(
title=title, season=season, episodes=episodes,
confidence=kw.pop("confidence", 0.9),
needs_review=kw.pop("needs_review", False),
original_filename=kw.pop(
"original_filename",
f"{title.replace(' ', '.')}.S{season:02d}E01.mkv"
if season is not None
else f"{title.replace(' ', '.')}.E01.mkv",
),
**kw,
)
def _video(filename="file.mkv", size=1000, category="movie", **kw):
return VideoFile(
path=kw.pop("path", Path(f"/tmp/{filename}")),
filename=filename, size_bytes=size,
modified_timestamp=kw.pop("modified_timestamp", datetime(2023, 1, 1)),
category=category, **kw,
)
class TestReportsIntegration:
"""Test report generation integrated with analysis engine."""
def test_completeness_workflow(self):
"""Test complete workflow from series analysis to completeness report."""
# Create test episodes with gaps
episodes = [
_series("Breaking Bad", episodes=[1],
original_filename="Breaking.Bad.S01E01.mkv"),
_series("Breaking Bad", episodes=[2],
original_filename="Breaking.Bad.S01E02.mkv"),
_series("Breaking Bad", episodes=[4],
original_filename="Breaking.Bad.S01E04.mkv"),
_series("The Wire", episodes=[1],
original_filename="The.Wire.S01E01.mkv"),
_series("The Wire", episodes=[3],
original_filename="The.Wire.S01E03.mkv"),
]
# Analyze completeness
analysis = analyze_series_completeness(episodes)
# Generate text report
library_root = Path("/mnt/nas/videos")
text_report = generate_completeness_report(analysis, "text", library_root)
# Verify report contains expected information
assert "Breaking Bad" in text_report
assert "The Wire" in text_report
assert "Episodes missing:" in text_report
# Generate JSON report
json_report = generate_completeness_report(analysis, "json", library_root)
data = json.loads(json_report)
# Verify JSON structure
assert data["metadata"]["series_count"] == 2
assert len(data["series"]) == 2
def test_duplicate_workflow(self):
"""Test complete workflow from duplicate detection to duplicate report."""
# Create test identities and files
now = datetime.now(timezone.utc)
identities = [
_movie("The Matrix", 1999,
original_filename="The.Matrix.1999.1080p.mkv"),
_movie("The Matrix", 1999,
original_filename="The.Matrix.1999.720p.mkv"),
_movie("Inception", 2010),
]
files = [
_video("The.Matrix.1999.1080p.mkv", 2_000_000_000,
modified_timestamp=now, resolution="1920x1080", codec="h264"),
_video("The.Matrix.1999.720p.mkv", 1_000_000_000,
modified_timestamp=now, resolution="1280x720", codec="h264"),
_video("Inception.2010.mkv", 1_500_000_000,
modified_timestamp=now),
]
# Detect duplicates
duplicates = detect_duplicates(list(zip(identities, files)))
# Generate text report
library_root = Path("/mnt/nas/videos")
text_report = generate_duplicate_report(duplicates, "text", library_root)
# Verify report contains expected information
assert "The Matrix (1999)" in text_report
assert "1920x1080" in text_report
assert "1280x720" in text_report
# Generate JSON report
json_report = generate_duplicate_report(duplicates, "json", library_root)
data = json.loads(json_report)
# Verify JSON structure
assert data["metadata"]["duplicate_groups"] == 1
assert len(data["duplicates"]) == 1
assert data["duplicates"][0]["file_count"] == 2
def test_summary_workflow(self):
"""Test summary report generation with mixed file types."""
# Create test files
now = datetime.now(timezone.utc)
files = [
_video("Movie1.mkv", 2_000_000_000, "movie",
modified_timestamp=now),
_video("Movie2.mkv", 1_500_000_000, "movie",
modified_timestamp=now),
_video("Show.S01E01.mkv", 1_000_000_000, "series",
modified_timestamp=now),
_video("Show.S01E02.mkv", 1_000_000_000, "series",
modified_timestamp=now),
_video("Anime1.mkv", 800_000_000, "anime",
modified_timestamp=now),
]
# Generate summary report
library_root = Path("/mnt/nas/videos")
report = generate_summary_report(files, library_root)
# Verify report contains expected information
assert "Total Files: 5" in report
assert "Movie:" in report
assert "Series:" in report
assert "Anime:" in report
assert "Category Breakdown:" in report
def test_all_reports_include_metadata(self):
"""Test that all reports include generation timestamp and library root."""
library_root = Path("/mnt/nas/videos")
# Test completeness report
completeness_report = generate_completeness_report([], "text", library_root)
assert "Generated:" in completeness_report
assert str(library_root) in completeness_report
# Test duplicate report
duplicate_report = generate_duplicate_report([], "text", library_root)
assert "Generated:" in duplicate_report
assert str(library_root) in duplicate_report
# Test summary report
summary_report = generate_summary_report([], library_root)
assert "Generated:" in summary_report
assert str(library_root) in summary_report