Files
dl-organizer/tests/test_cli_reports.py
6f0df5a774 release: v0.2.0 repository hygiene, CI, and docs sync
Stop tracking personal workflow artifacts at repo root, add CI and MIT
license, align README and agent skills with artifacts/ defaults, and
enable Ruff in dev/CI so releases are verifiable without local-only runs.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-01 15:32:03 +08:00

343 lines
13 KiB
Python

"""Integration tests for CLI report commands.
Tests the report commands to ensure they properly wire to the Report Generator.
"""
import json
from click.testing import CliRunner
from vlm.cli import main
class TestCLIReports:
"""Test CLI report commands."""
def test_report_inventory_csv(self, tmp_path):
"""Test inventory report generation in CSV format."""
# Create test inventory CSV
inventory_file = tmp_path / "inventory.csv"
with open(inventory_file, 'w', encoding='utf-8') as f:
f.write("# Generated: 2024-01-01T00:00:00\n")
f.write("# Library Root: /test/library\n")
f.write("path,filename,size_bytes,modified_timestamp,category,resolution,codec,duration_seconds,bitrate_kbps\n")
f.write("/test/library/movie/Movie1.mkv,Movie1.mkv,1000000,2024-01-01T00:00:00,movie,1920x1080,h264,7200,5000\n")
f.write("/test/library/series/Show.S01E01.mkv,Show.S01E01.mkv,800000,2024-01-01T00:00:00,series,1280x720,h264,2700,3000\n")
# Run command
runner = CliRunner()
result = runner.invoke(main, ['report', 'inventory', '--input', str(inventory_file), '--format', 'csv'])
# Verify success
assert result.exit_code == 0
assert "Loaded 2 files" in result.output
assert "Movie1.mkv" in result.output
assert "Show.S01E01.mkv" in result.output
def test_report_inventory_json(self, tmp_path):
"""Test inventory report generation in JSON format."""
# Create test inventory CSV
inventory_file = tmp_path / "inventory.csv"
with open(inventory_file, 'w', encoding='utf-8') as f:
f.write("# Generated: 2024-01-01T00:00:00\n")
f.write("# Library Root: /test/library\n")
f.write("path,filename,size_bytes,modified_timestamp,category,resolution,codec,duration_seconds,bitrate_kbps\n")
f.write("/test/library/movie/Movie1.mkv,Movie1.mkv,1000000,2024-01-01T00:00:00,movie,,,\n")
# Run command with output file
output_file = tmp_path / "inventory_report.json"
runner = CliRunner()
result = runner.invoke(main, [
'report', 'inventory',
'--input', str(inventory_file),
'--format', 'json',
'--output', str(output_file)
])
# Verify success
assert result.exit_code == 0
assert output_file.exists()
# Verify JSON content
with open(output_file, 'r') as f:
data = json.load(f)
assert data['metadata']['file_count'] == 1
assert len(data['files']) == 1
assert data['files'][0]['filename'] == 'Movie1.mkv'
def test_report_completeness_text(self, tmp_path):
"""Test completeness report generation in text format."""
# Create test analysis JSON
analysis_file = tmp_path / "analysis.json"
analysis_data = {
"metadata": {
"generated": "2024-01-01T00:00:00",
"source_identities": "identities.json",
"total_movies": 0,
"total_series": 3
},
"completeness": [
{
"series_title": "Breaking Bad",
"season": 1,
"episodes_found": [1, 2, 4],
"episodes_missing": [3]
}
],
"duplicates": []
}
with open(analysis_file, 'w') as f:
json.dump(analysis_data, f)
# Run command
runner = CliRunner()
result = runner.invoke(main, [
'report', 'completeness',
'--input', str(analysis_file),
'--format', 'text'
])
# Verify success
assert result.exit_code == 0
assert "Loaded 1 series with gaps" in result.output
assert "Breaking Bad" in result.output
assert "Episodes missing:" in result.output
def test_report_completeness_json(self, tmp_path):
"""Test completeness report generation in JSON format."""
# Create test analysis JSON
analysis_file = tmp_path / "analysis.json"
analysis_data = {
"metadata": {},
"completeness": [
{
"series_title": "The Wire",
"season": 1,
"episodes_found": [1, 3],
"episodes_missing": [2]
}
],
"duplicates": []
}
with open(analysis_file, 'w') as f:
json.dump(analysis_data, f)
# Run command with output file
output_file = tmp_path / "completeness_report.json"
runner = CliRunner()
result = runner.invoke(main, [
'report', 'completeness',
'--input', str(analysis_file),
'--format', 'json',
'--output', str(output_file)
])
# Verify success
assert result.exit_code == 0
assert output_file.exists()
# Verify JSON content
with open(output_file, 'r') as f:
data = json.load(f)
assert data['metadata']['series_count'] == 1
assert len(data['series']) == 1
assert data['series'][0]['title'] == 'The Wire'
def test_report_duplicates_text(self, tmp_path):
"""Test duplicate report generation in text format."""
# Create test analysis JSON
analysis_file = tmp_path / "analysis.json"
analysis_data = {
"metadata": {},
"completeness": [],
"duplicates": [
{
"identity": {
"type": "movie",
"title": "The Matrix",
"year": 1999
},
"files": [
"/movies/The.Matrix.1999.1080p.mkv",
"/movies/The.Matrix.1999.720p.mkv"
],
"quality_comparison": [
{
"filename": "The.Matrix.1999.1080p.mkv",
"path": "/movies/The.Matrix.1999.1080p.mkv",
"size_bytes": 2000000000,
"resolution": "1920x1080"
},
{
"filename": "The.Matrix.1999.720p.mkv",
"path": "/movies/The.Matrix.1999.720p.mkv",
"size_bytes": 1000000000,
"resolution": "1280x720"
}
]
}
]
}
with open(analysis_file, 'w') as f:
json.dump(analysis_data, f)
# Run command
runner = CliRunner()
result = runner.invoke(main, [
'report', 'duplicates',
'--input', str(analysis_file),
'--format', 'text'
])
# Verify success
assert result.exit_code == 0
assert "Loaded 1 duplicate groups" in result.output
assert "The Matrix (1999)" in result.output
assert "1920x1080" in result.output
def test_report_duplicates_json(self, tmp_path):
"""Test duplicate report generation in JSON format."""
# Create test analysis JSON
analysis_file = tmp_path / "analysis.json"
analysis_data = {
"metadata": {},
"completeness": [],
"duplicates": [
{
"identity": {
"type": "series",
"title": "Breaking Bad",
"season": 1,
"episodes": [1]
},
"files": [
"/series/Breaking.Bad.S01E01.1080p.mkv",
"/series/Breaking.Bad.S01E01.720p.mkv"
],
"quality_comparison": [
{
"filename": "Breaking.Bad.S01E01.1080p.mkv",
"path": "/series/Breaking.Bad.S01E01.1080p.mkv",
"size_bytes": 1500000000
},
{
"filename": "Breaking.Bad.S01E01.720p.mkv",
"path": "/series/Breaking.Bad.S01E01.720p.mkv",
"size_bytes": 800000000
}
]
}
]
}
with open(analysis_file, 'w') as f:
json.dump(analysis_data, f)
# Run command with output file
output_file = tmp_path / "duplicates_report.json"
runner = CliRunner()
result = runner.invoke(main, [
'report', 'duplicates',
'--input', str(analysis_file),
'--format', 'json',
'--output', str(output_file)
])
# Verify success
assert result.exit_code == 0
assert output_file.exists()
# Verify JSON content
with open(output_file, 'r') as f:
data = json.load(f)
assert data['metadata']['duplicate_groups'] == 1
assert len(data['duplicates']) == 1
def test_report_summary(self, tmp_path):
"""Test summary report generation."""
# Create test inventory CSV
inventory_file = tmp_path / "inventory.csv"
with open(inventory_file, 'w', encoding='utf-8') as f:
f.write("# Generated: 2024-01-01T00:00:00\n")
f.write("# Library Root: /test/library\n")
f.write("path,filename,size_bytes,modified_timestamp,category,resolution,codec,duration_seconds,bitrate_kbps\n")
f.write("/test/library/movie/Movie1.mkv,Movie1.mkv,2000000000,2024-01-01T00:00:00,movie,,,\n")
f.write("/test/library/movie/Movie2.mkv,Movie2.mkv,1500000000,2024-01-01T00:00:00,movie,,,\n")
f.write("/test/library/series/Show.S01E01.mkv,Show.S01E01.mkv,1000000000,2024-01-01T00:00:00,series,,,\n")
f.write("/test/library/anime/Anime1.mkv,Anime1.mkv,800000000,2024-01-01T00:00:00,anime,,,\n")
# Run command
runner = CliRunner()
result = runner.invoke(main, [
'report', 'summary',
'--input', str(inventory_file)
])
# Verify success
assert result.exit_code == 0
assert "Loaded 4 files" in result.output
assert "Total Files: 4" in result.output
assert "Movie:" in result.output
assert "Series:" in result.output
assert "Anime:" in result.output
def test_report_summary_with_output_file(self, tmp_path):
"""Test summary report generation with output file."""
# Create test inventory CSV
inventory_file = tmp_path / "inventory.csv"
with open(inventory_file, 'w', encoding='utf-8') as f:
f.write("# Generated: 2024-01-01T00:00:00\n")
f.write("# Library Root: /test/library\n")
f.write("path,filename,size_bytes,modified_timestamp,category,resolution,codec,duration_seconds,bitrate_kbps\n")
f.write("/test/library/movie/Movie1.mkv,Movie1.mkv,1000000,2024-01-01T00:00:00,movie,,,\n")
# Run command with output file
output_file = tmp_path / "summary_report.txt"
runner = CliRunner()
result = runner.invoke(main, [
'report', 'summary',
'--input', str(inventory_file),
'--output', str(output_file)
])
# Verify success
assert result.exit_code == 0
assert output_file.exists()
# Verify file content
with open(output_file, 'r') as f:
content = f.read()
assert "Total Files: 1" in content
assert "Movie:" in content
def test_report_inventory_missing_file(self, tmp_path):
"""Test inventory report with missing input file."""
runner = CliRunner()
result = runner.invoke(main, [
'report', 'inventory',
'--input', str(tmp_path / "nonexistent.csv")
])
# Verify runtime missing-file handling
assert result.exit_code != 0
assert "Error: Input file not found:" in result.output
def test_report_completeness_missing_file(self, tmp_path):
"""Test completeness report with missing input file."""
runner = CliRunner()
result = runner.invoke(main, [
'report', 'completeness',
'--input', str(tmp_path / "nonexistent.json")
])
# Verify runtime missing-file handling
assert result.exit_code != 0
assert "Error: Input file not found:" in result.output