Tests added
This commit is contained in:
1
tests/__init__.py
Normal file
1
tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Tests package
|
||||
28
tests/conftest.py
Normal file
28
tests/conftest.py
Normal file
@@ -0,0 +1,28 @@
|
||||
"""
|
||||
Konfigurace pytest - sdílené fixtures a nastavení pro všechny testy
|
||||
"""
|
||||
import pytest
|
||||
import tempfile
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def session_temp_dir():
|
||||
"""Session-wide dočasný adresář"""
|
||||
temp_dir = Path(tempfile.mkdtemp())
|
||||
yield temp_dir
|
||||
shutil.rmtree(temp_dir, ignore_errors=True)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def cleanup_config_files():
|
||||
"""Automaticky vyčistí config.json soubory po každém testu"""
|
||||
yield
|
||||
# Cleanup po testu
|
||||
config_file = Path("config.json")
|
||||
if config_file.exists():
|
||||
try:
|
||||
config_file.unlink()
|
||||
except Exception:
|
||||
pass
|
||||
252
tests/test_config.py
Normal file
252
tests/test_config.py
Normal file
@@ -0,0 +1,252 @@
|
||||
import pytest
|
||||
import json
|
||||
from pathlib import Path
|
||||
from src.core.config import load_config, save_config, default_config
|
||||
|
||||
|
||||
class TestConfig:
|
||||
"""Testy pro config modul"""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_config_file(self, tmp_path, monkeypatch):
|
||||
"""Fixture pro dočasný config soubor"""
|
||||
config_path = tmp_path / "test_config.json"
|
||||
# Změníme CONFIG_FILE v modulu config
|
||||
import src.core.config as config_module
|
||||
monkeypatch.setattr(config_module, 'CONFIG_FILE', config_path)
|
||||
return config_path
|
||||
|
||||
def test_default_config_structure(self):
|
||||
"""Test struktury defaultní konfigurace"""
|
||||
assert "ignore_patterns" in default_config
|
||||
assert "last_folder" in default_config
|
||||
assert isinstance(default_config["ignore_patterns"], list)
|
||||
assert default_config["last_folder"] is None
|
||||
|
||||
def test_load_config_nonexistent_file(self, temp_config_file):
|
||||
"""Test načtení konfigurace když soubor neexistuje"""
|
||||
config = load_config()
|
||||
|
||||
assert config == default_config
|
||||
assert config["ignore_patterns"] == []
|
||||
assert config["last_folder"] is None
|
||||
|
||||
def test_save_config(self, temp_config_file):
|
||||
"""Test uložení konfigurace"""
|
||||
test_config = {
|
||||
"ignore_patterns": ["*.tmp", "*.log"],
|
||||
"last_folder": "/home/user/documents"
|
||||
}
|
||||
|
||||
save_config(test_config)
|
||||
|
||||
# Kontrola že soubor existuje
|
||||
assert temp_config_file.exists()
|
||||
|
||||
# Kontrola obsahu
|
||||
with open(temp_config_file, "r", encoding="utf-8") as f:
|
||||
saved_data = json.load(f)
|
||||
|
||||
assert saved_data == test_config
|
||||
|
||||
def test_load_config_existing_file(self, temp_config_file):
|
||||
"""Test načtení existující konfigurace"""
|
||||
test_config = {
|
||||
"ignore_patterns": ["*.tmp"],
|
||||
"last_folder": "/test/path"
|
||||
}
|
||||
|
||||
# Uložení
|
||||
save_config(test_config)
|
||||
|
||||
# Načtení
|
||||
loaded_config = load_config()
|
||||
|
||||
assert loaded_config == test_config
|
||||
assert loaded_config["ignore_patterns"] == ["*.tmp"]
|
||||
assert loaded_config["last_folder"] == "/test/path"
|
||||
|
||||
def test_save_and_load_config_cycle(self, temp_config_file):
|
||||
"""Test cyklu uložení a načtení"""
|
||||
original_config = {
|
||||
"ignore_patterns": ["*.jpg", "*.png", "*.gif"],
|
||||
"last_folder": "/home/user/pictures"
|
||||
}
|
||||
|
||||
save_config(original_config)
|
||||
loaded_config = load_config()
|
||||
|
||||
assert loaded_config == original_config
|
||||
|
||||
def test_config_json_format(self, temp_config_file):
|
||||
"""Test že config je uložen ve správném JSON formátu"""
|
||||
test_config = {
|
||||
"ignore_patterns": ["*.tmp"],
|
||||
"last_folder": "/test"
|
||||
}
|
||||
|
||||
save_config(test_config)
|
||||
|
||||
# Kontrola formátování
|
||||
with open(temp_config_file, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
# Mělo by být naformátováno s indentací
|
||||
assert " " in content # 2 mezery jako indent
|
||||
|
||||
def test_config_utf8_encoding(self, temp_config_file):
|
||||
"""Test UTF-8 encoding s českými znaky"""
|
||||
test_config = {
|
||||
"ignore_patterns": ["*.čeština"],
|
||||
"last_folder": "/cesta/s/čestnými/znaky"
|
||||
}
|
||||
|
||||
save_config(test_config)
|
||||
loaded_config = load_config()
|
||||
|
||||
assert loaded_config == test_config
|
||||
assert loaded_config["last_folder"] == "/cesta/s/čestnými/znaky"
|
||||
|
||||
def test_config_empty_ignore_patterns(self, temp_config_file):
|
||||
"""Test s prázdným seznamem ignore_patterns"""
|
||||
test_config = {
|
||||
"ignore_patterns": [],
|
||||
"last_folder": "/test"
|
||||
}
|
||||
|
||||
save_config(test_config)
|
||||
loaded_config = load_config()
|
||||
|
||||
assert loaded_config["ignore_patterns"] == []
|
||||
|
||||
def test_config_null_last_folder(self, temp_config_file):
|
||||
"""Test s None hodnotou pro last_folder"""
|
||||
test_config = {
|
||||
"ignore_patterns": ["*.tmp"],
|
||||
"last_folder": None
|
||||
}
|
||||
|
||||
save_config(test_config)
|
||||
loaded_config = load_config()
|
||||
|
||||
assert loaded_config["last_folder"] is None
|
||||
|
||||
def test_config_multiple_ignore_patterns(self, temp_config_file):
|
||||
"""Test s více ignore patterny"""
|
||||
patterns = ["*.tmp", "*.log", "*.cache", "*/node_modules/*", "*.pyc"]
|
||||
test_config = {
|
||||
"ignore_patterns": patterns,
|
||||
"last_folder": "/test"
|
||||
}
|
||||
|
||||
save_config(test_config)
|
||||
loaded_config = load_config()
|
||||
|
||||
assert loaded_config["ignore_patterns"] == patterns
|
||||
assert len(loaded_config["ignore_patterns"]) == 5
|
||||
|
||||
def test_config_special_characters_in_patterns(self, temp_config_file):
|
||||
"""Test se speciálními znaky v patterns"""
|
||||
test_config = {
|
||||
"ignore_patterns": ["*.tmp", "file[0-9].txt", "test?.log"],
|
||||
"last_folder": "/test"
|
||||
}
|
||||
|
||||
save_config(test_config)
|
||||
loaded_config = load_config()
|
||||
|
||||
assert loaded_config["ignore_patterns"] == test_config["ignore_patterns"]
|
||||
|
||||
def test_load_config_corrupted_file(self, temp_config_file):
|
||||
"""Test načtení poškozeného config souboru"""
|
||||
# Vytvoření poškozeného JSON
|
||||
with open(temp_config_file, "w") as f:
|
||||
f.write("{ invalid json }")
|
||||
|
||||
# Mělo by vrátit default config
|
||||
config = load_config()
|
||||
assert config == default_config
|
||||
|
||||
def test_load_config_returns_new_dict(self, temp_config_file):
|
||||
"""Test že load_config vrací nový dictionary (ne stejnou referenci)"""
|
||||
config1 = load_config()
|
||||
config2 = load_config()
|
||||
|
||||
# Měly by to být různé objekty (ne stejná reference)
|
||||
assert config1 is not config2
|
||||
|
||||
# Ale hodnoty by měly být stejné
|
||||
assert config1 == config2
|
||||
|
||||
def test_config_overwrite(self, temp_config_file):
|
||||
"""Test přepsání existující konfigurace"""
|
||||
config1 = {
|
||||
"ignore_patterns": ["*.tmp"],
|
||||
"last_folder": "/path1"
|
||||
}
|
||||
|
||||
config2 = {
|
||||
"ignore_patterns": ["*.log"],
|
||||
"last_folder": "/path2"
|
||||
}
|
||||
|
||||
save_config(config1)
|
||||
save_config(config2)
|
||||
|
||||
loaded = load_config()
|
||||
assert loaded == config2
|
||||
|
||||
def test_config_path_with_spaces(self, temp_config_file):
|
||||
"""Test s cestou obsahující mezery"""
|
||||
test_config = {
|
||||
"ignore_patterns": [],
|
||||
"last_folder": "/path/with spaces/in name"
|
||||
}
|
||||
|
||||
save_config(test_config)
|
||||
loaded_config = load_config()
|
||||
|
||||
assert loaded_config["last_folder"] == "/path/with spaces/in name"
|
||||
|
||||
def test_config_long_path(self, temp_config_file):
|
||||
"""Test s dlouhou cestou"""
|
||||
long_path = "/very/long/path/" + "subdir/" * 50 + "final"
|
||||
test_config = {
|
||||
"ignore_patterns": [],
|
||||
"last_folder": long_path
|
||||
}
|
||||
|
||||
save_config(test_config)
|
||||
loaded_config = load_config()
|
||||
|
||||
assert loaded_config["last_folder"] == long_path
|
||||
|
||||
def test_config_many_patterns(self, temp_config_file):
|
||||
"""Test s velkým počtem patterns"""
|
||||
patterns = [f"*.ext{i}" for i in range(100)]
|
||||
test_config = {
|
||||
"ignore_patterns": patterns,
|
||||
"last_folder": "/test"
|
||||
}
|
||||
|
||||
save_config(test_config)
|
||||
loaded_config = load_config()
|
||||
|
||||
assert len(loaded_config["ignore_patterns"]) == 100
|
||||
assert loaded_config["ignore_patterns"] == patterns
|
||||
|
||||
def test_config_ensure_ascii_false(self, temp_config_file):
|
||||
"""Test že ensure_ascii=False funguje správně"""
|
||||
test_config = {
|
||||
"ignore_patterns": ["čeština", "русский", "中文"],
|
||||
"last_folder": "/cesta/čeština"
|
||||
}
|
||||
|
||||
save_config(test_config)
|
||||
|
||||
# Kontrola že znaky nejsou escapovány
|
||||
with open(temp_config_file, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
assert "čeština" in content
|
||||
assert "\\u" not in content # Nemělo by být escapováno
|
||||
265
tests/test_file.py
Normal file
265
tests/test_file.py
Normal file
@@ -0,0 +1,265 @@
|
||||
import pytest
|
||||
import json
|
||||
from pathlib import Path
|
||||
from src.core.file import File
|
||||
from src.core.tag import Tag
|
||||
from src.core.tag_manager import TagManager
|
||||
|
||||
|
||||
class TestFile:
|
||||
"""Testy pro třídu File"""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_dir(self, tmp_path):
|
||||
"""Fixture pro dočasný adresář"""
|
||||
return tmp_path
|
||||
|
||||
@pytest.fixture
|
||||
def tag_manager(self):
|
||||
"""Fixture pro TagManager"""
|
||||
return TagManager()
|
||||
|
||||
@pytest.fixture
|
||||
def test_file(self, temp_dir):
|
||||
"""Fixture pro testovací soubor"""
|
||||
test_file = temp_dir / "test.txt"
|
||||
test_file.write_text("test content")
|
||||
return test_file
|
||||
|
||||
def test_file_creation(self, test_file, tag_manager):
|
||||
"""Test vytvoření File objektu"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
assert file_obj.file_path == test_file
|
||||
assert file_obj.filename == "test.txt"
|
||||
assert file_obj.new == True
|
||||
|
||||
def test_file_metadata_filename(self, test_file, tag_manager):
|
||||
"""Test názvu metadata souboru"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
expected = test_file.parent / ".test.txt.!tag"
|
||||
assert file_obj.metadata_filename == expected
|
||||
|
||||
def test_file_initial_tags(self, test_file, tag_manager):
|
||||
"""Test že nový soubor má tag Stav/Nové"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
assert len(file_obj.tags) == 1
|
||||
assert file_obj.tags[0].full_path == "Stav/Nové"
|
||||
|
||||
def test_file_metadata_saved(self, test_file, tag_manager):
|
||||
"""Test že metadata jsou uložena při vytvoření"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
assert file_obj.metadata_filename.exists()
|
||||
|
||||
def test_file_save_metadata(self, test_file, tag_manager):
|
||||
"""Test uložení metadat"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
file_obj.new = False
|
||||
file_obj.ignored = True
|
||||
file_obj.save_metadata()
|
||||
|
||||
# Načtení a kontrola
|
||||
with open(file_obj.metadata_filename, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
assert data["new"] == False
|
||||
assert data["ignored"] == True
|
||||
|
||||
def test_file_load_metadata(self, test_file, tag_manager):
|
||||
"""Test načtení metadat"""
|
||||
# Vytvoření a uložení metadat
|
||||
file_obj = File(test_file, tag_manager)
|
||||
tag = tag_manager.add_tag("Video", "HD")
|
||||
file_obj.tags.append(tag)
|
||||
file_obj.date = "2025-01-15"
|
||||
file_obj.save_metadata()
|
||||
|
||||
# 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 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"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
file_obj.set_date("2025-12-25")
|
||||
assert file_obj.date == "2025-12-25"
|
||||
|
||||
# Kontrola že bylo uloženo
|
||||
with open(file_obj.metadata_filename, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
assert data["date"] == "2025-12-25"
|
||||
|
||||
def test_file_set_date_to_none(self, test_file, tag_manager):
|
||||
"""Test smazání data"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
file_obj.set_date("2025-12-25")
|
||||
file_obj.set_date(None)
|
||||
assert file_obj.date is None
|
||||
|
||||
def test_file_set_date_empty_string(self, test_file, tag_manager):
|
||||
"""Test nastavení prázdného řetězce jako datum"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
file_obj.set_date("2025-12-25")
|
||||
file_obj.set_date("")
|
||||
assert file_obj.date is None
|
||||
|
||||
def test_file_add_tag_object(self, test_file, tag_manager):
|
||||
"""Test přidání Tag objektu"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
tag = Tag("Video", "4K")
|
||||
file_obj.add_tag(tag)
|
||||
|
||||
assert tag in file_obj.tags
|
||||
assert len(file_obj.tags) == 2 # Stav/Nové + Video/4K
|
||||
|
||||
def test_file_add_tag_string(self, test_file, tag_manager):
|
||||
"""Test přidání tagu jako string"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
file_obj.add_tag("Audio/MP3")
|
||||
|
||||
tag_paths = {tag.full_path for tag in file_obj.tags}
|
||||
assert "Audio/MP3" in tag_paths
|
||||
|
||||
def test_file_add_tag_string_without_category(self, test_file, tag_manager):
|
||||
"""Test přidání tagu bez kategorie (použije 'default')"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
file_obj.add_tag("SimpleTag")
|
||||
|
||||
tag_paths = {tag.full_path for tag in file_obj.tags}
|
||||
assert "default/SimpleTag" in tag_paths
|
||||
|
||||
def test_file_add_duplicate_tag(self, test_file, tag_manager):
|
||||
"""Test že duplicitní tag není přidán"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
tag = Tag("Video", "HD")
|
||||
file_obj.add_tag(tag)
|
||||
file_obj.add_tag(tag)
|
||||
|
||||
# Spočítáme kolikrát se tag vyskytuje
|
||||
count = sum(1 for t in file_obj.tags if t == tag)
|
||||
assert count == 1
|
||||
|
||||
def test_file_remove_tag_object(self, test_file, tag_manager):
|
||||
"""Test odstranění Tag objektu"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
tag = Tag("Video", "HD")
|
||||
file_obj.add_tag(tag)
|
||||
file_obj.remove_tag(tag)
|
||||
|
||||
assert tag not in file_obj.tags
|
||||
|
||||
def test_file_remove_tag_string(self, test_file, tag_manager):
|
||||
"""Test odstranění tagu jako string"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
file_obj.add_tag("Video/HD")
|
||||
file_obj.remove_tag("Video/HD")
|
||||
|
||||
tag_paths = {tag.full_path for tag in file_obj.tags}
|
||||
assert "Video/HD" not in tag_paths
|
||||
|
||||
def test_file_remove_tag_string_without_category(self, test_file, tag_manager):
|
||||
"""Test odstranění tagu bez kategorie"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
file_obj.add_tag("SimpleTag")
|
||||
file_obj.remove_tag("SimpleTag")
|
||||
|
||||
tag_paths = {tag.full_path for tag in file_obj.tags}
|
||||
assert "default/SimpleTag" not in tag_paths
|
||||
|
||||
def test_file_remove_nonexistent_tag(self, test_file, tag_manager):
|
||||
"""Test odstranění neexistujícího tagu (nemělo by vyhodit výjimku)"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
initial_count = len(file_obj.tags)
|
||||
file_obj.remove_tag("Nonexistent/Tag")
|
||||
assert len(file_obj.tags) == initial_count
|
||||
|
||||
def test_file_without_tagmanager(self, test_file):
|
||||
"""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é
|
||||
|
||||
def test_file_metadata_persistence(self, test_file, tag_manager):
|
||||
"""Test že metadata přežijí reload"""
|
||||
# Vytvoření a úprava souboru
|
||||
file_obj1 = File(test_file, tag_manager)
|
||||
file_obj1.add_tag("Video/HD")
|
||||
file_obj1.add_tag("Audio/Stereo")
|
||||
file_obj1.set_date("2025-01-01")
|
||||
file_obj1.new = False
|
||||
file_obj1.ignored = True
|
||||
file_obj1.save_metadata()
|
||||
|
||||
# Načtení nového objektu
|
||||
file_obj2 = File(test_file, tag_manager)
|
||||
|
||||
# Kontrola
|
||||
assert file_obj2.new == False
|
||||
assert file_obj2.ignored == True
|
||||
assert file_obj2.date == "2025-01-01"
|
||||
|
||||
tag_paths = {tag.full_path for tag in file_obj2.tags}
|
||||
assert "Video/HD" in tag_paths
|
||||
assert "Audio/Stereo" in tag_paths
|
||||
|
||||
def test_file_metadata_json_format(self, test_file, tag_manager):
|
||||
"""Test formátu JSON metadat"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
file_obj.add_tag("Test/Tag")
|
||||
file_obj.set_date("2025-06-15")
|
||||
|
||||
# Kontrola obsahu JSON
|
||||
with open(file_obj.metadata_filename, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
assert "new" in data
|
||||
assert "ignored" in data
|
||||
assert "tags" in data
|
||||
assert "date" in data
|
||||
assert isinstance(data["tags"], list)
|
||||
|
||||
def test_file_unicode_handling(self, temp_dir, tag_manager):
|
||||
"""Test správného zacházení s unicode znaky"""
|
||||
test_file = temp_dir / "český_soubor.txt"
|
||||
test_file.write_text("obsah")
|
||||
|
||||
file_obj = File(test_file, tag_manager)
|
||||
file_obj.add_tag("Kategorie/Český tag")
|
||||
file_obj.save_metadata()
|
||||
|
||||
# Reload a kontrola
|
||||
file_obj2 = File(test_file, tag_manager)
|
||||
tag_paths = {tag.full_path for tag in file_obj2.tags}
|
||||
assert "Kategorie/Český tag" in tag_paths
|
||||
|
||||
def test_file_complex_scenario(self, test_file, tag_manager):
|
||||
"""Test komplexního scénáře použití"""
|
||||
file_obj = File(test_file, tag_manager)
|
||||
|
||||
# Přidání více tagů
|
||||
file_obj.add_tag("Video/HD")
|
||||
file_obj.add_tag("Video/Stereo")
|
||||
file_obj.add_tag("Stav/Zkontrolováno")
|
||||
file_obj.set_date("2025-01-01")
|
||||
|
||||
# Odstranění tagu
|
||||
file_obj.remove_tag("Stav/Nové")
|
||||
|
||||
# Kontrola stavu
|
||||
tag_paths = {tag.full_path for tag in file_obj.tags}
|
||||
assert "Video/HD" in tag_paths
|
||||
assert "Video/Stereo" in tag_paths
|
||||
assert "Stav/Zkontrolováno" in tag_paths
|
||||
assert "Stav/Nové" not in tag_paths
|
||||
assert file_obj.date == "2025-01-01"
|
||||
|
||||
# Reload a kontrola persistence
|
||||
file_obj2 = File(test_file, tag_manager)
|
||||
tag_paths2 = {tag.full_path for tag in file_obj2.tags}
|
||||
assert tag_paths == tag_paths2
|
||||
assert file_obj2.date == "2025-01-01"
|
||||
283
tests/test_file_manager.py
Normal file
283
tests/test_file_manager.py
Normal file
@@ -0,0 +1,283 @@
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from src.core.file_manager import FileManager
|
||||
from src.core.tag_manager import TagManager
|
||||
from src.core.file import File
|
||||
from src.core.tag import Tag
|
||||
|
||||
|
||||
class TestFileManager:
|
||||
"""Testy pro třídu FileManager"""
|
||||
|
||||
@pytest.fixture
|
||||
def tag_manager(self):
|
||||
"""Fixture pro TagManager"""
|
||||
return TagManager()
|
||||
|
||||
@pytest.fixture
|
||||
def file_manager(self, tag_manager):
|
||||
"""Fixture pro FileManager"""
|
||||
return FileManager(tag_manager)
|
||||
|
||||
@pytest.fixture
|
||||
def temp_dir(self, tmp_path):
|
||||
"""Fixture pro dočasný adresář s testovacími soubory"""
|
||||
# Vytvoření struktury souborů
|
||||
(tmp_path / "file1.txt").write_text("content1")
|
||||
(tmp_path / "file2.txt").write_text("content2")
|
||||
(tmp_path / "file3.jpg").write_text("image")
|
||||
|
||||
# Podsložka
|
||||
subdir = tmp_path / "subdir"
|
||||
subdir.mkdir()
|
||||
(subdir / "file4.txt").write_text("content4")
|
||||
|
||||
return tmp_path
|
||||
|
||||
@pytest.fixture
|
||||
def temp_config_file(self, tmp_path, monkeypatch):
|
||||
"""Fixture pro dočasný config soubor"""
|
||||
config_path = tmp_path / "test_config.json"
|
||||
# Změníme CONFIG_FILE v modulu config
|
||||
import src.core.config as config_module
|
||||
monkeypatch.setattr(config_module, 'CONFIG_FILE', config_path)
|
||||
return config_path
|
||||
|
||||
def test_file_manager_creation(self, file_manager, tag_manager):
|
||||
"""Test vytvoření FileManager"""
|
||||
assert file_manager.filelist == []
|
||||
assert file_manager.folders == []
|
||||
assert file_manager.tagmanager == tag_manager
|
||||
|
||||
def test_file_manager_append_folder(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test přidání složky"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
assert temp_dir in file_manager.folders
|
||||
assert len(file_manager.filelist) > 0
|
||||
|
||||
def test_file_manager_append_folder_finds_all_files(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test že append najde všechny soubory včetně podsložek"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
# Měli bychom najít file1.txt, file2.txt, file3.jpg, subdir/file4.txt
|
||||
# (ne .!tag soubory)
|
||||
filenames = {f.filename for f in file_manager.filelist}
|
||||
assert "file1.txt" in filenames
|
||||
assert "file2.txt" in filenames
|
||||
assert "file3.jpg" in filenames
|
||||
assert "file4.txt" in filenames
|
||||
|
||||
def test_file_manager_ignores_tag_files(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test že .!tag soubory jsou ignorovány"""
|
||||
# Vytvoření .!tag souboru
|
||||
(temp_dir / ".file1.txt.!tag").write_text('{"tags": []}')
|
||||
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
filenames = {f.filename for f in file_manager.filelist}
|
||||
assert ".file1.txt.!tag" not in filenames
|
||||
|
||||
def test_file_manager_ignore_patterns(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test ignorování souborů podle patternů"""
|
||||
file_manager.config["ignore_patterns"] = ["*.jpg"]
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
filenames = {f.filename for f in file_manager.filelist}
|
||||
assert "file3.jpg" not in filenames
|
||||
assert "file1.txt" in filenames
|
||||
|
||||
def test_file_manager_ignore_patterns_path(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test ignorování podle celé cesty"""
|
||||
file_manager.config["ignore_patterns"] = ["*/subdir/*"]
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
filenames = {f.filename for f in file_manager.filelist}
|
||||
assert "file4.txt" not in filenames
|
||||
assert "file1.txt" in filenames
|
||||
|
||||
def test_file_manager_assign_tag_to_file_objects(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test přiřazení tagu k souborům"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
# Vybereme první dva soubory
|
||||
files = file_manager.filelist[:2]
|
||||
tag = Tag("Video", "HD")
|
||||
|
||||
file_manager.assign_tag_to_file_objects(files, tag)
|
||||
|
||||
for f in files:
|
||||
assert tag in f.tags
|
||||
|
||||
def test_file_manager_assign_tag_string(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test přiřazení tagu jako string"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
files = file_manager.filelist[:1]
|
||||
file_manager.assign_tag_to_file_objects(files, "Video/4K")
|
||||
|
||||
tag_paths = {tag.full_path for tag in files[0].tags}
|
||||
assert "Video/4K" in tag_paths
|
||||
|
||||
def test_file_manager_assign_tag_without_category(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test přiřazení tagu bez kategorie"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
files = file_manager.filelist[:1]
|
||||
file_manager.assign_tag_to_file_objects(files, "SimpleTag")
|
||||
|
||||
tag_paths = {tag.full_path for tag in files[0].tags}
|
||||
assert "default/SimpleTag" in tag_paths
|
||||
|
||||
def test_file_manager_remove_tag_from_file_objects(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test odstranění tagu ze souborů"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
files = file_manager.filelist[:2]
|
||||
tag = Tag("Video", "HD")
|
||||
|
||||
# Přidání a pak odstranění
|
||||
file_manager.assign_tag_to_file_objects(files, tag)
|
||||
file_manager.remove_tag_from_file_objects(files, tag)
|
||||
|
||||
for f in files:
|
||||
assert tag not in f.tags
|
||||
|
||||
def test_file_manager_remove_tag_string(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test odstranění tagu jako string"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
files = file_manager.filelist[:1]
|
||||
file_manager.assign_tag_to_file_objects(files, "Video/HD")
|
||||
file_manager.remove_tag_from_file_objects(files, "Video/HD")
|
||||
|
||||
tag_paths = {tag.full_path for tag in files[0].tags}
|
||||
assert "Video/HD" not in tag_paths
|
||||
|
||||
def test_file_manager_filter_files_by_tags_empty(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test filtrace bez tagů vrací všechny soubory"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
filtered = file_manager.filter_files_by_tags([])
|
||||
assert len(filtered) == len(file_manager.filelist)
|
||||
|
||||
def test_file_manager_filter_files_by_tags_none(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test filtrace s None vrací všechny soubory"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
filtered = file_manager.filter_files_by_tags(None)
|
||||
assert len(filtered) == len(file_manager.filelist)
|
||||
|
||||
def test_file_manager_filter_files_by_single_tag(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test filtrace podle jednoho tagu"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
# Přiřadíme tag některým souborům
|
||||
tag = Tag("Video", "HD")
|
||||
files_to_tag = file_manager.filelist[:2]
|
||||
file_manager.assign_tag_to_file_objects(files_to_tag, tag)
|
||||
|
||||
# Filtrujeme
|
||||
filtered = file_manager.filter_files_by_tags([tag])
|
||||
assert len(filtered) == 2
|
||||
for f in filtered:
|
||||
assert tag in f.tags
|
||||
|
||||
def test_file_manager_filter_files_by_multiple_tags(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test filtrace podle více tagů (AND logika)"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
tag1 = Tag("Video", "HD")
|
||||
tag2 = Tag("Audio", "Stereo")
|
||||
|
||||
# První soubor má oba tagy
|
||||
file_manager.assign_tag_to_file_objects([file_manager.filelist[0]], tag1)
|
||||
file_manager.assign_tag_to_file_objects([file_manager.filelist[0]], tag2)
|
||||
|
||||
# Druhý soubor má jen první tag
|
||||
file_manager.assign_tag_to_file_objects([file_manager.filelist[1]], tag1)
|
||||
|
||||
# Filtrujeme podle obou tagů
|
||||
filtered = file_manager.filter_files_by_tags([tag1, tag2])
|
||||
assert len(filtered) == 1
|
||||
assert filtered[0] == file_manager.filelist[0]
|
||||
|
||||
def test_file_manager_filter_files_by_tag_strings(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test filtrace podle tagů jako stringy"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
file_manager.assign_tag_to_file_objects([file_manager.filelist[0]], "Video/HD")
|
||||
|
||||
filtered = file_manager.filter_files_by_tags(["Video/HD"])
|
||||
assert len(filtered) == 1
|
||||
|
||||
def test_file_manager_on_files_changed_callback(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test callback při změně souborů"""
|
||||
callback_called = []
|
||||
|
||||
def callback(filelist):
|
||||
callback_called.append(filelist)
|
||||
|
||||
file_manager.on_files_changed = callback
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
# Přiřazení tagu by mělo zavolat callback
|
||||
tag = Tag("Video", "HD")
|
||||
file_manager.assign_tag_to_file_objects([file_manager.filelist[0]], tag)
|
||||
|
||||
assert len(callback_called) == 1
|
||||
|
||||
def test_file_manager_complex_scenario(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test komplexního scénáře"""
|
||||
# Přidání složky
|
||||
file_manager.append(temp_dir)
|
||||
initial_count = len(file_manager.filelist)
|
||||
assert initial_count > 0
|
||||
|
||||
# Přiřazení různých tagů různým souborům
|
||||
tag_hd = Tag("Video", "HD")
|
||||
tag_4k = Tag("Video", "4K")
|
||||
tag_stereo = Tag("Audio", "Stereo")
|
||||
|
||||
file_manager.assign_tag_to_file_objects([file_manager.filelist[0]], tag_hd)
|
||||
file_manager.assign_tag_to_file_objects([file_manager.filelist[0]], tag_stereo)
|
||||
file_manager.assign_tag_to_file_objects([file_manager.filelist[1]], tag_4k)
|
||||
|
||||
# Filtrace podle HD
|
||||
filtered_hd = file_manager.filter_files_by_tags([tag_hd])
|
||||
assert len(filtered_hd) == 1
|
||||
|
||||
# Filtrace podle HD + Stereo
|
||||
filtered_both = file_manager.filter_files_by_tags([tag_hd, tag_stereo])
|
||||
assert len(filtered_both) == 1
|
||||
|
||||
# Filtrace podle 4K
|
||||
filtered_4k = file_manager.filter_files_by_tags([tag_4k])
|
||||
assert len(filtered_4k) == 1
|
||||
|
||||
def test_file_manager_config_last_folder(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test uložení poslední složky do konfigurace"""
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
assert file_manager.config["last_folder"] == str(temp_dir)
|
||||
|
||||
def test_file_manager_empty_filelist(self, file_manager):
|
||||
"""Test práce s prázdným filelistem"""
|
||||
# Test filtrace na prázdném seznamu
|
||||
filtered = file_manager.filter_files_by_tags([Tag("Video", "HD")])
|
||||
assert filtered == []
|
||||
|
||||
# Test přiřazení tagů na prázdný seznam
|
||||
file_manager.assign_tag_to_file_objects([], Tag("Video", "HD"))
|
||||
assert len(file_manager.filelist) == 0
|
||||
|
||||
def test_file_manager_multiple_ignore_patterns(self, file_manager, temp_dir, temp_config_file):
|
||||
"""Test více ignore patternů najednou"""
|
||||
file_manager.config["ignore_patterns"] = ["*.jpg", "*.png", "*/subdir/*"]
|
||||
file_manager.append(temp_dir)
|
||||
|
||||
filenames = {f.filename for f in file_manager.filelist}
|
||||
assert "file3.jpg" not in filenames
|
||||
assert "file4.txt" not in filenames
|
||||
assert "file1.txt" in filenames
|
||||
assert "file2.txt" in filenames
|
||||
@@ -1,40 +0,0 @@
|
||||
import sys, os
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
|
||||
# přidáme src do sys.path (pokud nespouštíš pytest s -m nebo PYTHONPATH=src)
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src")))
|
||||
|
||||
from core.image import load_icon
|
||||
from PIL import Image, ImageTk
|
||||
import tkinter as tk
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def tk_root():
|
||||
"""Fixture pro inicializaci Tkinteru (nutné pro ImageTk)."""
|
||||
root = tk.Tk()
|
||||
yield root
|
||||
root.destroy()
|
||||
|
||||
|
||||
def test_load_icon_returns_photoimage(tk_root):
|
||||
# vytvoříme dočasný obrázek
|
||||
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
|
||||
tmp_path = Path(tmp.name)
|
||||
try:
|
||||
# vytvoříme 100x100 červený obrázek
|
||||
img = Image.new("RGB", (100, 100), color="red")
|
||||
img.save(tmp_path)
|
||||
|
||||
icon = load_icon(tmp_path)
|
||||
|
||||
# musí být PhotoImage
|
||||
assert isinstance(icon, ImageTk.PhotoImage)
|
||||
|
||||
# ověříme velikost 16x16
|
||||
assert icon.width() == 16
|
||||
assert icon.height() == 16
|
||||
finally:
|
||||
tmp_path.unlink(missing_ok=True)
|
||||
75
tests/test_media_utils.py
Normal file
75
tests/test_media_utils.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
|
||||
from src.core.media_utils import load_icon
|
||||
from PIL import Image, ImageTk
|
||||
import tkinter as tk
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def tk_root():
|
||||
"""Fixture pro inicializaci Tkinteru (nutné pro ImageTk)."""
|
||||
root = tk.Tk()
|
||||
yield root
|
||||
root.destroy()
|
||||
|
||||
|
||||
def test_load_icon_returns_photoimage(tk_root):
|
||||
"""Test že load_icon vrací PhotoImage"""
|
||||
# vytvoříme dočasný obrázek
|
||||
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
|
||||
tmp_path = Path(tmp.name)
|
||||
try:
|
||||
# vytvoříme 100x100 červený obrázek
|
||||
img = Image.new("RGB", (100, 100), color="red")
|
||||
img.save(tmp_path)
|
||||
|
||||
icon = load_icon(tmp_path)
|
||||
|
||||
# musí být PhotoImage
|
||||
assert isinstance(icon, ImageTk.PhotoImage)
|
||||
|
||||
# ověříme velikost 16x16
|
||||
assert icon.width() == 16
|
||||
assert icon.height() == 16
|
||||
finally:
|
||||
tmp_path.unlink(missing_ok=True)
|
||||
|
||||
|
||||
def test_load_icon_resizes_image(tk_root):
|
||||
"""Test že load_icon správně změní velikost obrázku"""
|
||||
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
|
||||
tmp_path = Path(tmp.name)
|
||||
try:
|
||||
# vytvoříme velký obrázek 500x500
|
||||
img = Image.new("RGB", (500, 500), color="blue")
|
||||
img.save(tmp_path)
|
||||
|
||||
icon = load_icon(tmp_path)
|
||||
|
||||
# i velký obrázek by měl být zmenšen na 16x16
|
||||
assert icon.width() == 16
|
||||
assert icon.height() == 16
|
||||
finally:
|
||||
tmp_path.unlink(missing_ok=True)
|
||||
|
||||
|
||||
def test_load_icon_different_formats(tk_root):
|
||||
"""Test načítání různých formátů obrázků"""
|
||||
formats = [".png", ".jpg", ".bmp"]
|
||||
|
||||
for fmt in formats:
|
||||
with tempfile.NamedTemporaryFile(suffix=fmt, delete=False) as tmp:
|
||||
tmp_path = Path(tmp.name)
|
||||
try:
|
||||
img = Image.new("RGB", (32, 32), color="green")
|
||||
img.save(tmp_path)
|
||||
|
||||
icon = load_icon(tmp_path)
|
||||
|
||||
assert isinstance(icon, ImageTk.PhotoImage)
|
||||
assert icon.width() == 16
|
||||
assert icon.height() == 16
|
||||
finally:
|
||||
tmp_path.unlink(missing_ok=True)
|
||||
106
tests/test_tag.py
Normal file
106
tests/test_tag.py
Normal file
@@ -0,0 +1,106 @@
|
||||
import pytest
|
||||
from src.core.tag import Tag
|
||||
|
||||
|
||||
class TestTag:
|
||||
"""Testy pro třídu Tag"""
|
||||
|
||||
def test_tag_creation(self):
|
||||
"""Test vytvoření tagu"""
|
||||
tag = Tag("Kategorie", "Název")
|
||||
assert tag.category == "Kategorie"
|
||||
assert tag.name == "Název"
|
||||
|
||||
def test_tag_full_path(self):
|
||||
"""Test full_path property"""
|
||||
tag = Tag("Video", "HD")
|
||||
assert tag.full_path == "Video/HD"
|
||||
|
||||
def test_tag_str_representation(self):
|
||||
"""Test string reprezentace"""
|
||||
tag = Tag("Foto", "Dovolená")
|
||||
assert str(tag) == "Foto/Dovolená"
|
||||
|
||||
def test_tag_repr(self):
|
||||
"""Test repr reprezentace"""
|
||||
tag = Tag("Audio", "Hudba")
|
||||
assert repr(tag) == "Tag(Audio/Hudba)"
|
||||
|
||||
def test_tag_equality_same_tags(self):
|
||||
"""Test rovnosti stejných tagů"""
|
||||
tag1 = Tag("Kategorie", "Název")
|
||||
tag2 = Tag("Kategorie", "Název")
|
||||
assert tag1 == tag2
|
||||
|
||||
def test_tag_equality_different_tags(self):
|
||||
"""Test nerovnosti různých tagů"""
|
||||
tag1 = Tag("Kategorie1", "Název")
|
||||
tag2 = Tag("Kategorie2", "Název")
|
||||
assert tag1 != tag2
|
||||
|
||||
tag3 = Tag("Kategorie", "Název1")
|
||||
tag4 = Tag("Kategorie", "Název2")
|
||||
assert tag3 != tag4
|
||||
|
||||
def test_tag_equality_with_non_tag(self):
|
||||
"""Test porovnání s ne-Tag objektem"""
|
||||
tag = Tag("Kategorie", "Název")
|
||||
assert tag != "Kategorie/Název"
|
||||
assert tag != 123
|
||||
assert tag != None
|
||||
|
||||
def test_tag_hash(self):
|
||||
"""Test hashování - důležité pro použití v set/dict"""
|
||||
tag1 = Tag("Kategorie", "Název")
|
||||
tag2 = Tag("Kategorie", "Název")
|
||||
tag3 = Tag("Jiná", "Název")
|
||||
|
||||
# Stejné tagy mají stejný hash
|
||||
assert hash(tag1) == hash(tag2)
|
||||
# Různé tagy mají různý hash (většinou)
|
||||
assert hash(tag1) != hash(tag3)
|
||||
|
||||
def test_tag_in_set(self):
|
||||
"""Test použití tagů v set"""
|
||||
tag1 = Tag("Kategorie", "Název")
|
||||
tag2 = Tag("Kategorie", "Název")
|
||||
tag3 = Tag("Jiná", "Název")
|
||||
|
||||
tag_set = {tag1, tag2, tag3}
|
||||
# tag1 a tag2 jsou stejné, takže set obsahuje pouze 2 prvky
|
||||
assert len(tag_set) == 2
|
||||
assert tag1 in tag_set
|
||||
assert tag3 in tag_set
|
||||
|
||||
def test_tag_in_dict(self):
|
||||
"""Test použití tagů jako klíčů v dict"""
|
||||
tag1 = Tag("Kategorie", "Název")
|
||||
tag2 = Tag("Kategorie", "Název")
|
||||
|
||||
tag_dict = {tag1: "hodnota1"}
|
||||
tag_dict[tag2] = "hodnota2"
|
||||
|
||||
# tag1 a tag2 jsou stejné, takže dict má 1 klíč
|
||||
assert len(tag_dict) == 1
|
||||
assert tag_dict[tag1] == "hodnota2"
|
||||
|
||||
def test_tag_with_special_characters(self):
|
||||
"""Test tagů se speciálními znaky"""
|
||||
tag = Tag("Kategorie/Složitá", "Název s mezerami")
|
||||
assert tag.category == "Kategorie/Složitá"
|
||||
assert tag.name == "Název s mezerami"
|
||||
assert tag.full_path == "Kategorie/Složitá/Název s mezerami"
|
||||
|
||||
def test_tag_with_empty_strings(self):
|
||||
"""Test tagů s prázdnými řetězci"""
|
||||
tag = Tag("", "")
|
||||
assert tag.category == ""
|
||||
assert tag.name == ""
|
||||
assert tag.full_path == "/"
|
||||
|
||||
def test_tag_unicode(self):
|
||||
"""Test tagů s unicode znaky"""
|
||||
tag = Tag("Kategorie", "Čeština")
|
||||
assert tag.category == "Kategorie"
|
||||
assert tag.name == "Čeština"
|
||||
assert tag.full_path == "Kategorie/Čeština"
|
||||
198
tests/test_tag_manager.py
Normal file
198
tests/test_tag_manager.py
Normal file
@@ -0,0 +1,198 @@
|
||||
import pytest
|
||||
from src.core.tag_manager import TagManager
|
||||
from src.core.tag import Tag
|
||||
|
||||
|
||||
class TestTagManager:
|
||||
"""Testy pro třídu TagManager"""
|
||||
|
||||
@pytest.fixture
|
||||
def tag_manager(self):
|
||||
"""Fixture pro vytvoření TagManager instance"""
|
||||
return TagManager()
|
||||
|
||||
def test_tag_manager_creation(self, tag_manager):
|
||||
"""Test vytvoření TagManager"""
|
||||
assert tag_manager.tags_by_category == {}
|
||||
|
||||
def test_add_category(self, tag_manager):
|
||||
"""Test přidání kategorie"""
|
||||
tag_manager.add_category("Video")
|
||||
assert "Video" in tag_manager.tags_by_category
|
||||
assert tag_manager.tags_by_category["Video"] == set()
|
||||
|
||||
def test_add_category_duplicate(self, tag_manager):
|
||||
"""Test přidání duplicitní kategorie"""
|
||||
tag_manager.add_category("Video")
|
||||
tag_manager.add_category("Video")
|
||||
assert len(tag_manager.tags_by_category) == 1
|
||||
|
||||
def test_remove_category(self, tag_manager):
|
||||
"""Test odstranění kategorie"""
|
||||
tag_manager.add_category("Video")
|
||||
tag_manager.remove_category("Video")
|
||||
assert "Video" not in tag_manager.tags_by_category
|
||||
|
||||
def test_remove_nonexistent_category(self, tag_manager):
|
||||
"""Test odstranění neexistující kategorie"""
|
||||
# Nemělo by vyhodit výjimku
|
||||
tag_manager.remove_category("Neexistující")
|
||||
assert "Neexistující" not in tag_manager.tags_by_category
|
||||
|
||||
def test_add_tag(self, tag_manager):
|
||||
"""Test přidání tagu"""
|
||||
tag = tag_manager.add_tag("Video", "HD")
|
||||
assert isinstance(tag, Tag)
|
||||
assert tag.category == "Video"
|
||||
assert tag.name == "HD"
|
||||
assert "Video" in tag_manager.tags_by_category
|
||||
assert tag in tag_manager.tags_by_category["Video"]
|
||||
|
||||
def test_add_tag_creates_category(self, tag_manager):
|
||||
"""Test že add_tag vytvoří kategorii pokud neexistuje"""
|
||||
tag = tag_manager.add_tag("NovaKategorie", "Tag")
|
||||
assert "NovaKategorie" in tag_manager.tags_by_category
|
||||
|
||||
def test_add_multiple_tags_same_category(self, tag_manager):
|
||||
"""Test přidání více tagů do stejné kategorie"""
|
||||
tag1 = tag_manager.add_tag("Video", "HD")
|
||||
tag2 = tag_manager.add_tag("Video", "4K")
|
||||
tag3 = tag_manager.add_tag("Video", "SD")
|
||||
|
||||
assert len(tag_manager.tags_by_category["Video"]) == 3
|
||||
assert tag1 in tag_manager.tags_by_category["Video"]
|
||||
assert tag2 in tag_manager.tags_by_category["Video"]
|
||||
assert tag3 in tag_manager.tags_by_category["Video"]
|
||||
|
||||
def test_add_duplicate_tag(self, tag_manager):
|
||||
"""Test přidání duplicitního tagu (set zabrání duplicitám)"""
|
||||
tag1 = tag_manager.add_tag("Video", "HD")
|
||||
tag2 = tag_manager.add_tag("Video", "HD")
|
||||
|
||||
assert len(tag_manager.tags_by_category["Video"]) == 1
|
||||
assert tag1 == tag2
|
||||
|
||||
def test_remove_tag(self, tag_manager):
|
||||
"""Test odstranění tagu - když je poslední, kategorie se smaže"""
|
||||
tag_manager.add_tag("Video", "HD")
|
||||
tag_manager.remove_tag("Video", "HD")
|
||||
|
||||
# Kategorie by měla být smazána (podle implementace v tag_manager.py)
|
||||
assert "Video" not in tag_manager.tags_by_category
|
||||
|
||||
def test_remove_tag_removes_empty_category(self, tag_manager):
|
||||
"""Test že odstranění posledního tagu odstraní i kategorii"""
|
||||
tag_manager.add_tag("Video", "HD")
|
||||
tag_manager.remove_tag("Video", "HD")
|
||||
|
||||
assert "Video" not in tag_manager.tags_by_category
|
||||
|
||||
def test_remove_tag_keeps_category_with_other_tags(self, tag_manager):
|
||||
"""Test že odstranění tagu neodstraní kategorii s dalšími tagy"""
|
||||
tag_manager.add_tag("Video", "HD")
|
||||
tag_manager.add_tag("Video", "4K")
|
||||
tag_manager.remove_tag("Video", "HD")
|
||||
|
||||
assert "Video" in tag_manager.tags_by_category
|
||||
assert len(tag_manager.tags_by_category["Video"]) == 1
|
||||
|
||||
def test_remove_nonexistent_tag(self, tag_manager):
|
||||
"""Test odstranění neexistujícího tagu"""
|
||||
tag_manager.add_category("Video")
|
||||
# Nemělo by vyhodit výjimku
|
||||
tag_manager.remove_tag("Video", "Neexistující")
|
||||
|
||||
def test_remove_tag_from_nonexistent_category(self, tag_manager):
|
||||
"""Test odstranění tagu z neexistující kategorie"""
|
||||
# Nemělo by vyhodit výjimku
|
||||
tag_manager.remove_tag("Neexistující", "Tag")
|
||||
|
||||
def test_get_all_tags_empty(self, tag_manager):
|
||||
"""Test získání všech tagů (prázdný manager)"""
|
||||
tags = tag_manager.get_all_tags()
|
||||
assert tags == []
|
||||
|
||||
def test_get_all_tags(self, tag_manager):
|
||||
"""Test získání všech tagů"""
|
||||
tag_manager.add_tag("Video", "HD")
|
||||
tag_manager.add_tag("Video", "4K")
|
||||
tag_manager.add_tag("Audio", "MP3")
|
||||
|
||||
tags = tag_manager.get_all_tags()
|
||||
assert len(tags) == 3
|
||||
assert "Video/HD" in tags
|
||||
assert "Video/4K" in tags
|
||||
assert "Audio/MP3" in tags
|
||||
|
||||
def test_get_categories_empty(self, tag_manager):
|
||||
"""Test získání kategorií (prázdný manager)"""
|
||||
categories = tag_manager.get_categories()
|
||||
assert categories == []
|
||||
|
||||
def test_get_categories(self, tag_manager):
|
||||
"""Test získání kategorií"""
|
||||
tag_manager.add_tag("Video", "HD")
|
||||
tag_manager.add_tag("Audio", "MP3")
|
||||
tag_manager.add_tag("Foto", "RAW")
|
||||
|
||||
categories = tag_manager.get_categories()
|
||||
assert len(categories) == 3
|
||||
assert "Video" in categories
|
||||
assert "Audio" in categories
|
||||
assert "Foto" in categories
|
||||
|
||||
def test_get_tags_in_category_empty(self, tag_manager):
|
||||
"""Test získání tagů z prázdné kategorie"""
|
||||
tag_manager.add_category("Video")
|
||||
tags = tag_manager.get_tags_in_category("Video")
|
||||
assert tags == []
|
||||
|
||||
def test_get_tags_in_category(self, tag_manager):
|
||||
"""Test získání tagů z kategorie"""
|
||||
tag_manager.add_tag("Video", "HD")
|
||||
tag_manager.add_tag("Video", "4K")
|
||||
tag_manager.add_tag("Audio", "MP3")
|
||||
|
||||
video_tags = tag_manager.get_tags_in_category("Video")
|
||||
assert len(video_tags) == 2
|
||||
|
||||
# Kontrola že obsahují správné tagy (pořadí není garantováno)
|
||||
tag_names = {tag.name for tag in video_tags}
|
||||
assert "HD" in tag_names
|
||||
assert "4K" in tag_names
|
||||
|
||||
def test_get_tags_in_nonexistent_category(self, tag_manager):
|
||||
"""Test získání tagů z neexistující kategorie"""
|
||||
tags = tag_manager.get_tags_in_category("Neexistující")
|
||||
assert tags == []
|
||||
|
||||
def test_complex_scenario(self, tag_manager):
|
||||
"""Test komplexního scénáře použití"""
|
||||
# Přidání několika kategorií a tagů
|
||||
tag_manager.add_tag("Video", "HD")
|
||||
tag_manager.add_tag("Video", "4K")
|
||||
tag_manager.add_tag("Audio", "MP3")
|
||||
tag_manager.add_tag("Audio", "FLAC")
|
||||
tag_manager.add_tag("Foto", "RAW")
|
||||
|
||||
# Kontrola stavu
|
||||
assert len(tag_manager.get_categories()) == 3
|
||||
assert len(tag_manager.get_all_tags()) == 5
|
||||
|
||||
# Odstranění některých tagů
|
||||
tag_manager.remove_tag("Video", "HD")
|
||||
assert len(tag_manager.get_tags_in_category("Video")) == 1
|
||||
|
||||
# Odstranění celé kategorie
|
||||
tag_manager.remove_category("Foto")
|
||||
assert "Foto" not in tag_manager.get_categories()
|
||||
assert len(tag_manager.get_all_tags()) == 3
|
||||
|
||||
def test_tag_uniqueness_in_set(self, tag_manager):
|
||||
"""Test že tagy jsou správně ukládány jako set (bez duplicit)"""
|
||||
tag_manager.add_tag("Video", "HD")
|
||||
tag_manager.add_tag("Video", "HD")
|
||||
tag_manager.add_tag("Video", "HD")
|
||||
|
||||
# I když přidáme 3x, v setu je jen 1
|
||||
assert len(tag_manager.tags_by_category["Video"]) == 1
|
||||
178
tests/test_utils.py
Normal file
178
tests/test_utils.py
Normal file
@@ -0,0 +1,178 @@
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from src.core.utils import list_files
|
||||
|
||||
|
||||
class TestUtils:
|
||||
"""Testy pro utils funkce"""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_dir(self, tmp_path):
|
||||
"""Fixture pro dočasný adresář s testovací strukturou"""
|
||||
# Vytvoření souborů v root
|
||||
(tmp_path / "file1.txt").write_text("content1")
|
||||
(tmp_path / "file2.jpg").write_text("image")
|
||||
|
||||
# Podsložka
|
||||
subdir1 = tmp_path / "subdir1"
|
||||
subdir1.mkdir()
|
||||
(subdir1 / "file3.txt").write_text("content3")
|
||||
(subdir1 / "file4.png").write_text("image2")
|
||||
|
||||
# Vnořená podsložka
|
||||
subdir2 = subdir1 / "subdir2"
|
||||
subdir2.mkdir()
|
||||
(subdir2 / "file5.txt").write_text("content5")
|
||||
|
||||
# Prázdná složka
|
||||
empty_dir = tmp_path / "empty"
|
||||
empty_dir.mkdir()
|
||||
|
||||
return tmp_path
|
||||
|
||||
def test_list_files_basic(self, temp_dir):
|
||||
"""Test základního listování souborů"""
|
||||
files = list_files(temp_dir)
|
||||
assert isinstance(files, list)
|
||||
assert len(files) > 0
|
||||
assert all(isinstance(f, Path) for f in files)
|
||||
|
||||
def test_list_files_finds_all_files(self, temp_dir):
|
||||
"""Test že najde všechny soubory včetně vnořených"""
|
||||
files = list_files(temp_dir)
|
||||
filenames = {f.name for f in files}
|
||||
|
||||
assert "file1.txt" in filenames
|
||||
assert "file2.jpg" in filenames
|
||||
assert "file3.txt" in filenames
|
||||
assert "file4.png" in filenames
|
||||
assert "file5.txt" in filenames
|
||||
assert len(filenames) == 5
|
||||
|
||||
def test_list_files_recursive(self, temp_dir):
|
||||
"""Test rekurzivního procházení složek"""
|
||||
files = list_files(temp_dir)
|
||||
|
||||
# Kontrola cest - měly by obsahovat subdir1 a subdir2
|
||||
file_paths = [str(f) for f in files]
|
||||
assert any("subdir1" in path for path in file_paths)
|
||||
assert any("subdir2" in path for path in file_paths)
|
||||
|
||||
def test_list_files_only_files_no_directories(self, temp_dir):
|
||||
"""Test že vrací pouze soubory, ne složky"""
|
||||
files = list_files(temp_dir)
|
||||
|
||||
# Všechny výsledky by měly být soubory
|
||||
assert all(f.is_file() for f in files)
|
||||
|
||||
# Složky by neměly být ve výsledcích
|
||||
filenames = {f.name for f in files}
|
||||
assert "subdir1" not in filenames
|
||||
assert "subdir2" not in filenames
|
||||
assert "empty" not in filenames
|
||||
|
||||
def test_list_files_with_string_path(self, temp_dir):
|
||||
"""Test s cestou jako string"""
|
||||
files = list_files(str(temp_dir))
|
||||
assert len(files) == 5
|
||||
|
||||
def test_list_files_with_path_object(self, temp_dir):
|
||||
"""Test s cestou jako Path objekt"""
|
||||
files = list_files(temp_dir)
|
||||
assert len(files) == 5
|
||||
|
||||
def test_list_files_empty_directory(self, temp_dir):
|
||||
"""Test prázdné složky"""
|
||||
empty_dir = temp_dir / "empty"
|
||||
files = list_files(empty_dir)
|
||||
assert files == []
|
||||
|
||||
def test_list_files_nonexistent_directory(self):
|
||||
"""Test neexistující složky"""
|
||||
with pytest.raises(NotADirectoryError) as exc_info:
|
||||
list_files("/nonexistent/path")
|
||||
assert "není platná složka" in str(exc_info.value)
|
||||
|
||||
def test_list_files_file_not_directory(self, temp_dir):
|
||||
"""Test když je zadán soubor místo složky"""
|
||||
file_path = temp_dir / "file1.txt"
|
||||
with pytest.raises(NotADirectoryError) as exc_info:
|
||||
list_files(file_path)
|
||||
assert "není platná složka" in str(exc_info.value)
|
||||
|
||||
def test_list_files_returns_absolute_paths(self, temp_dir):
|
||||
"""Test že vrací absolutní cesty"""
|
||||
files = list_files(temp_dir)
|
||||
assert all(f.is_absolute() for f in files)
|
||||
|
||||
def test_list_files_different_extensions(self, temp_dir):
|
||||
"""Test s různými příponami"""
|
||||
files = list_files(temp_dir)
|
||||
extensions = {f.suffix for f in files}
|
||||
|
||||
assert ".txt" in extensions
|
||||
assert ".jpg" in extensions
|
||||
assert ".png" in extensions
|
||||
|
||||
def test_list_files_hidden_files(self, temp_dir):
|
||||
"""Test se skrytými soubory (začínající tečkou)"""
|
||||
# Vytvoření skrytého souboru
|
||||
(temp_dir / ".hidden").write_text("hidden content")
|
||||
|
||||
files = list_files(temp_dir)
|
||||
filenames = {f.name for f in files}
|
||||
|
||||
# Skryté soubory by měly být také nalezeny
|
||||
assert ".hidden" in filenames
|
||||
|
||||
def test_list_files_special_characters_in_names(self, temp_dir):
|
||||
"""Test se speciálními znaky v názvech"""
|
||||
# Vytvoření souborů se spec. znaky
|
||||
(temp_dir / "soubor s mezerami.txt").write_text("content")
|
||||
(temp_dir / "český_název.txt").write_text("content")
|
||||
|
||||
files = list_files(temp_dir)
|
||||
filenames = {f.name for f in files}
|
||||
|
||||
assert "soubor s mezerami.txt" in filenames
|
||||
assert "český_název.txt" in filenames
|
||||
|
||||
def test_list_files_symlinks(self, temp_dir):
|
||||
"""Test se symbolickými linky (pokud OS podporuje)"""
|
||||
try:
|
||||
# Vytvoření symlinku
|
||||
target = temp_dir / "file1.txt"
|
||||
link = temp_dir / "link_to_file1.txt"
|
||||
link.symlink_to(target)
|
||||
|
||||
files = list_files(temp_dir)
|
||||
# Symlink by měl být také nalezen a považován za soubor
|
||||
filenames = {f.name for f in files}
|
||||
assert "link_to_file1.txt" in filenames or "file1.txt" in filenames
|
||||
except OSError:
|
||||
# Pokud OS nepodporuje symlinky, přeskočíme
|
||||
pytest.skip("OS does not support symlinks")
|
||||
|
||||
def test_list_files_large_directory_structure(self, tmp_path):
|
||||
"""Test s větší strukturou složek"""
|
||||
# Vytvoření více vnořených úrovní
|
||||
for i in range(3):
|
||||
level_dir = tmp_path / f"level{i}"
|
||||
level_dir.mkdir()
|
||||
for j in range(5):
|
||||
(level_dir / f"file_{i}_{j}.txt").write_text(f"content {i} {j}")
|
||||
|
||||
files = list_files(tmp_path)
|
||||
# Měli bychom najít 3 * 5 = 15 souborů
|
||||
assert len(files) == 15
|
||||
|
||||
def test_list_files_preserves_path_structure(self, temp_dir):
|
||||
"""Test že zachovává strukturu cest"""
|
||||
files = list_files(temp_dir)
|
||||
|
||||
# Najdeme soubor v subdir2
|
||||
file5 = [f for f in files if f.name == "file5.txt"][0]
|
||||
|
||||
# Cesta by měla obsahovat obě složky
|
||||
assert "subdir1" in str(file5)
|
||||
assert "subdir2" in str(file5)
|
||||
Reference in New Issue
Block a user