"""Unit tests for PaymentAllocationEvent schema.""" import pytest from pydantic import ValidationError from src.schemas import ( PaymentAllocationEvent, SimplePaymentAllocationEvent, parse_event, ) def _make_event_dict( detail_type: str = 'close_balance.completed', target_id: int = 1, target_type: str = 'statement_period_payment_entity', correlation_id: str | None = 'abc-123', ) -> dict: """Create a valid event dict for testing.""" return { 'detail-type': detail_type, 'detail': { 'metadata': { 'correlation_id': correlation_id, 'target_id': target_id, 'target_type': target_type, }, }, } class TestPaymentAllocationEvent: """Tests for PaymentAllocationEvent validation.""" def test_valid_event(self): """Test valid event parsing.""" event = PaymentAllocationEvent(**_make_event_dict(target_id=42)) assert event.detail.metadata.target_id == 42 assert event.detail_type == 'close_balance.completed' assert event.detail.metadata.target_type == 'statement_period_payment_entity' assert event.detail.metadata.correlation_id == 'abc-123' def test_correlation_id_optional(self): """Test that correlation_id is optional.""" event = PaymentAllocationEvent(**_make_event_dict(correlation_id=None)) assert event.detail.metadata.correlation_id is None def test_extra_fields_ignored(self): """Test that extra fields are ignored at all levels.""" event_dict = _make_event_dict() event_dict['source'] = 'some-source' event_dict['detail']['extra'] = 'ignored' event_dict['detail']['metadata']['outbox_event_id'] = 123 event = PaymentAllocationEvent(**event_dict) assert event.detail.metadata.target_id == 1 def test_missing_detail_type(self): """Test validation error when detail-type is missing.""" event_dict = _make_event_dict() del event_dict['detail-type'] with pytest.raises(ValidationError) as exc_info: PaymentAllocationEvent(**event_dict) assert 'detail-type' in str(exc_info.value) def test_wrong_detail_type(self): """Test validation error for wrong detail-type value.""" with pytest.raises(ValidationError): PaymentAllocationEvent( **_make_event_dict(detail_type='file_upload.completed') ) def test_wrong_target_type(self): """Test validation error for wrong target_type value.""" with pytest.raises(ValidationError): PaymentAllocationEvent(**_make_event_dict(target_type='file_upload')) def test_missing_detail(self): """Test validation error when detail is missing.""" with pytest.raises(ValidationError): PaymentAllocationEvent(**{'detail-type': 'close_balance.completed'}) def test_missing_metadata(self): """Test validation error when metadata is missing.""" with pytest.raises(ValidationError): PaymentAllocationEvent( **{ 'detail-type': 'close_balance.completed', 'detail': {}, } ) class TestSimplePaymentAllocationEvent: """Tests for SimplePaymentAllocationEvent validation.""" def test_valid_simple_event(self): """Test valid simple event parsing.""" event = SimplePaymentAllocationEvent(statement_period_payment_entity_id=42) assert event.statement_period_payment_entity_id == 42 def test_missing_sppe_id(self): """Test validation error when sppe_id is missing.""" with pytest.raises(ValidationError): SimplePaymentAllocationEvent() class TestParseEvent: """Tests for parse_event function.""" def test_parse_eventbridge_event(self): """Test parsing a full EventBridge event.""" raw = _make_event_dict(target_id=42) assert parse_event(raw) == 42 def test_parse_simple_event(self): """Test parsing a simple event.""" raw = {'statement_period_payment_entity_id': 99} assert parse_event(raw) == 99 def test_parse_invalid_eventbridge_event(self): """Test parsing an invalid EventBridge event raises ValidationError.""" raw = { 'detail-type': 'wrong.type', 'detail': { 'metadata': { 'target_id': 1, 'target_type': 'statement_period_payment_entity', } }, } with pytest.raises(ValidationError): parse_event(raw) def test_parse_empty_event(self): """Test parsing an empty event raises ValidationError.""" with pytest.raises(ValidationError): parse_event({})