"""Tests for quarantine manager.""" import json import pytest from pathlib import Path from datetime import datetime from vlm.quarantine import QuarantineManager from vlm.config import Config from vlm.models import QuarantineEntry, QuarantineManifest class TestQuarantineManager: """Test suite for QuarantineManager.""" @pytest.fixture def config(self, tmp_path): """Create a test configuration.""" library_root = tmp_path / "library" library_root.mkdir() # Create category directories (library_root / "movie").mkdir() (library_root / "series").mkdir() (library_root / "anime").mkdir() (library_root / "other").mkdir() return Config( library_root=library_root, quarantine_dir=".quarantine" ) @pytest.fixture def manager(self, config): """Create a quarantine manager instance.""" return QuarantineManager(config) def test_quarantine_movie_file(self, manager, config): """Test quarantining a movie file.""" # Create a test movie file movie_file = config.library_root / "movie" / "Test Movie (2020).mkv" movie_file.write_text("test content") # Quarantine the file result = manager.quarantine_file(movie_file, reason="duplicate") # Verify operation succeeded assert result.success is True assert result.error_message is None # Verify file was moved assert not movie_file.exists() # Verify file is in quarantine expected_quarantine_path = config.library_root / "movie" / ".quarantine" / "Test Movie (2020).mkv" assert expected_quarantine_path.exists() assert expected_quarantine_path.read_text() == "test content" def test_quarantine_series_file(self, manager, config): """Test quarantining a series file.""" # Create a test series file with subdirectory series_dir = config.library_root / "series" / "Test Show" / "Season 01" series_dir.mkdir(parents=True) series_file = series_dir / "S01E01.mkv" series_file.write_text("test content") # Quarantine the file result = manager.quarantine_file(series_file, reason="low quality") # Verify operation succeeded assert result.success is True assert result.error_message is None # Verify file was moved assert not series_file.exists() # Verify file is in quarantine with preserved structure expected_quarantine_path = ( config.library_root / "series" / ".quarantine" / "Test Show" / "Season 01" / "S01E01.mkv" ) assert expected_quarantine_path.exists() assert expected_quarantine_path.read_text() == "test content" def test_quarantine_anime_file_rejected(self, manager, config): """Test that quarantining anime files is rejected.""" # Create a test anime file anime_file = config.library_root / "anime" / "Test Anime.mkv" anime_file.write_text("test content") # Attempt to quarantine should raise ValueError with pytest.raises(ValueError, match="Quarantine not supported for category 'anime'"): manager.quarantine_file(anime_file) # Verify file was not moved assert anime_file.exists() def test_quarantine_other_file_rejected(self, manager, config): """Test that quarantining other files is rejected.""" # Create a test other file other_file = config.library_root / "other" / "Test File.mkv" other_file.write_text("test content") # Attempt to quarantine should raise ValueError with pytest.raises(ValueError, match="Quarantine not supported for category 'other'"): manager.quarantine_file(other_file) # Verify file was not moved assert other_file.exists() def test_quarantine_conflict_handling(self, manager, config): """Test that destination conflicts are handled with numeric suffixes.""" # Create a test movie file movie_file = config.library_root / "movie" / "Test Movie (2020).mkv" movie_file.write_text("original content") # Create a conflicting file in quarantine quarantine_dir = config.library_root / "movie" / ".quarantine" quarantine_dir.mkdir() existing_file = quarantine_dir / "Test Movie (2020).mkv" existing_file.write_text("existing content") # Quarantine the file result = manager.quarantine_file(movie_file) # Verify operation succeeded assert result.success is True # Verify original file was moved assert not movie_file.exists() # Verify existing file is unchanged assert existing_file.exists() assert existing_file.read_text() == "existing content" # Verify new file has numeric suffix new_file = quarantine_dir / "Test Movie (2020)_1.mkv" assert new_file.exists() assert new_file.read_text() == "original content" def test_quarantine_multiple_conflicts(self, manager, config): """Test handling multiple conflicts with incrementing suffixes.""" # Create quarantine directory with existing files quarantine_dir = config.library_root / "movie" / ".quarantine" quarantine_dir.mkdir() # Create existing files (quarantine_dir / "Test Movie (2020).mkv").write_text("file 0") (quarantine_dir / "Test Movie (2020)_1.mkv").write_text("file 1") (quarantine_dir / "Test Movie (2020)_2.mkv").write_text("file 2") # Create new file to quarantine movie_file = config.library_root / "movie" / "Test Movie (2020).mkv" movie_file.write_text("file 3") # Quarantine the file result = manager.quarantine_file(movie_file) # Verify operation succeeded assert result.success is True # Verify new file has suffix _3 new_file = quarantine_dir / "Test Movie (2020)_3.mkv" assert new_file.exists() assert new_file.read_text() == "file 3" def test_quarantine_nonexistent_file(self, manager, config): """Test quarantining a file that doesn't exist.""" # Try to quarantine non-existent file nonexistent_file = config.library_root / "movie" / "Nonexistent.mkv" result = manager.quarantine_file(nonexistent_file) # Verify operation failed assert result.success is False assert "does not exist" in result.error_message def test_quarantine_preserves_directory_structure(self, manager, config): """Test that quarantine preserves relative directory structure.""" # Create a deeply nested series file series_path = config.library_root / "series" / "Show" / "Season 02" / "Extras" series_path.mkdir(parents=True) series_file = series_path / "Behind the Scenes.mkv" series_file.write_text("test content") # Quarantine the file result = manager.quarantine_file(series_file) # Verify operation succeeded assert result.success is True # Verify structure is preserved in quarantine expected_path = ( config.library_root / "series" / ".quarantine" / "Show" / "Season 02" / "Extras" / "Behind the Scenes.mkv" ) assert expected_path.exists() assert expected_path.read_text() == "test content" def test_determine_category_movie(self, manager, config): """Test category determination for movie files.""" movie_file = config.library_root / "movie" / "Test.mkv" category = manager._determine_category(movie_file) assert category == "movie" def test_determine_category_series(self, manager, config): """Test category determination for series files.""" series_file = config.library_root / "series" / "Show" / "S01E01.mkv" category = manager._determine_category(series_file) assert category == "series" def test_determine_category_anime(self, manager, config): """Test category determination for anime files.""" anime_file = config.library_root / "anime" / "Test.mkv" category = manager._determine_category(anime_file) assert category == "anime" def test_determine_category_other(self, manager, config): """Test category determination for other files.""" other_file = config.library_root / "other" / "Test.mkv" category = manager._determine_category(other_file) assert category == "other" def test_determine_category_outside_library(self, manager, config): """Test category determination for files outside library.""" outside_file = Path("/tmp/Test.mkv") category = manager._determine_category(outside_file) assert category == "other" def test_resolve_conflict_no_conflict(self, manager, config): """Test conflict resolution when no conflict exists.""" test_path = config.library_root / "movie" / ".quarantine" / "Test.mkv" resolved = manager._resolve_conflict(test_path) assert resolved == test_path def test_resolve_conflict_with_conflict(self, manager, config): """Test conflict resolution when conflict exists.""" quarantine_dir = config.library_root / "movie" / ".quarantine" quarantine_dir.mkdir(parents=True) # Create existing file existing = quarantine_dir / "Test.mkv" existing.write_text("existing") # Resolve conflict resolved = manager._resolve_conflict(existing) # Should return path with _1 suffix assert resolved == quarantine_dir / "Test_1.mkv" assert not resolved.exists() class TestQuarantineManifest: """Test suite for quarantine manifest management.""" @pytest.fixture def config(self, tmp_path): """Create a test configuration.""" library_root = tmp_path / "library" library_root.mkdir() # Create category directories (library_root / "movie").mkdir() (library_root / "series").mkdir() return Config( library_root=library_root, quarantine_dir=".quarantine" ) @pytest.fixture def manager(self, config): """Create a quarantine manager instance.""" return QuarantineManager(config) def test_manifest_created_on_first_quarantine(self, manager, config): """Test that manifest is created when first file is quarantined.""" # Create a test movie file movie_file = config.library_root / "movie" / "Test Movie (2020).mkv" movie_file.write_text("test content") # Quarantine the file result = manager.quarantine_file(movie_file, reason="duplicate") # Verify operation succeeded assert result.success is True # Verify manifest was created manifest_path = config.library_root / "movie" / ".quarantine" / "manifest.json" assert manifest_path.exists() # Load and verify manifest content with open(manifest_path, 'r') as f: data = json.load(f) assert 'entries' in data assert len(data['entries']) == 1 entry = data['entries'][0] assert entry['original_path'] == str(movie_file) assert entry['category'] == "movie" assert entry['reason'] == "duplicate" assert entry['size_bytes'] == len("test content") assert 'quarantined_at' in entry assert 'quarantine_path' in entry def test_manifest_updated_on_subsequent_quarantine(self, manager, config): """Test that manifest is updated when additional files are quarantined.""" # Create and quarantine first file movie_file1 = config.library_root / "movie" / "Movie1.mkv" movie_file1.write_text("content1") manager.quarantine_file(movie_file1, reason="duplicate") # Create and quarantine second file movie_file2 = config.library_root / "movie" / "Movie2.mkv" movie_file2.write_text("content2") manager.quarantine_file(movie_file2, reason="low quality") # Load manifest manifest_path = config.library_root / "movie" / ".quarantine" / "manifest.json" with open(manifest_path, 'r') as f: data = json.load(f) # Verify both entries are in manifest assert len(data['entries']) == 2 # Verify first entry entry1 = data['entries'][0] assert entry1['original_path'] == str(movie_file1) assert entry1['reason'] == "duplicate" # Verify second entry entry2 = data['entries'][1] assert entry2['original_path'] == str(movie_file2) assert entry2['reason'] == "low quality" def test_manifest_includes_all_required_fields(self, manager, config): """Test that manifest entries include all required fields.""" # Create a test series file series_dir = config.library_root / "series" / "Show" / "Season 01" series_dir.mkdir(parents=True) series_file = series_dir / "S01E01.mkv" series_file.write_text("test content") # Quarantine the file manager.quarantine_file(series_file, reason="test reason") # Load manifest manifest_path = config.library_root / "series" / ".quarantine" / "manifest.json" with open(manifest_path, 'r') as f: data = json.load(f) entry = data['entries'][0] # Verify all required fields are present assert 'original_path' in entry assert 'quarantine_path' in entry assert 'quarantined_at' in entry assert 'reason' in entry assert 'size_bytes' in entry assert 'category' in entry # Verify field values assert entry['original_path'] == str(series_file) assert entry['category'] == "series" assert entry['reason'] == "test reason" assert entry['size_bytes'] == len("test content") # Verify timestamp is valid ISO format datetime.fromisoformat(entry['quarantined_at']) def test_manifest_separate_per_category(self, manager, config): """Test that each category has its own manifest.""" # Create and quarantine movie file movie_file = config.library_root / "movie" / "Movie.mkv" movie_file.write_text("movie content") manager.quarantine_file(movie_file) # Create and quarantine series file series_file = config.library_root / "series" / "S01E01.mkv" series_file.write_text("series content") manager.quarantine_file(series_file) # Verify separate manifests exist movie_manifest_path = config.library_root / "movie" / ".quarantine" / "manifest.json" series_manifest_path = config.library_root / "series" / ".quarantine" / "manifest.json" assert movie_manifest_path.exists() assert series_manifest_path.exists() # Verify movie manifest contains only movie entry with open(movie_manifest_path, 'r') as f: movie_data = json.load(f) assert len(movie_data['entries']) == 1 assert movie_data['entries'][0]['category'] == "movie" # Verify series manifest contains only series entry with open(series_manifest_path, 'r') as f: series_data = json.load(f) assert len(series_data['entries']) == 1 assert series_data['entries'][0]['category'] == "series" def test_manifest_handles_none_reason(self, manager, config): """Test that manifest handles files quarantined without a reason.""" # Create and quarantine file without reason movie_file = config.library_root / "movie" / "Movie.mkv" movie_file.write_text("content") manager.quarantine_file(movie_file) # No reason provided # Load manifest manifest_path = config.library_root / "movie" / ".quarantine" / "manifest.json" with open(manifest_path, 'r') as f: data = json.load(f) entry = data['entries'][0] # Verify reason is None/null assert entry['reason'] is None def test_load_manifest_empty_when_not_exists(self, manager, config): """Test that loading non-existent manifest returns empty manifest.""" manifest = manager._load_manifest("movie") assert isinstance(manifest, QuarantineManifest) assert len(manifest.entries) == 0 def test_load_manifest_parses_existing_manifest(self, manager, config): """Test that loading existing manifest parses entries correctly.""" # Create manifest manually manifest_path = config.library_root / "movie" / ".quarantine" / "manifest.json" manifest_path.parent.mkdir(parents=True) test_data = { 'entries': [ { 'original_path': '/path/to/original.mkv', 'quarantine_path': '/path/to/quarantine.mkv', 'quarantined_at': '2024-01-15T10:30:00', 'reason': 'test reason', 'size_bytes': 1024, 'category': 'movie' } ] } with open(manifest_path, 'w') as f: json.dump(test_data, f) # Load manifest manifest = manager._load_manifest("movie") # Verify parsed correctly assert len(manifest.entries) == 1 entry = manifest.entries[0] assert entry.original_path == Path('/path/to/original.mkv') assert entry.quarantine_path == Path('/path/to/quarantine.mkv') assert entry.quarantined_at == datetime(2024, 1, 15, 10, 30, 0) assert entry.reason == 'test reason' assert entry.size_bytes == 1024 assert entry.category == 'movie' def test_save_manifest_creates_directory(self, manager, config): """Test that saving manifest creates quarantine directory if needed.""" # Create manifest manifest = QuarantineManifest(entries=[]) # Save manifest (directory doesn't exist yet) manager._save_manifest("movie", manifest) # Verify directory and file were created manifest_path = config.library_root / "movie" / ".quarantine" / "manifest.json" assert manifest_path.exists() assert manifest_path.parent.is_dir() def test_manifest_preserves_utf8_characters(self, manager, config): """Test that manifest correctly handles UTF-8 characters in paths and reasons.""" # Create file with UTF-8 characters movie_file = config.library_root / "movie" / "Café Müller (2020).mkv" movie_file.write_text("content") # Quarantine with UTF-8 reason manager.quarantine_file(movie_file, reason="Qualité insuffisante") # Load manifest manifest_path = config.library_root / "movie" / ".quarantine" / "manifest.json" with open(manifest_path, 'r', encoding='utf-8') as f: data = json.load(f) entry = data['entries'][0] # Verify UTF-8 characters are preserved assert "Café Müller" in entry['original_path'] assert entry['reason'] == "Qualité insuffisante" class TestQuarantineListing: """Test suite for quarantine listing functionality.""" @pytest.fixture def config(self, tmp_path): """Create a test configuration.""" library_root = tmp_path / "library" library_root.mkdir() # Create category directories (library_root / "movie").mkdir() (library_root / "series").mkdir() return Config( library_root=library_root, quarantine_dir=".quarantine" ) @pytest.fixture def manager(self, config): """Create a quarantine manager instance.""" return QuarantineManager(config) def test_list_quarantined_empty(self, manager, config): """Test listing quarantined files when none exist.""" entries = manager.list_quarantined() assert entries == [] def test_list_quarantined_single_category(self, manager, config): """Test listing quarantined files from a single category.""" # Create and quarantine movie files movie1 = config.library_root / "movie" / "Movie1.mkv" movie1.write_text("content1") manager.quarantine_file(movie1, reason="duplicate") movie2 = config.library_root / "movie" / "Movie2.mkv" movie2.write_text("content2") manager.quarantine_file(movie2, reason="low quality") # List quarantined files from movie category entries = manager.list_quarantined(category="movie") assert len(entries) == 2 assert all(e.category == "movie" for e in entries) # Verify entries contain expected data original_paths = [str(e.original_path) for e in entries] assert str(movie1) in original_paths assert str(movie2) in original_paths def test_list_quarantined_all_categories(self, manager, config): """Test listing quarantined files from all categories.""" # Create and quarantine movie file movie = config.library_root / "movie" / "Movie.mkv" movie.write_text("movie content") manager.quarantine_file(movie, reason="duplicate") # Create and quarantine series file series = config.library_root / "series" / "S01E01.mkv" series.write_text("series content") manager.quarantine_file(series, reason="low quality") # List all quarantined files entries = manager.list_quarantined() assert len(entries) == 2 # Verify both categories are represented categories = [e.category for e in entries] assert "movie" in categories assert "series" in categories def test_list_quarantined_filter_by_category(self, manager, config): """Test filtering quarantined files by category.""" # Create and quarantine files in both categories movie = config.library_root / "movie" / "Movie.mkv" movie.write_text("movie content") manager.quarantine_file(movie) series = config.library_root / "series" / "S01E01.mkv" series.write_text("series content") manager.quarantine_file(series) # List only movie files movie_entries = manager.list_quarantined(category="movie") assert len(movie_entries) == 1 assert movie_entries[0].category == "movie" # List only series files series_entries = manager.list_quarantined(category="series") assert len(series_entries) == 1 assert series_entries[0].category == "series" def test_list_quarantined_invalid_category(self, manager, config): """Test listing with invalid category returns empty list.""" entries = manager.list_quarantined(category="anime") assert entries == [] entries = manager.list_quarantined(category="other") assert entries == [] entries = manager.list_quarantined(category="invalid") assert entries == [] def test_list_quarantined_includes_all_fields(self, manager, config): """Test that listed entries include all required fields.""" # Create and quarantine file movie = config.library_root / "movie" / "Movie.mkv" movie.write_text("test content") manager.quarantine_file(movie, reason="test reason") # List quarantined files entries = manager.list_quarantined() assert len(entries) == 1 entry = entries[0] # Verify all fields are present assert entry.original_path == movie assert entry.quarantine_path.exists() assert entry.quarantined_at is not None assert entry.reason == "test reason" assert entry.size_bytes == len("test content") assert entry.category == "movie" def test_list_quarantined_preserves_directory_structure(self, manager, config): """Test that listing shows preserved directory structure.""" # Create nested series file series_path = config.library_root / "series" / "Show" / "Season 01" series_path.mkdir(parents=True) series_file = series_path / "S01E01.mkv" series_file.write_text("content") # Quarantine the file manager.quarantine_file(series_file) # List quarantined files entries = manager.list_quarantined(category="series") assert len(entries) == 1 entry = entries[0] # Verify quarantine path preserves structure expected_quarantine = ( config.library_root / "series" / ".quarantine" / "Show" / "Season 01" / "S01E01.mkv" ) assert entry.quarantine_path == expected_quarantine def test_list_quarantined_multiple_files_same_category(self, manager, config): """Test listing multiple files from the same category.""" # Create and quarantine multiple movie files for i in range(5): movie = config.library_root / "movie" / f"Movie{i}.mkv" movie.write_text(f"content{i}") manager.quarantine_file(movie, reason=f"reason{i}") # List quarantined files entries = manager.list_quarantined(category="movie") assert len(entries) == 5 # Verify all entries are unique original_paths = [e.original_path for e in entries] assert len(set(original_paths)) == 5 class TestQuarantineRestoration: """Test suite for quarantine restoration functionality.""" @pytest.fixture def config(self, tmp_path): """Create a test configuration.""" library_root = tmp_path / "library" library_root.mkdir() # Create category directories (library_root / "movie").mkdir() (library_root / "series").mkdir() return Config( library_root=library_root, quarantine_dir=".quarantine" ) @pytest.fixture def manager(self, config): """Create a quarantine manager instance.""" return QuarantineManager(config) def test_restore_movie_file(self, manager, config): """Test restoring a quarantined movie file.""" # Create and quarantine movie file original_path = config.library_root / "movie" / "Movie.mkv" original_path.write_text("test content") result = manager.quarantine_file(original_path, reason="duplicate") assert result.success is True quarantine_path = result.operation.destination_path # Verify file is in quarantine assert quarantine_path.exists() assert not original_path.exists() # Restore the file restore_result = manager.restore_from_quarantine(quarantine_path) # Verify restoration succeeded assert restore_result.success is True assert restore_result.error_message is None # Verify file is back at original location assert original_path.exists() assert original_path.read_text() == "test content" # Verify file is removed from quarantine assert not quarantine_path.exists() def test_restore_series_file(self, manager, config): """Test restoring a quarantined series file.""" # Create nested series file series_path = config.library_root / "series" / "Show" / "Season 01" series_path.mkdir(parents=True) original_path = series_path / "S01E01.mkv" original_path.write_text("series content") # Quarantine the file result = manager.quarantine_file(original_path) quarantine_path = result.operation.destination_path # Restore the file restore_result = manager.restore_from_quarantine(quarantine_path) # Verify restoration succeeded assert restore_result.success is True # Verify file is back with preserved structure assert original_path.exists() assert original_path.read_text() == "series content" assert not quarantine_path.exists() def test_restore_removes_manifest_entry(self, manager, config): """Test that restoration removes entry from manifest.""" # Create and quarantine file original_path = config.library_root / "movie" / "Movie.mkv" original_path.write_text("content") result = manager.quarantine_file(original_path) quarantine_path = result.operation.destination_path # Verify manifest has entry manifest = manager._load_manifest("movie") assert len(manifest.entries) == 1 # Restore the file manager.restore_from_quarantine(quarantine_path) # Verify manifest entry is removed manifest = manager._load_manifest("movie") assert len(manifest.entries) == 0 def test_restore_nonexistent_file(self, manager, config): """Test restoring a file that doesn't exist.""" # Try to restore non-existent file nonexistent = config.library_root / "movie" / ".quarantine" / "Nonexistent.mkv" result = manager.restore_from_quarantine(nonexistent) # Verify operation failed assert result.success is False assert "does not exist" in result.error_message def test_restore_conflict_destination_exists(self, manager, config): """Test restoration when original location already has a file.""" # Create and quarantine file original_path = config.library_root / "movie" / "Movie.mkv" original_path.write_text("original content") result = manager.quarantine_file(original_path) quarantine_path = result.operation.destination_path # Create a new file at original location original_path.write_text("new content") # Try to restore restore_result = manager.restore_from_quarantine(quarantine_path) # Verify restoration failed due to conflict assert restore_result.success is False assert "already exists" in restore_result.error_message assert restore_result.operation.has_conflict is True # Verify original file is unchanged assert original_path.read_text() == "new content" # Verify quarantine file still exists assert quarantine_path.exists() def test_restore_creates_parent_directory(self, manager, config): """Test that restoration creates parent directory if needed.""" # Create and quarantine file series_path = config.library_root / "series" / "Show" / "Season 01" series_path.mkdir(parents=True) original_path = series_path / "S01E01.mkv" original_path.write_text("content") result = manager.quarantine_file(original_path) quarantine_path = result.operation.destination_path # Remove the parent directory import shutil shutil.rmtree(series_path) # Restore the file restore_result = manager.restore_from_quarantine(quarantine_path) # Verify restoration succeeded and directory was created assert restore_result.success is True assert original_path.exists() assert original_path.parent.is_dir() def test_restore_no_manifest_entry(self, manager, config): """Test restoring a file that has no manifest entry.""" # Create quarantine file manually without manifest entry quarantine_dir = config.library_root / "movie" / ".quarantine" quarantine_dir.mkdir(parents=True) quarantine_path = quarantine_dir / "Movie.mkv" quarantine_path.write_text("content") # Try to restore result = manager.restore_from_quarantine(quarantine_path) # Verify operation failed assert result.success is False assert "No manifest entry" in result.error_message def test_restore_invalid_quarantine_path(self, manager, config): """Test restoring from an invalid quarantine path.""" # Try to restore from non-quarantine location invalid_path = config.library_root / "movie" / "Movie.mkv" invalid_path.write_text("content") result = manager.restore_from_quarantine(invalid_path) # Verify operation failed assert result.success is False assert "Could not determine category" in result.error_message def test_restore_multiple_files(self, manager, config): """Test restoring multiple quarantined files.""" # Create and quarantine multiple files files = [] quarantine_paths = [] for i in range(3): file_path = config.library_root / "movie" / f"Movie{i}.mkv" file_path.write_text(f"content{i}") files.append(file_path) result = manager.quarantine_file(file_path) quarantine_paths.append(result.operation.destination_path) # Verify all files are quarantined for file_path in files: assert not file_path.exists() for qpath in quarantine_paths: assert qpath.exists() # Restore all files for qpath in quarantine_paths: result = manager.restore_from_quarantine(qpath) assert result.success is True # Verify all files are restored for i, file_path in enumerate(files): assert file_path.exists() assert file_path.read_text() == f"content{i}" # Verify all quarantine files are removed for qpath in quarantine_paths: assert not qpath.exists() # Verify manifest is empty manifest = manager._load_manifest("movie") assert len(manifest.entries) == 0 def test_determine_category_from_quarantine_movie(self, manager, config): """Test determining category from movie quarantine path.""" qpath = config.library_root / "movie" / ".quarantine" / "Movie.mkv" category = manager._determine_category_from_quarantine(qpath) assert category == "movie" def test_determine_category_from_quarantine_series(self, manager, config): """Test determining category from series quarantine path.""" qpath = config.library_root / "series" / ".quarantine" / "Show" / "S01E01.mkv" category = manager._determine_category_from_quarantine(qpath) assert category == "series" def test_determine_category_from_quarantine_invalid(self, manager, config): """Test determining category from invalid quarantine path.""" # Not in quarantine directory invalid = config.library_root / "movie" / "Movie.mkv" category = manager._determine_category_from_quarantine(invalid) assert category is None # Outside library root outside = Path("/tmp/Movie.mkv") category = manager._determine_category_from_quarantine(outside) assert category is None # Unsupported category anime = config.library_root / "anime" / ".quarantine" / "Anime.mkv" category = manager._determine_category_from_quarantine(anime) assert category is None