Add ČSFD Anubis bypass, drop legacy preset tags, rename Země → Země původu
This commit is contained in:
+35
-4
@@ -16,9 +16,19 @@ from src.core.csfd import (
|
||||
_extract_genres,
|
||||
_extract_origin_info,
|
||||
_check_dependencies,
|
||||
_solve_anubis_pow,
|
||||
)
|
||||
|
||||
|
||||
def _mock_session(mock_requests):
|
||||
"""Wire ``mock_requests`` so ``requests.Session()`` (also as a context
|
||||
manager) yields a single configurable session mock and return it."""
|
||||
session = MagicMock()
|
||||
session.__enter__.return_value = session
|
||||
mock_requests.Session.return_value = session
|
||||
return session
|
||||
|
||||
|
||||
# Sample HTML for testing
|
||||
SAMPLE_JSON_LD = """
|
||||
{
|
||||
@@ -219,7 +229,8 @@ class TestFetchMovie:
|
||||
mock_response = MagicMock()
|
||||
mock_response.text = SAMPLE_HTML
|
||||
mock_response.raise_for_status = MagicMock()
|
||||
mock_requests.get.return_value = mock_response
|
||||
session = _mock_session(mock_requests)
|
||||
session.get.return_value = mock_response
|
||||
|
||||
movie = fetch_movie("https://www.csfd.cz/film/123-test/")
|
||||
|
||||
@@ -227,13 +238,14 @@ class TestFetchMovie:
|
||||
assert movie.csfd_id == 123
|
||||
assert movie.rating == 86
|
||||
assert "Drama" in movie.genres
|
||||
mock_requests.get.assert_called_once()
|
||||
session.get.assert_called_once()
|
||||
|
||||
@patch("src.core.csfd.requests")
|
||||
def test_fetch_movie_network_error(self, mock_requests):
|
||||
"""Test network error handling."""
|
||||
import requests as real_requests
|
||||
mock_requests.get.side_effect = real_requests.RequestException("Network error")
|
||||
session = _mock_session(mock_requests)
|
||||
session.get.side_effect = real_requests.RequestException("Network error")
|
||||
|
||||
with pytest.raises(real_requests.RequestException):
|
||||
fetch_movie("https://www.csfd.cz/film/123/")
|
||||
@@ -254,7 +266,8 @@ class TestSearchMovies:
|
||||
mock_response = MagicMock()
|
||||
mock_response.text = search_html
|
||||
mock_response.raise_for_status = MagicMock()
|
||||
mock_requests.get.return_value = mock_response
|
||||
session = _mock_session(mock_requests)
|
||||
session.get.return_value = mock_response
|
||||
mock_requests.utils.quote = lambda x: x
|
||||
|
||||
results = search_movies("test", limit=10)
|
||||
@@ -277,6 +290,24 @@ class TestFetchMovieById:
|
||||
assert movie.title == "Test"
|
||||
|
||||
|
||||
class TestAnubisPoW:
|
||||
"""Tests for the Anubis proof-of-work solver."""
|
||||
|
||||
def test_solve_pow_difficulty_one(self):
|
||||
"""Difficulty 1 requires a single leading zero nibble in the hash."""
|
||||
import hashlib
|
||||
|
||||
random_data = "abc123"
|
||||
hash_hex, nonce, _ = _solve_anubis_pow(random_data, difficulty=1)
|
||||
assert hash_hex[0] == "0"
|
||||
assert hashlib.sha256(f"{random_data}{nonce}".encode()).hexdigest() == hash_hex
|
||||
|
||||
def test_solve_pow_difficulty_two(self):
|
||||
"""Difficulty 2 requires two leading zero nibbles (one zero byte)."""
|
||||
hash_hex, _, _ = _solve_anubis_pow("seed", difficulty=2)
|
||||
assert hash_hex[:2] == "00"
|
||||
|
||||
|
||||
class TestDependencyCheck:
|
||||
"""Tests for dependency checking."""
|
||||
|
||||
|
||||
+5
-7
@@ -40,10 +40,9 @@ class TestFile:
|
||||
assert file_obj.metadata_filename == expected
|
||||
|
||||
def test_file_initial_tags(self, test_file, tag_manager):
|
||||
"""Test že nový soubor má tag Stav/Nové"""
|
||||
"""Test že nový soubor nemá žádné automatické tagy (Stav/Nové odstraněn)"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
assert len(file_obj.tags) == 1
|
||||
assert file_obj.tags[0].full_path == "Stav/Nové"
|
||||
assert file_obj.tags == []
|
||||
|
||||
def test_file_metadata_saved(self, test_file, tag_manager):
|
||||
"""Test že metadata jsou uložena při vytvoření"""
|
||||
@@ -75,13 +74,12 @@ class TestFile:
|
||||
|
||||
# Vytvoření nového objektu - měl by načíst metadata
|
||||
file_obj2 = File(test_file, tag_manager)
|
||||
assert len(file_obj2.tags) == 2 # Stav/Nové + Video/HD
|
||||
assert len(file_obj2.tags) == 1 # Video/HD
|
||||
assert file_obj2.date == "2025-01-15"
|
||||
|
||||
# Kontrola že tagy obsahují správné hodnoty
|
||||
tag_paths = {tag.full_path for tag in file_obj2.tags}
|
||||
assert "Video/HD" in tag_paths
|
||||
assert "Stav/Nové" in tag_paths
|
||||
|
||||
def test_file_set_date(self, test_file, tag_manager):
|
||||
"""Test nastavení data"""
|
||||
@@ -115,7 +113,7 @@ class TestFile:
|
||||
file_obj.add_tag(tag)
|
||||
|
||||
assert tag in file_obj.tags
|
||||
assert len(file_obj.tags) == 2 # Stav/Nové + Video/4K
|
||||
assert len(file_obj.tags) == 1 # Video/4K
|
||||
|
||||
def test_file_add_tag_string(self, test_file, tag_manager):
|
||||
"""Test přidání tagu jako string"""
|
||||
@@ -182,7 +180,7 @@ class TestFile:
|
||||
"""Test File bez TagManager"""
|
||||
file_obj = File(test_file, tagmanager=None)
|
||||
assert file_obj.tagmanager is None
|
||||
assert len(file_obj.tags) == 0 # Bez TagManager se nepřidá Stav/Nové
|
||||
assert len(file_obj.tags) == 0 # nový soubor nemá žádné automatické tagy
|
||||
|
||||
def test_file_metadata_persistence(self, test_file, tag_manager):
|
||||
"""Test že metadata přežijí reload"""
|
||||
|
||||
@@ -42,7 +42,7 @@ class TestHardlinkManager:
|
||||
|
||||
# File 1 with multiple tags
|
||||
f1 = File(temp_source_dir / "file1.txt", tag_manager)
|
||||
f1.tags.clear() # Remove default "Stav/Nové" tag
|
||||
f1.tags.clear() # ensure a clean tag set
|
||||
f1.add_tag(Tag("žánr", "Komedie"))
|
||||
f1.add_tag(Tag("žánr", "Akční"))
|
||||
f1.add_tag(Tag("rok", "1988"))
|
||||
@@ -50,13 +50,13 @@ class TestHardlinkManager:
|
||||
|
||||
# File 2 with one tag
|
||||
f2 = File(temp_source_dir / "file2.txt", tag_manager)
|
||||
f2.tags.clear() # Remove default "Stav/Nové" tag
|
||||
f2.tags.clear() # ensure a clean tag set
|
||||
f2.add_tag(Tag("žánr", "Drama"))
|
||||
files.append(f2)
|
||||
|
||||
# File 3 with no tags
|
||||
f3 = File(temp_source_dir / "file3.txt", tag_manager)
|
||||
f3.tags.clear() # Remove default "Stav/Nové" tag
|
||||
f3.tags.clear() # ensure a clean tag set
|
||||
files.append(f3)
|
||||
|
||||
return files
|
||||
|
||||
@@ -63,7 +63,7 @@ class TestFileWithIndex:
|
||||
|
||||
assert not f.metadata_filename.exists() # no sidecar
|
||||
assert index.get(movie) is not None # record created in index
|
||||
assert f.tags[0].full_path == "Stav/Nové"
|
||||
assert f.tags == [] # no automatic tags
|
||||
|
||||
def test_index_backed_metadata_persists_across_reload(self, tmp_path):
|
||||
index = PoolIndex(tmp_path)
|
||||
|
||||
+25
-98
@@ -13,24 +13,12 @@ class TestTagManager:
|
||||
|
||||
@pytest.fixture
|
||||
def empty_tag_manager(self):
|
||||
"""Fixture pro prázdný TagManager (bez default tagů)"""
|
||||
tm = TagManager()
|
||||
# Odstranit default tagy pro testy které potřebují prázdný manager
|
||||
for category in list(tm.tags_by_category.keys()):
|
||||
tm.remove_category(category)
|
||||
return tm
|
||||
"""Fixture pro prázdný TagManager (alias k tag_manager, žádné default tagy)"""
|
||||
return TagManager()
|
||||
|
||||
def test_tag_manager_creation_has_defaults(self, tag_manager):
|
||||
"""Test vytvoření TagManager obsahuje default tagy"""
|
||||
assert "Hodnocení" in tag_manager.tags_by_category
|
||||
assert "Barva" in tag_manager.tags_by_category
|
||||
|
||||
def test_tag_manager_default_tags_count(self, tag_manager):
|
||||
"""Test počtu default tagů"""
|
||||
# Hodnocení má 5 hvězdiček
|
||||
assert len(tag_manager.tags_by_category["Hodnocení"]) == 5
|
||||
# Barva má 6 barev
|
||||
assert len(tag_manager.tags_by_category["Barva"]) == 6
|
||||
def test_tag_manager_creation_has_no_defaults(self, tag_manager):
|
||||
"""Test že nový TagManager nemá žádné předdefinované tagy"""
|
||||
assert tag_manager.tags_by_category == {}
|
||||
|
||||
def test_add_category(self, tag_manager):
|
||||
"""Test přidání kategorie"""
|
||||
@@ -141,11 +129,9 @@ class TestTagManager:
|
||||
assert "Video/4K" in tags
|
||||
assert "Audio/MP3" in tags
|
||||
|
||||
def test_get_all_tags_includes_defaults(self, tag_manager):
|
||||
"""Test že get_all_tags obsahuje default tagy"""
|
||||
tags = tag_manager.get_all_tags()
|
||||
# Minimálně 11 default tagů (5 hodnocení + 6 barev)
|
||||
assert len(tags) >= 11
|
||||
def test_get_all_tags_empty_on_fresh_manager(self, tag_manager):
|
||||
"""Test že čerstvý TagManager nemá žádné tagy (bez defaultů)"""
|
||||
assert tag_manager.get_all_tags() == []
|
||||
|
||||
def test_get_categories_empty(self, empty_tag_manager):
|
||||
"""Test získání kategorií (prázdný manager)"""
|
||||
@@ -164,11 +150,9 @@ class TestTagManager:
|
||||
assert "Audio" in categories
|
||||
assert "Foto" in categories
|
||||
|
||||
def test_get_categories_includes_defaults(self, tag_manager):
|
||||
"""Test že get_categories obsahuje default kategorie"""
|
||||
categories = tag_manager.get_categories()
|
||||
assert "Hodnocení" in categories
|
||||
assert "Barva" in categories
|
||||
def test_get_categories_empty_on_fresh_manager(self, tag_manager):
|
||||
"""Test že čerstvý TagManager nemá žádné kategorie (bez defaultů)"""
|
||||
assert tag_manager.get_categories() == []
|
||||
|
||||
def test_get_tags_in_category_empty(self, tag_manager):
|
||||
"""Test získání tagů z prázdné kategorie"""
|
||||
@@ -230,81 +214,33 @@ class TestTagManager:
|
||||
|
||||
|
||||
class TestDefaultTags:
|
||||
"""Testy pro defaultní tagy"""
|
||||
"""Testy pro defaultní tagy (legacy Tagger presety byly odstraněny)"""
|
||||
|
||||
def test_default_tags_constant_exists(self):
|
||||
"""Test že DEFAULT_TAGS konstanta existuje"""
|
||||
assert DEFAULT_TAGS is not None
|
||||
"""Test že DEFAULT_TAGS konstanta existuje a je prázdná"""
|
||||
assert isinstance(DEFAULT_TAGS, dict)
|
||||
assert DEFAULT_TAGS == {}
|
||||
|
||||
def test_default_tags_has_hodnoceni(self):
|
||||
"""Test že DEFAULT_TAGS obsahuje Hodnocení"""
|
||||
assert "Hodnocení" in DEFAULT_TAGS
|
||||
assert len(DEFAULT_TAGS["Hodnocení"]) == 5
|
||||
def test_legacy_presets_removed(self):
|
||||
"""Test že staré předdefinované kategorie (Hodnocení, Barva) jsou pryč"""
|
||||
assert "Hodnocení" not in DEFAULT_TAGS
|
||||
assert "Barva" not in DEFAULT_TAGS
|
||||
|
||||
def test_default_tags_has_barva(self):
|
||||
"""Test že DEFAULT_TAGS obsahuje Barva"""
|
||||
assert "Barva" in DEFAULT_TAGS
|
||||
assert len(DEFAULT_TAGS["Barva"]) == 6
|
||||
|
||||
def test_hodnoceni_stars_content(self):
|
||||
"""Test obsahu hvězdiček v Hodnocení"""
|
||||
stars = DEFAULT_TAGS["Hodnocení"]
|
||||
assert "⭐" in stars
|
||||
assert "⭐⭐⭐⭐⭐" in stars
|
||||
|
||||
def test_barva_colors_content(self):
|
||||
"""Test obsahu barev v Barva"""
|
||||
colors = DEFAULT_TAGS["Barva"]
|
||||
# Kontrolujeme že obsahuje některé barvy
|
||||
color_names = " ".join(colors)
|
||||
assert "Červená" in color_names
|
||||
assert "Zelená" in color_names
|
||||
assert "Modrá" in color_names
|
||||
|
||||
def test_tag_manager_loads_all_default_tags(self):
|
||||
"""Test že TagManager načte všechny default tagy"""
|
||||
def test_tag_manager_starts_empty(self):
|
||||
"""Test že TagManager bez defaultů startuje prázdný"""
|
||||
tm = TagManager()
|
||||
assert tm.get_all_tags() == []
|
||||
assert tm.get_categories() == []
|
||||
|
||||
for category, tag_names in DEFAULT_TAGS.items():
|
||||
assert category in tm.tags_by_category
|
||||
tags_in_category = tm.get_tags_in_category(category)
|
||||
assert len(tags_in_category) == len(tag_names)
|
||||
|
||||
def test_can_add_custom_tags_alongside_defaults(self):
|
||||
"""Test že lze přidat vlastní tagy vedle defaultních"""
|
||||
def test_can_add_custom_tags(self):
|
||||
"""Test že lze přidat vlastní tagy do prázdného manageru"""
|
||||
tm = TagManager()
|
||||
initial_count = len(tm.get_all_tags())
|
||||
|
||||
tm.add_tag("Custom", "MyTag")
|
||||
|
||||
assert len(tm.get_all_tags()) == initial_count + 1
|
||||
assert tm.get_all_tags() == ["Custom/MyTag"]
|
||||
assert "Custom" in tm.get_categories()
|
||||
|
||||
def test_can_remove_default_category(self):
|
||||
"""Test že lze odstranit default kategorii"""
|
||||
tm = TagManager()
|
||||
tm.remove_category("Hodnocení")
|
||||
|
||||
assert "Hodnocení" not in tm.tags_by_category
|
||||
|
||||
def test_hodnoceni_tags_are_sorted_by_stars(self):
|
||||
"""Test že tagy v Hodnocení jsou seřazeny od 1 do 5 hvězd"""
|
||||
tm = TagManager()
|
||||
tags = tm.get_tags_in_category("Hodnocení")
|
||||
|
||||
tag_names = [t.name for t in tags]
|
||||
assert tag_names == ["⭐", "⭐⭐", "⭐⭐⭐", "⭐⭐⭐⭐", "⭐⭐⭐⭐⭐"]
|
||||
|
||||
def test_barva_tags_are_sorted_in_predefined_order(self):
|
||||
"""Test že tagy v Barva jsou seřazeny v předdefinovaném pořadí"""
|
||||
tm = TagManager()
|
||||
tags = tm.get_tags_in_category("Barva")
|
||||
|
||||
tag_names = [t.name for t in tags]
|
||||
expected = ["🔴 Červená", "🟠 Oranžová", "🟡 Žlutá", "🟢 Zelená", "🔵 Modrá", "🟣 Fialová"]
|
||||
assert tag_names == expected
|
||||
|
||||
def test_custom_category_tags_sorted_alphabetically(self):
|
||||
"""Test že tagy v custom kategorii jsou seřazeny abecedně"""
|
||||
tm = TagManager()
|
||||
@@ -316,12 +252,3 @@ class TestDefaultTags:
|
||||
tag_names = [t.name for t in tags]
|
||||
|
||||
assert tag_names == ["4K", "HD", "SD"]
|
||||
|
||||
def test_can_add_tag_to_default_category(self):
|
||||
"""Test že lze přidat tag do default kategorie"""
|
||||
tm = TagManager()
|
||||
initial_count = len(tm.get_tags_in_category("Hodnocení"))
|
||||
|
||||
tm.add_tag("Hodnocení", "Custom Rating")
|
||||
|
||||
assert len(tm.get_tags_in_category("Hodnocení")) == initial_count + 1
|
||||
|
||||
Reference in New Issue
Block a user