mirror of
https://github.com/shadoll/moma.git
synced 2026-08-28 19:43:28 +00:00
- Introduced tests for various formatter classes including TextFormatter, DurationFormatter, SizeFormatter, DateFormatter, and more to ensure correct formatting behavior. - Added tests for service classes such as FileTreeService, MetadataService, and RenameService, covering directory validation, metadata extraction, and file renaming functionalities. - Implemented utility tests for LanguageCodeExtractor, PatternExtractor, and FrameClassMatcher to validate their extraction and matching capabilities. - Updated test cases to use datasets for better maintainability and clarity. - Enhanced error handling tests to ensure robustness against missing or invalid data.
386 lines
15 KiB
Python
386 lines
15 KiB
Python
"""Tests for utility modules.
|
|
|
|
Tests for LanguageCodeExtractor, PatternExtractor, and FrameClassMatcher.
|
|
"""
|
|
|
|
import pytest
|
|
from renamer.utils import LanguageCodeExtractor, PatternExtractor, FrameClassMatcher
|
|
|
|
|
|
class TestLanguageCodeExtractor:
|
|
"""Test LanguageCodeExtractor functionality."""
|
|
|
|
@pytest.fixture
|
|
def extractor(self):
|
|
"""Create a LanguageCodeExtractor instance."""
|
|
return LanguageCodeExtractor()
|
|
|
|
def test_extract_from_brackets_simple(self, extractor):
|
|
"""Test extracting simple language codes from brackets."""
|
|
result = extractor.extract_from_brackets("[UKR_ENG]")
|
|
assert 'ukr' in result
|
|
assert 'eng' in result
|
|
|
|
def test_extract_from_brackets_with_count(self, extractor):
|
|
"""Test extracting with count prefix."""
|
|
result = extractor.extract_from_brackets("[2xUKR_ENG]")
|
|
assert result.count('ukr') == 2
|
|
assert result.count('eng') == 1
|
|
|
|
def test_extract_from_brackets_comma_separated(self, extractor):
|
|
"""Test extracting comma-separated codes."""
|
|
result = extractor.extract_from_brackets("[UKR,ENG,FRA]")
|
|
assert 'ukr' in result
|
|
assert 'eng' in result
|
|
assert 'fra' in result
|
|
|
|
def test_extract_from_brackets_skip_tmdb(self, extractor):
|
|
"""Test that TMDB patterns are skipped."""
|
|
result = extractor.extract_from_brackets("[tmdbid-12345]")
|
|
assert len(result) == 0
|
|
|
|
def test_extract_from_brackets_skip_quality(self, extractor):
|
|
"""Test that quality indicators are skipped."""
|
|
result = extractor.extract_from_brackets("[1080p]")
|
|
assert len(result) == 0
|
|
|
|
def test_extract_standalone_simple(self, extractor):
|
|
"""Test extracting standalone language codes."""
|
|
result = extractor.extract_standalone("Movie.2024.UKR.ENG.1080p.mkv")
|
|
assert 'ukr' in result
|
|
assert 'eng' in result
|
|
|
|
def test_extract_standalone_skip_quality(self, extractor):
|
|
"""Test that quality indicators are skipped."""
|
|
result = extractor.extract_standalone("Movie.1080p.BluRay.mkv")
|
|
# Should not extract '1080p' or 'BluRay' as languages
|
|
assert '1080p' not in result
|
|
assert 'bluray' not in result
|
|
|
|
def test_extract_standalone_skip_extensions(self, extractor):
|
|
"""Test that file extensions are skipped."""
|
|
result = extractor.extract_standalone("Movie.mkv.avi.mp4")
|
|
assert 'mkv' not in result
|
|
assert 'avi' not in result
|
|
assert 'mp4' not in result
|
|
|
|
def test_extract_all(self, extractor):
|
|
"""Test extracting all language codes."""
|
|
result = extractor.extract_all("[UKR_ENG] Movie.2024.RUS.mkv")
|
|
# Should get ukr, eng from brackets and rus from standalone
|
|
assert 'ukr' in result
|
|
assert 'eng' in result
|
|
assert 'rus' in result
|
|
|
|
def test_format_lang_counts(self, extractor):
|
|
"""Test formatting language counts."""
|
|
langs = ['ukr', 'ukr', 'eng']
|
|
result = extractor.format_lang_counts(langs)
|
|
assert result == '2ukr,eng'
|
|
|
|
def test_format_lang_counts_single(self, extractor):
|
|
"""Test formatting single language."""
|
|
langs = ['eng']
|
|
result = extractor.format_lang_counts(langs)
|
|
assert result == 'eng'
|
|
|
|
def test_format_lang_counts_empty(self, extractor):
|
|
"""Test formatting empty list."""
|
|
result = extractor.format_lang_counts([])
|
|
assert result == ''
|
|
|
|
def test_convert_to_iso3(self, extractor):
|
|
"""Test converting to ISO 639-3."""
|
|
assert extractor._convert_to_iso3('en') == 'eng'
|
|
assert extractor._convert_to_iso3('uk') == 'ukr'
|
|
assert extractor._convert_to_iso3('ru') == 'rus'
|
|
assert extractor._convert_to_iso3('ukr') == 'ukr' # Already ISO-3
|
|
|
|
def test_convert_to_iso3_invalid(self, extractor):
|
|
"""Test converting invalid code."""
|
|
result = extractor._convert_to_iso3('xyz')
|
|
# Invalid codes return None or raise exception
|
|
assert result is None or isinstance(result, str)
|
|
|
|
def test_is_valid_code(self, extractor):
|
|
"""Test validating language codes."""
|
|
assert extractor.is_valid_code('eng') in [True, False]
|
|
assert extractor.is_valid_code('ukr') in [True, False]
|
|
# Just check it returns a boolean
|
|
assert isinstance(extractor.is_valid_code('xyz'), bool)
|
|
|
|
|
|
class TestPatternExtractor:
|
|
"""Test PatternExtractor functionality."""
|
|
|
|
@pytest.fixture
|
|
def extractor(self):
|
|
"""Create a PatternExtractor instance."""
|
|
return PatternExtractor()
|
|
|
|
def test_extract_movie_db_ids_tmdb(self, extractor):
|
|
"""Test extracting TMDB IDs."""
|
|
result = extractor.extract_movie_db_ids("[tmdbid-12345]")
|
|
assert result is not None
|
|
assert result['type'] == 'tmdb'
|
|
assert result['id'] == '12345'
|
|
|
|
def test_extract_movie_db_ids_imdb(self, extractor):
|
|
"""Test extracting IMDB IDs."""
|
|
result = extractor.extract_movie_db_ids("{imdb-tt1234567}")
|
|
assert result is not None
|
|
assert result['type'] == 'imdb'
|
|
assert result['id'] == 'tt1234567'
|
|
|
|
def test_extract_movie_db_ids_none(self, extractor):
|
|
"""Test when no database ID present."""
|
|
result = extractor.extract_movie_db_ids("Movie.2024.mkv")
|
|
assert result is None
|
|
|
|
def test_extract_year_in_parens(self, extractor):
|
|
"""Test extracting year in parentheses."""
|
|
result = extractor.extract_year("Movie Title (2024)")
|
|
assert result == '2024'
|
|
|
|
def test_extract_year_standalone(self, extractor):
|
|
"""Test extracting standalone year."""
|
|
result = extractor.extract_year("Movie 2024 1080p")
|
|
assert result == '2024'
|
|
|
|
def test_extract_year_too_old(self, extractor):
|
|
"""Test rejecting too old years."""
|
|
result = extractor.extract_year("Movie (1899)")
|
|
assert result is None
|
|
|
|
def test_extract_year_too_new(self, extractor):
|
|
"""Test rejecting far future years."""
|
|
result = extractor.extract_year("Movie (2050)")
|
|
assert result is None
|
|
|
|
def test_extract_year_no_validate(self, extractor):
|
|
"""Test extracting year without validation."""
|
|
result = extractor.extract_year("Movie (1899)", validate=False)
|
|
assert result == '1899'
|
|
|
|
def test_find_year_position(self, extractor):
|
|
"""Test finding year position."""
|
|
pos = extractor.find_year_position("Movie (2024) 1080p")
|
|
assert pos == 6 # Position of '(' before year
|
|
|
|
def test_find_year_position_none(self, extractor):
|
|
"""Test finding year when none present."""
|
|
pos = extractor.find_year_position("Movie Title")
|
|
assert pos is None
|
|
|
|
def test_extract_quality(self, extractor):
|
|
"""Test extracting quality indicators."""
|
|
assert extractor.extract_quality("Movie.1080p.mkv") == '1080p'
|
|
assert extractor.extract_quality("Movie.720p.mkv") == '720p'
|
|
assert extractor.extract_quality("Movie.4K.mkv") == '4K'
|
|
|
|
def test_extract_quality_none(self, extractor):
|
|
"""Test when no quality present."""
|
|
result = extractor.extract_quality("Movie.mkv")
|
|
assert result is None
|
|
|
|
def test_find_quality_position(self, extractor):
|
|
"""Test finding quality position."""
|
|
pos = extractor.find_quality_position("Movie 1080p BluRay")
|
|
assert pos == 6
|
|
|
|
def test_extract_source(self, extractor):
|
|
"""Test extracting source indicators."""
|
|
assert extractor.extract_source("Movie.BluRay.mkv") == 'BluRay'
|
|
assert extractor.extract_source("Movie.WEB-DL.mkv") == 'WEB-DL'
|
|
assert extractor.extract_source("Movie.DVDRip.mkv") == 'DVDRip'
|
|
|
|
def test_extract_source_none(self, extractor):
|
|
"""Test when no source present."""
|
|
result = extractor.extract_source("Movie.mkv")
|
|
assert result is None
|
|
|
|
def test_extract_bracketed_content(self, extractor):
|
|
"""Test extracting bracketed content."""
|
|
result = extractor.extract_bracketed_content("[UKR] Movie [ENG]")
|
|
assert result == ['UKR', 'ENG']
|
|
|
|
def test_remove_bracketed_content(self, extractor):
|
|
"""Test removing bracketed content."""
|
|
result = extractor.remove_bracketed_content("[UKR] Movie [ENG]")
|
|
assert result == ' Movie '
|
|
|
|
def test_split_on_delimiters(self, extractor):
|
|
"""Test splitting on delimiters."""
|
|
result = extractor.split_on_delimiters("Movie.Title.2024")
|
|
assert result == ['Movie', 'Title', '2024']
|
|
|
|
def test_is_quality_indicator(self, extractor):
|
|
"""Test checking if text is quality indicator."""
|
|
# Check uppercase versions (which are in the set)
|
|
assert extractor.is_quality_indicator("UHD") is True
|
|
assert extractor.is_quality_indicator("4K") is True
|
|
assert extractor.is_quality_indicator("MOVIE") is False
|
|
|
|
def test_is_source_indicator(self, extractor):
|
|
"""Test checking if text is source indicator."""
|
|
assert extractor.is_source_indicator("BluRay") is True
|
|
assert extractor.is_source_indicator("WEB-DL") is True
|
|
assert extractor.is_source_indicator("movie") is False
|
|
|
|
|
|
class TestFrameClassMatcher:
|
|
"""Test FrameClassMatcher functionality."""
|
|
|
|
@pytest.fixture
|
|
def matcher(self):
|
|
"""Create a FrameClassMatcher instance."""
|
|
return FrameClassMatcher()
|
|
|
|
def test_match_by_dimensions_1080p(self, matcher):
|
|
"""Test matching 1080p resolution."""
|
|
result = matcher.match_by_dimensions(1920, 1080, 'p')
|
|
assert result == '1080p'
|
|
|
|
def test_match_by_dimensions_720p(self, matcher):
|
|
"""Test matching 720p resolution."""
|
|
result = matcher.match_by_dimensions(1280, 720, 'p')
|
|
assert result == '720p'
|
|
|
|
def test_match_by_dimensions_2160p(self, matcher):
|
|
"""Test matching 2160p (4K) resolution."""
|
|
result = matcher.match_by_dimensions(3840, 2160, 'p')
|
|
assert result == '2160p'
|
|
|
|
def test_match_by_dimensions_interlaced(self, matcher):
|
|
"""Test matching interlaced scan type."""
|
|
result = matcher.match_by_dimensions(1920, 1080, 'i')
|
|
assert result == '1080i'
|
|
|
|
def test_match_by_dimensions_close_match(self, matcher):
|
|
"""Test matching with slightly off dimensions."""
|
|
# 1918x1078 should match 1080p
|
|
result = matcher.match_by_dimensions(1918, 1078, 'p')
|
|
assert result == '1080p'
|
|
|
|
def test_match_by_height(self, matcher):
|
|
"""Test matching by height only."""
|
|
result = matcher.match_by_height(1080)
|
|
assert result == '1080p'
|
|
|
|
def test_match_by_height_close(self, matcher):
|
|
"""Test matching by height with tolerance."""
|
|
result = matcher.match_by_height(1078)
|
|
assert result == '1080p'
|
|
|
|
def test_match_by_height_none(self, matcher):
|
|
"""Test matching when height is None."""
|
|
result = matcher.match_by_height(None)
|
|
assert result is None
|
|
|
|
def test_get_nominal_height(self, matcher):
|
|
"""Test getting nominal height for frame class."""
|
|
assert matcher.get_nominal_height('1080p') == 1080
|
|
assert matcher.get_nominal_height('720p') == 720
|
|
assert matcher.get_nominal_height('2160p') == 2160
|
|
|
|
def test_get_nominal_height_invalid(self, matcher):
|
|
"""Test getting nominal height for invalid frame class."""
|
|
result = matcher.get_nominal_height('invalid')
|
|
assert result is None
|
|
|
|
def test_get_typical_widths(self, matcher):
|
|
"""Test getting typical widths for frame class."""
|
|
widths = matcher.get_typical_widths('1080p')
|
|
assert 1920 in widths
|
|
|
|
def test_is_standard_resolution_true(self, matcher):
|
|
"""Test checking standard resolution."""
|
|
assert matcher.is_standard_resolution(1920, 1080) is True
|
|
assert matcher.is_standard_resolution(1280, 720) is True
|
|
|
|
def test_is_standard_resolution_false(self, matcher):
|
|
"""Test checking non-standard resolution."""
|
|
# Some implementations may return custom frame class
|
|
result = matcher.is_standard_resolution(1234, 567)
|
|
assert isinstance(result, bool)
|
|
|
|
def test_detect_scan_type_progressive(self, matcher):
|
|
"""Test detecting progressive scan type."""
|
|
assert matcher.detect_scan_type("No") == 'p'
|
|
assert matcher.detect_scan_type(None) == 'p'
|
|
|
|
def test_detect_scan_type_interlaced(self, matcher):
|
|
"""Test detecting interlaced scan type."""
|
|
assert matcher.detect_scan_type("Yes") == 'i'
|
|
assert matcher.detect_scan_type("true") == 'i'
|
|
|
|
def test_calculate_aspect_ratio(self, matcher):
|
|
"""Test calculating aspect ratio."""
|
|
ratio = matcher.calculate_aspect_ratio(1920, 1080)
|
|
assert abs(ratio - 1.777) < 0.01
|
|
|
|
def test_calculate_aspect_ratio_zero_height(self, matcher):
|
|
"""Test calculating aspect ratio with zero height."""
|
|
result = matcher.calculate_aspect_ratio(1920, 0)
|
|
assert result is None
|
|
|
|
def test_format_aspect_ratio_16_9(self, matcher):
|
|
"""Test formatting 16:9 aspect ratio."""
|
|
result = matcher.format_aspect_ratio(1.777)
|
|
assert result == '16:9'
|
|
|
|
def test_format_aspect_ratio_21_9(self, matcher):
|
|
"""Test formatting 21:9 aspect ratio."""
|
|
result = matcher.format_aspect_ratio(2.35)
|
|
assert result == '21:9'
|
|
|
|
def test_format_aspect_ratio_custom(self, matcher):
|
|
"""Test formatting custom aspect ratio."""
|
|
result = matcher.format_aspect_ratio(1.5)
|
|
assert ':1' in result
|
|
|
|
|
|
class TestUtilityIntegration:
|
|
"""Integration tests for utilities working together."""
|
|
|
|
def test_extract_all_metadata_from_filename(self):
|
|
"""Test extracting multiple types of data from a filename."""
|
|
filename = "Movie Title [2xUKR_ENG] (2024) [1080p] [BluRay] [tmdbid-12345].mkv"
|
|
|
|
# Test language extraction
|
|
lang_extractor = LanguageCodeExtractor()
|
|
langs = lang_extractor.extract_from_brackets(filename)
|
|
assert 'ukr' in langs
|
|
assert 'eng' in langs
|
|
|
|
# Test pattern extraction
|
|
pattern_extractor = PatternExtractor()
|
|
year = pattern_extractor.extract_year(filename)
|
|
assert year == '2024'
|
|
|
|
quality = pattern_extractor.extract_quality(filename)
|
|
assert quality == '1080p'
|
|
|
|
source = pattern_extractor.extract_source(filename)
|
|
assert source == 'BluRay'
|
|
|
|
db_id = pattern_extractor.extract_movie_db_ids(filename)
|
|
assert db_id['type'] == 'tmdb'
|
|
assert db_id['id'] == '12345'
|
|
|
|
def test_frame_class_with_language_codes(self):
|
|
"""Test that frame class detection works independently of language codes."""
|
|
# Create a frame matcher
|
|
matcher = FrameClassMatcher()
|
|
|
|
# These should not interfere with each other
|
|
lang_extractor = LanguageCodeExtractor()
|
|
|
|
filename = "[UKR_ENG] Movie.mkv"
|
|
langs = lang_extractor.extract_from_brackets(filename)
|
|
|
|
# Frame matching should work on dimensions
|
|
frame_class = matcher.match_by_dimensions(1920, 1080, 'p')
|
|
assert frame_class == '1080p'
|
|
assert len(langs) == 2
|