"""Tests for folder ignore patterns feature.""" import os import tempfile import warnings from unittest.mock import patch import pytest from src.config.settings import Settings class TestShouldIgnoreFolder: """Test should_ignore_folder method.""" def test_ignore_pattern_matches_exact(self): """Test exact folder name match.""" settings = Settings() assert settings.should_ignore_folder("The Last of Us") is True def test_ignore_pattern_matches_case_insensitive(self): """Test case-insensitive matching.""" settings = Settings() assert settings.should_ignore_folder("the last of us") is True assert settings.should_ignore_folder("THE LAST OF US") is True def test_ignore_pattern_partial_match(self): """Test partial folder name match.""" settings = Settings() assert settings.should_ignore_folder("Loki Season 2") is True assert settings.should_ignore_folder("Chernobyl Complete") is True def test_non_matching_folder_returns_false(self): """Test non-matching folder passes through.""" settings = Settings() assert settings.should_ignore_folder("Attack on Titan") is False assert settings.should_ignore_folder("Naruto") is False def test_empty_folder_returns_false(self): """Test empty folder name.""" settings = Settings() assert settings.should_ignore_folder("") is False def test_custom_patterns_via_env_var(self, monkeypatch): """Test custom ignore patterns via environment variable.""" monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "MyShow|AnotherShow") settings = Settings() assert settings.should_ignore_folder("MyShow") is True assert settings.should_ignore_folder("AnotherShow") is True assert settings.should_ignore_folder("OtherShow") is False def test_custom_patterns_case_insensitive_via_env_var(self, monkeypatch): """Test custom patterns respect case-insensitivity via env var.""" monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "myshow") settings = Settings() assert settings.should_ignore_folder("MyShow") is True assert settings.should_ignore_folder("MYSHOW") is True class TestFolderIgnorePatternsProperty: """Test folder_ignore_patterns property.""" def test_default_patterns_parsed(self): """Test default patterns are parsed correctly.""" settings = Settings() patterns = settings.folder_ignore_patterns assert len(patterns) > 0 assert "The Last of Us" in patterns assert "Loki" in patterns def test_empty_string_via_env_var_returns_empty_list(self, monkeypatch): """Test empty patterns string via env var.""" monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "") settings = Settings() patterns = settings.folder_ignore_patterns assert patterns == [] def test_single_pattern_via_env_var(self, monkeypatch): """Test single pattern via env var.""" monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "TestShow") settings = Settings() patterns = settings.folder_ignore_patterns # Single pattern in pipe-separated string assert "TestShow" in patterns def test_pipe_separated_patterns_via_env_var(self, monkeypatch): """Test pipe-separated patterns via env var.""" monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "Show1|Show2|Show3") settings = Settings() patterns = settings.folder_ignore_patterns assert len(patterns) == 3 assert "Show1" in patterns assert "Show2" in patterns assert "Show3" in patterns def test_pattern_with_spaces_trimmed_via_env_var(self, monkeypatch): """Test patterns with spaces are trimmed.""" monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "Show1 | Show2 | Show3 ") settings = Settings() patterns = settings.folder_ignore_patterns # All patterns should be trimmed of whitespace for p in patterns: assert p == p.strip() class TestSerieScannerIgnorePatterns: """Test SerieScanner respects ignore patterns.""" def test_scanner_skips_ignored_folders(self, tmp_path): """Test scanner skips folders matching ignore patterns.""" from src.core.SerieScanner import SerieScanner from src.core.providers.aniworld_provider import AniworldLoader # Create test folders ignored_folder = tmp_path / "The Last of Us" ignored_folder.mkdir() (ignored_folder / "S01E01.mp4").touch() normal_folder = tmp_path / "Attack on Titan" normal_folder.mkdir() (normal_folder / "S01E01.mp4").touch() loader = AniworldLoader() scanner = SerieScanner(str(tmp_path), loader) # Get MP4 files - should only find Attack on Titan mp4_files = list(scanner._SerieScanner__find_mp4_files()) folder_names = [name for name, _ in mp4_files] assert "Attack on Titan" in folder_names assert "The Last of Us" not in folder_names def test_scanner_normal_folders_not_ignored(self, tmp_path): """Test normal folders are not skipped.""" from src.core.SerieScanner import SerieScanner from src.core.providers.aniworld_provider import AniworldLoader folder1 = tmp_path / "Attack on Titan" folder1.mkdir() (folder1 / "S01E01.mp4").touch() folder2 = tmp_path / "Naruto" folder2.mkdir() (folder2 / "S01E01.mp4").touch() loader = AniworldLoader() scanner = SerieScanner(str(tmp_path), loader) mp4_files = list(scanner._SerieScanner__find_mp4_files()) folder_names = [name for name, _ in mp4_files] assert "Attack on Titan" in folder_names assert "Naruto" in folder_names def test_scanner_respects_default_ignore_patterns(self, tmp_path): """Test scanner respects default ignore patterns.""" from src.core.SerieScanner import SerieScanner from src.core.providers.aniworld_provider import AniworldLoader # Create folder matching default ignore pattern (Chernobyl) ignored_folder = tmp_path / "Chernobyl Complete Series" ignored_folder.mkdir() (ignored_folder / "S01E01.mp4").touch() normal_folder = tmp_path / "Normal Anime" normal_folder.mkdir() (normal_folder / "S01E01.mp4").touch() loader = AniworldLoader() scanner = SerieScanner(str(tmp_path), loader) mp4_files = list(scanner._SerieScanner__find_mp4_files()) folder_names = [name for name, _ in mp4_files] assert "Normal Anime" in folder_names assert "Chernobyl Complete Series" not in folder_names class TestSerieListIgnorePatterns: """Test SerieList respects ignore patterns.""" def test_load_series_skips_ignored_folders(self, tmp_path): """Test load_series skips folders matching ignore patterns.""" from src.core.entities.SerieList import SerieList from src.core.entities.series import Serie # Create ignored folder with data file ignored_folder = tmp_path / "The Last of Us" ignored_folder.mkdir() ignored_data = ignored_folder / "data" ignored_serie = Serie( key="the-last-of-us", name="The Last of Us", site="https://aniworld.to/anime/stream/the-last-of-us", folder="The Last of Us", episodeDict={1: [1, 2, 3]} ) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) ignored_serie.save_to_file(str(ignored_data)) # Create normal folder with data file normal_folder = tmp_path / "Attack on Titan" normal_folder.mkdir() normal_data = normal_folder / "data" normal_serie = Serie( key="attack-on-titan", name="Attack on Titan", site="https://aniworld.to/anime/stream/attack-on-titan", folder="Attack on Titan", episodeDict={1: [1, 2]} ) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) normal_serie.save_to_file(str(normal_data)) # Load series serie_list = SerieList(str(tmp_path)) # Verify ignored folder was skipped assert serie_list.contains("attack-on-titan") is True assert serie_list.contains("the-last-of-us") is False