"""Integration tests for CLI report commands. Tests the report commands to ensure they properly wire to the Report Generator. """ import json import csv from pathlib import Path from datetime import datetime, timezone 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