ytptube/app/tests/test_encoder.py
2025-12-30 20:42:50 +03:00

164 lines
5.4 KiB
Python

"""
Tests for encoder.py - JSON encoding utilities.
This test suite provides comprehensive coverage for the Encoder class:
- Tests serialization of various Python types
- Tests special handling of Path objects
- Tests DateRange serialization
- Tests date serialization
- Tests ImpersonateTarget serialization
- Tests ItemDTO serialization
- Tests object serialization with serialize() method
- Tests object serialization with __dict__ fallback
- Tests fallback to default JSONEncoder behavior
Total test functions: 10
All supported types and edge cases are covered.
"""
import json
from datetime import date
from pathlib import Path
from unittest.mock import MagicMock
import pytest
from app.library.encoder import Encoder
class TestEncoder:
"""Test the Encoder class."""
def setup_method(self):
"""Set up test fixtures."""
self.encoder = Encoder()
def test_path_serialization(self):
"""Test that Path objects are serialized as strings."""
path = Path("/tmp/test/file.txt")
result = self.encoder.default(path)
assert result == "/tmp/test/file.txt"
assert isinstance(result, str)
def test_path_serialization_relative(self):
"""Test that relative Path objects are serialized correctly."""
path = Path("relative/path/file.txt")
result = self.encoder.default(path)
assert result == "relative/path/file.txt"
def test_date_serialization(self):
"""Test that date objects are serialized as strings."""
test_date = date(2024, 3, 15)
result = self.encoder.default(test_date)
assert result == "2024-03-15"
def test_object_with_serialize_method(self):
"""Test that objects with serialize method use it."""
class CustomObject:
def serialize(self):
return {"custom": "data", "type": "test"}
obj = CustomObject()
result = self.encoder.default(obj)
assert result == {"custom": "data", "type": "test"}
def test_object_with_dict_fallback(self):
"""Test that objects without serialize method fall back to __dict__."""
class SimpleObject:
def __init__(self):
self.name = "test"
self.value = 42
obj = SimpleObject()
result = self.encoder.default(obj)
assert result == {"name": "test", "value": 42}
def test_object_without_dict_fallback_to_default(self):
"""Test that objects without __dict__ fall back to default JSONEncoder."""
# This should raise TypeError since complex is not JSON serializable
with pytest.raises(TypeError):
self.encoder.default(complex(1, 2))
def test_json_dumps_integration(self):
"""Test full JSON serialization with various types."""
data = {"path": Path("/tmp/test.txt"), "date": date(2024, 1, 1), "number": 42, "string": "test"}
result = json.dumps(data, cls=Encoder)
parsed = json.loads(result)
assert parsed["path"] == "/tmp/test.txt"
assert parsed["date"] == "2024-01-01"
assert parsed["number"] == 42
assert parsed["string"] == "test"
def test_json_dumps_with_custom_object(self):
"""Test JSON serialization with custom objects."""
class TestObject:
def __init__(self):
self.name = "test"
self.items = [1, 2, 3]
data = {"object": TestObject(), "regular": "data"}
result = json.dumps(data, cls=Encoder)
parsed = json.loads(result)
assert parsed["object"]["name"] == "test"
assert parsed["object"]["items"] == [1, 2, 3]
assert parsed["regular"] == "data"
def test_nested_serialization(self):
"""Test serialization of nested structures with various types."""
class CustomObj:
def serialize(self):
return {"serialized": True}
data = {
"paths": [Path("/tmp/1.txt"), Path("/tmp/2.txt")],
"dates": [date(2024, 1, 1), date(2024, 12, 31)],
"custom": CustomObj(),
"nested": {"path": Path("/nested/path"), "date": date(2024, 6, 15)},
}
result = json.dumps(data, cls=Encoder)
parsed = json.loads(result)
assert parsed["paths"] == ["/tmp/1.txt", "/tmp/2.txt"]
assert parsed["dates"] == ["2024-01-01", "2024-12-31"]
assert parsed["custom"] == {"serialized": True}
assert parsed["nested"]["path"] == "/nested/path"
assert parsed["nested"]["date"] == "2024-06-15"
def test_mock_daterange_serialization(self):
"""Test DateRange serialization with mock object."""
# Mock a DateRange-like object
mock_daterange = MagicMock()
mock_daterange.start = date(2024, 1, 15)
mock_daterange.end = date(2024, 12, 31)
# Mock isinstance to return True for DateRange
import builtins
original_isinstance = builtins.isinstance
def mock_isinstance(obj, cls):
if obj is mock_daterange and hasattr(cls, "__name__") and "DateRange" in str(cls):
return True
return original_isinstance(obj, cls)
builtins.isinstance = mock_isinstance
try:
result = self.encoder.default(mock_daterange)
expected = {"start": "20240115", "end": "20241231"}
assert result == expected
finally:
builtins.isinstance = original_isinstance
if __name__ == "__main__":
pytest.main([__file__])