"""Unit tests for persistence serialize_model function. Tests cover: - serialize_model() with various column types - datetime conversion to isoformat - masked_columns exclusion """ from __future__ import annotations import datetime from unittest.mock import Mock from sqlalchemy import Column, Integer, String, DateTime from sqlalchemy.orm import declarative_base from importlib import import_module def get_persistence_module(): """Lazy import to avoid circular import issues.""" return import_module('langbot.pkg.persistence.mgr') # Create a simple test model Base = declarative_base() class TestModel(Base): __tablename__ = 'test_model' id = Column(Integer, primary_key=True) name = Column(String(50)) created_at = Column(DateTime) updated_at = Column(DateTime, nullable=True) class TestSerializeModel: """Tests for serialize_model method.""" def test_serialize_string_and_int_columns(self): """Test that string and int columns are serialized directly.""" persistence = get_persistence_module() # Create a mock persistence manager mock_app = Mock() mock_app.persistence_mgr = None mgr = persistence.PersistenceManager(mock_app) # Create test model instance instance = TestModel(id=1, name='test_name', created_at=datetime.datetime(2024, 1, 15, 10, 30, 0)) result = mgr.serialize_model(TestModel, instance) assert result['id'] == 1 assert result['name'] == 'test_name' def test_serialize_datetime_to_isoformat(self): """Test that datetime columns are converted to isoformat string.""" persistence = get_persistence_module() mock_app = Mock() mgr = persistence.PersistenceManager(mock_app) dt = datetime.datetime(2024, 1, 15, 10, 30, 45) instance = TestModel(id=1, name='test', created_at=dt) result = mgr.serialize_model(TestModel, instance) assert result['created_at'] == '2024-01-15T10:30:45' assert isinstance(result['created_at'], str) def test_serialize_datetime_with_timezone(self): """Test datetime with timezone conversion.""" persistence = get_persistence_module() mock_app = Mock() mgr = persistence.PersistenceManager(mock_app) # datetime with timezone dt = datetime.datetime(2024, 1, 15, 10, 30, 45, tzinfo=datetime.timezone.utc) instance = TestModel(id=1, name='test', created_at=dt) result = mgr.serialize_model(TestModel, instance) assert '2024-01-15' in result['created_at'] assert isinstance(result['created_at'], str) def test_serialize_none_datetime(self): """Test that None datetime column is serialized as None.""" persistence = get_persistence_module() mock_app = Mock() mgr = persistence.PersistenceManager(mock_app) instance = TestModel(id=1, name='test', created_at=datetime.datetime.now(), updated_at=None) result = mgr.serialize_model(TestModel, instance) # None datetime should be None (not converted to isoformat) assert result['updated_at'] is None def test_masked_columns_excluded(self): """Test that masked columns are excluded from output.""" persistence = get_persistence_module() mock_app = Mock() mgr = persistence.PersistenceManager(mock_app) instance = TestModel(id=1, name='secret_name', created_at=datetime.datetime.now()) result = mgr.serialize_model(TestModel, instance, masked_columns=['name']) assert 'id' in result assert 'created_at' in result assert 'name' not in result def test_masked_columns_multiple(self): """Test that multiple masked columns are excluded.""" persistence = get_persistence_module() mock_app = Mock() mgr = persistence.PersistenceManager(mock_app) instance = TestModel(id=1, name='secret', created_at=datetime.datetime.now()) result = mgr.serialize_model(TestModel, instance, masked_columns=['id', 'name']) assert 'id' not in result assert 'name' not in result assert 'created_at' in result