From 7cf7e56a93a3726a60593b6c9de7a498ff7bdde5 Mon Sep 17 00:00:00 2001 From: Paul de Raaij Date: Wed, 29 Jul 2026 01:46:58 -0400 Subject: [PATCH] feat: add DomainEvent base class and 5 domain event types --- domain/marketplace/__init__.py | 6 +++ domain/marketplace/domain_event.py | 36 +++++++++++++ tests/test_domain_event.py | 81 ++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 domain/marketplace/domain_event.py create mode 100644 tests/test_domain_event.py diff --git a/domain/marketplace/__init__.py b/domain/marketplace/__init__.py index 0eaf436..0475334 100644 --- a/domain/marketplace/__init__.py +++ b/domain/marketplace/__init__.py @@ -3,6 +3,12 @@ from .classified_ad_id import ClassifiedAdId as ClassifiedAdId from .classified_ad_state import ClassifiedAdState as ClassifiedAdState from .classified_ad_text import ClassifiedAdText as ClassifiedAdText from .classified_ad_title import ClassifiedAdTitle as ClassifiedAdTitle +from .domain_event import ClassifiedAdCreated as ClassifiedAdCreated +from .domain_event import ClassifiedAdPriceUpdated as ClassifiedAdPriceUpdated +from .domain_event import ClassifiedAdSentForReview as ClassifiedAdSentForReview +from .domain_event import ClassifiedAdTextUpdated as ClassifiedAdTextUpdated +from .domain_event import ClassifiedAdTitleChanged as ClassifiedAdTitleChanged +from .domain_event import DomainEvent as DomainEvent from .invalid_entity_state_exception import ( InvalidEntityStateException as InvalidEntityStateException, ) diff --git a/domain/marketplace/domain_event.py b/domain/marketplace/domain_event.py new file mode 100644 index 0000000..2392adb --- /dev/null +++ b/domain/marketplace/domain_event.py @@ -0,0 +1,36 @@ +from dataclasses import dataclass +from decimal import Decimal +from uuid import UUID + + +class DomainEvent: + pass + + +@dataclass(frozen=True) +class ClassifiedAdCreated(DomainEvent): + id: UUID + owner_id: UUID + + +@dataclass(frozen=True) +class ClassifiedAdTitleChanged(DomainEvent): + id: UUID + title: str + + +@dataclass(frozen=True) +class ClassifiedAdTextUpdated(DomainEvent): + id: UUID + ad_text: str + + +@dataclass(frozen=True) +class ClassifiedAdPriceUpdated(DomainEvent): + id: UUID + price: Decimal + + +@dataclass(frozen=True) +class ClassifiedAdSentForReview(DomainEvent): + id: UUID diff --git a/tests/test_domain_event.py b/tests/test_domain_event.py new file mode 100644 index 0000000..752a389 --- /dev/null +++ b/tests/test_domain_event.py @@ -0,0 +1,81 @@ +from decimal import Decimal +from uuid import uuid4 + +from domain.marketplace.domain_event import ( + ClassifiedAdCreated, + ClassifiedAdPriceUpdated, + ClassifiedAdSentForReview, + ClassifiedAdTextUpdated, + ClassifiedAdTitleChanged, + DomainEvent, +) + + +def test_classified_ad_created_creation(): + event_id = uuid4() + owner_id = uuid4() + + event = ClassifiedAdCreated(id=event_id, owner_id=owner_id) + + assert event.id == event_id + assert event.owner_id == owner_id + + +def test_classified_ad_title_changed_creation(): + event_id = uuid4() + + event = ClassifiedAdTitleChanged(id=event_id, title="New Title") + + assert event.id == event_id + assert event.title == "New Title" + + +def test_classified_ad_text_updated_creation(): + event_id = uuid4() + + event = ClassifiedAdTextUpdated(id=event_id, ad_text="Updated text") + + assert event.id == event_id + assert event.ad_text == "Updated text" + + +def test_classified_ad_price_updated_creation(): + event_id = uuid4() + + event = ClassifiedAdPriceUpdated(id=event_id, price=Decimal("99.99")) + + assert event.id == event_id + assert event.price == Decimal("99.99") + + +def test_classified_ad_sent_for_review_creation(): + event_id = uuid4() + + event = ClassifiedAdSentForReview(id=event_id) + + assert event.id == event_id + + +def test_domain_event_isinstance_check(): + event = ClassifiedAdCreated(id=uuid4(), owner_id=uuid4()) + + assert isinstance(event, DomainEvent) + + +def test_domain_events_are_immutable(): + event = ClassifiedAdCreated(id=uuid4(), owner_id=uuid4()) + + try: + event.id = uuid4() # type: ignore + assert False, "Should have raised FrozenInstanceError" + except AttributeError: + pass + + +def test_domain_event_equality(): + event_id = uuid4() + + event1 = ClassifiedAdSentForReview(id=event_id) + event2 = ClassifiedAdSentForReview(id=event_id) + + assert event1 == event2