feat: major architectural refactor
- Refactor memory system (episodic/STM/LTM with components) - Implement complete subtitle domain (scanner, matcher, placer) - Add YAML workflow infrastructure - Externalize knowledge base (patterns, release groups) - Add comprehensive testing suite - Create manual testing CLIs
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
"""Tests for shared domain value objects: ImdbId, FilePath, FileSize."""
|
||||
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
|
||||
from alfred.domain.shared.exceptions import ValidationError
|
||||
from alfred.domain.shared.value_objects import FilePath, FileSize, ImdbId
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ImdbId
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestImdbId:
|
||||
|
||||
def test_valid_7_digits(self):
|
||||
id_ = ImdbId("tt1375666")
|
||||
assert str(id_) == "tt1375666"
|
||||
|
||||
def test_valid_8_digits(self):
|
||||
id_ = ImdbId("tt12345678")
|
||||
assert str(id_) == "tt12345678"
|
||||
|
||||
def test_empty_raises(self):
|
||||
with pytest.raises(ValidationError):
|
||||
ImdbId("")
|
||||
|
||||
def test_no_tt_prefix_raises(self):
|
||||
with pytest.raises(ValidationError):
|
||||
ImdbId("1375666")
|
||||
|
||||
def test_too_few_digits_raises(self):
|
||||
with pytest.raises(ValidationError):
|
||||
ImdbId("tt12345") # only 5 digits
|
||||
|
||||
def test_too_many_digits_raises(self):
|
||||
with pytest.raises(ValidationError):
|
||||
ImdbId("tt123456789") # 9 digits
|
||||
|
||||
def test_non_string_raises(self):
|
||||
with pytest.raises(ValidationError):
|
||||
ImdbId(1375666) # type: ignore
|
||||
|
||||
def test_repr(self):
|
||||
assert "tt1375666" in repr(ImdbId("tt1375666"))
|
||||
|
||||
def test_equality(self):
|
||||
assert ImdbId("tt1375666") == ImdbId("tt1375666")
|
||||
assert ImdbId("tt1375666") != ImdbId("tt0903747")
|
||||
|
||||
def test_hashable(self):
|
||||
# Frozen dataclass should be hashable
|
||||
ids = {ImdbId("tt1375666"), ImdbId("tt0903747")}
|
||||
assert len(ids) == 2
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# FilePath
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestFilePath:
|
||||
|
||||
def test_from_string(self, tmp_path):
|
||||
p = FilePath(str(tmp_path))
|
||||
assert isinstance(p.value, Path)
|
||||
|
||||
def test_from_path(self, tmp_path):
|
||||
p = FilePath(tmp_path)
|
||||
assert p.value == tmp_path
|
||||
|
||||
def test_invalid_type_raises(self):
|
||||
with pytest.raises(ValidationError):
|
||||
FilePath(123) # type: ignore
|
||||
|
||||
def test_exists_true(self, tmp_path):
|
||||
p = FilePath(tmp_path)
|
||||
assert p.exists()
|
||||
|
||||
def test_exists_false(self, tmp_path):
|
||||
p = FilePath(tmp_path / "nonexistent")
|
||||
assert not p.exists()
|
||||
|
||||
def test_is_file(self, tmp_path):
|
||||
f = tmp_path / "file.txt"
|
||||
f.write_text("x")
|
||||
assert FilePath(f).is_file()
|
||||
assert not FilePath(tmp_path).is_file()
|
||||
|
||||
def test_is_dir(self, tmp_path):
|
||||
assert FilePath(tmp_path).is_dir()
|
||||
|
||||
def test_str(self, tmp_path):
|
||||
p = FilePath(tmp_path)
|
||||
assert str(p) == str(tmp_path)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# FileSize
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestFileSize:
|
||||
|
||||
def test_bytes(self):
|
||||
s = FileSize(500)
|
||||
assert s.bytes == 500
|
||||
|
||||
def test_negative_raises(self):
|
||||
with pytest.raises(ValidationError):
|
||||
FileSize(-1)
|
||||
|
||||
def test_non_integer_raises(self):
|
||||
with pytest.raises(ValidationError):
|
||||
FileSize(1.5) # type: ignore
|
||||
|
||||
def test_zero_is_valid(self):
|
||||
s = FileSize(0)
|
||||
assert s.bytes == 0
|
||||
|
||||
def test_human_readable_bytes(self):
|
||||
assert FileSize(500).to_human_readable() == "500 B"
|
||||
|
||||
def test_human_readable_kb(self):
|
||||
result = FileSize(2048).to_human_readable()
|
||||
assert "KB" in result
|
||||
|
||||
def test_human_readable_mb(self):
|
||||
result = FileSize(5 * 1024 * 1024).to_human_readable()
|
||||
assert "MB" in result
|
||||
|
||||
def test_human_readable_gb(self):
|
||||
result = FileSize(2 * 1024 ** 3).to_human_readable()
|
||||
assert "GB" in result
|
||||
|
||||
def test_str_is_human_readable(self):
|
||||
s = FileSize(1024)
|
||||
assert str(s) == s.to_human_readable()
|
||||
Reference in New Issue
Block a user