Add and extend test coverage for models and their methods
All checks were successful
Build and Push Docker Images / changes (push) Successful in 4s
Build and Push Docker Images / build-backend (push) Successful in 49s
Build and Push Docker Images / build-frontend (push) Has been skipped

Enhanced test coverage includes `repr` methods, model functionality, and validation logic for key models like `GiftItem`, `GiftCategory`, `EventMedia`, `RSVP`, and `GiftPurchase`. Refactored and added fixtures to support comprehensive testing scenarios. Addresses validation for gift reordering and updates `EventMedia` representation format for consistency.
This commit is contained in:
2025-02-28 15:57:32 +01:00
parent c15c55d691
commit 1fd1144bc1
6 changed files with 256 additions and 6 deletions

View File

@@ -4,7 +4,8 @@ from datetime import datetime, timezone
import pytest
from app.models import GiftItem, GiftStatus, GiftPriority, RSVP, RSVPStatus, EventMedia, MediaType, MediaPurpose, \
from app.models import Event, GiftItem, GiftStatus, GiftPriority, GiftCategory, GiftPurchase, RSVP, RSVPStatus, \
EventMedia, MediaType, MediaPurpose, \
EventTheme, Guest, GuestStatus, ActivityType, ActivityLog, EmailTemplate, TemplateType, NotificationLog, \
NotificationType, NotificationStatus
from app.models.user import User
@@ -47,6 +48,31 @@ def mock_user(db_session):
return mock_user
@pytest.fixture
def event_fixture(db_session, mock_user):
"""
Fixture to create and return an Event instance with valid data.
"""
event = Event(
id=uuid.uuid4(),
title="Birthday Party",
slug="birthday-party-1", # Required unique slug
description="A special 1st birthday celebration event.",
event_date=datetime(2023, 12, 25, tzinfo=timezone.utc),
timezone="UTC", # Required timezone
created_by=mock_user.id, # Reference to a valid mock_user
is_public=False, # Default value
is_active=True, # Default value
rsvp_enabled=False, # Default value
gift_registry_enabled=True, # Default value
updates_enabled=True # Default value
)
db_session.add(event)
db_session.commit()
return event
@pytest.fixture
def gift_item_fixture(db_session, mock_user):
"""
@@ -219,6 +245,7 @@ def email_template_fixture(db_session, mock_user):
db_session.commit()
return email_template
@pytest.fixture
def notification_log_fixture(db_session, email_template_fixture, guest_fixture):
"""
@@ -238,4 +265,43 @@ def notification_log_fixture(db_session, email_template_fixture, guest_fixture):
)
db_session.add(notification_log)
db_session.commit()
return notification_log
return notification_log
@pytest.fixture
def gift_purchase_fixture(db_session, gift_item_fixture, guest_fixture):
"""
Fixture to create and return a GiftPurchase instance.
"""
gift_purchase = GiftPurchase(
id=uuid.uuid4(),
gift_id=gift_item_fixture.id,
guest_id=guest_fixture.id,
quantity=1,
purchased_at=datetime.now(timezone.utc),
purchase_price=25.0,
purchase_currency="USD",
notes="Gift purchased through store link"
)
db_session.add(gift_purchase)
db_session.commit()
return gift_purchase
@pytest.fixture
def gift_category_fixture(db_session, mock_user, event_fixture):
"""
Fixture to create and return a GiftCategory instance.
"""
gift_category = GiftCategory(
id=uuid.uuid4(),
name="Electronics",
description="Category for electronic gifts",
event_id=event_fixture.id,
created_by=mock_user.id,
display_order=0,
is_visible=True
)
db_session.add(gift_category)
db_session.commit()
return gift_category

View File

@@ -101,4 +101,12 @@ def test_media_metadata(event_media_fixture):
# Update and check
event_media_fixture.media_metadata = {"resolution": "1280x720"}
assert event_media_fixture.media_metadata == {"resolution": "1280x720"}
assert event_media_fixture.media_metadata == {"resolution": "1280x720"}
def test_event_media_repr(event_media_fixture):
# Act
result = repr(event_media_fixture)
# Assert
expected = f"<EventMedia {event_media_fixture.original_filename} ({event_media_fixture.media_type.value}) for event={event_media_fixture.event_id}>"
assert result == expected

View File

@@ -1,5 +1,8 @@
# tests/models/test_gift.py
import uuid
import pytest
from app.models.gift import GiftItem, GiftStatus, GiftPriority, GiftCategory, GiftPurchase
@@ -84,6 +87,45 @@ def test_gift_item_is_fully_received(gift_item_fixture):
# Assert
assert is_fully_received is True
def test_gift_item_repr(db_session, gift_item_fixture):
# Act
repr_output = repr(gift_item_fixture)
# Assert
assert repr_output == f"<GiftItem {gift_item_fixture.name} ({gift_item_fixture.status.value})>"
from datetime import datetime, timezone
def test_update_status(db_session, gift_item_fixture):
# Arrange
gift_item_fixture.status = 'available'
# Act
gift_item_fixture.update_status('reserved')
# Assert
assert gift_item_fixture.status == 'reserved'
assert gift_item_fixture.last_status_change is not None
assert gift_item_fixture.last_status_change <= datetime.now(timezone.utc)
def test_gift_item_formatted_price(db_session, gift_item_fixture):
# Act: Case when price and currency are set
gift_item_fixture.price = 25.0
gift_item_fixture.currency = "USD"
formatted_price = gift_item_fixture.formatted_price
# Assert
assert formatted_price == "25.00 USD"
# Act: Case when price is `None`
gift_item_fixture.price = None
formatted_price_no_price = gift_item_fixture.formatted_price
# Assert
assert formatted_price_no_price == "Price not set"
# ================================
# GiftCategory Test Cases
@@ -147,6 +189,107 @@ def test_gift_category_total_gifts(db_session, mock_user):
# Assert
assert total_gifts == 3 # 2 from gift1 + 1 from gift2
def test_gift_category_repr(db_session, gift_category_fixture):
# Act
repr_output = repr(gift_category_fixture)
# Assert
assert repr_output == f"<GiftCategory {gift_category_fixture.name}>"
def test_gift_category_available_gifts(db_session, gift_category_fixture, gift_item_fixture):
"""
Test that the available_gifts method correctly counts the available gifts.
"""
# Update gift_item_fixture to match the gift_category_fixture
gift_item = GiftItem(
name="Toy Car",
description="A toy for kids",
price=10.0,
currency="USD",
quantity_requested=1,
quantity_received=0,
status=GiftStatus.AVAILABLE,
is_visible=True,
category_id=gift_category_fixture.id,
event_id=gift_category_fixture.event_id, # Ensure event linkage
added_by=gift_category_fixture.created_by # Link to a user
)
db_session.add(gift_item)
db_session.commit()
# Assert that exactly one gift is available
assert gift_category_fixture.available_gifts == 1
def test_gift_category_reorder_gifts(db_session, gift_category_fixture, mock_user):
"""
Test that the reorder_gifts method correctly updates gift display_order
based on the provided order of gift IDs.
"""
# Create GiftItems with proper required fields and UUID objects (not strings)
gift1_id = uuid.uuid4()
gift2_id = uuid.uuid4()
gift3_id = uuid.uuid4()
gift1 = GiftItem(
id=gift1_id,
name="Gift 1",
display_order=0,
category_id=gift_category_fixture.id,
event_id=gift_category_fixture.event_id, # Required field
added_by=gift_category_fixture.created_by, # Required field
status=GiftStatus.AVAILABLE # Required field
)
gift2 = GiftItem(
id=gift2_id,
name="Gift 2",
display_order=1,
category_id=gift_category_fixture.id,
event_id=gift_category_fixture.event_id,
added_by=gift_category_fixture.created_by,
status=GiftStatus.AVAILABLE
)
gift3 = GiftItem(
id=gift3_id,
name="Gift 3",
display_order=2,
category_id=gift_category_fixture.id,
event_id=gift_category_fixture.event_id,
added_by=gift_category_fixture.created_by,
status=GiftStatus.AVAILABLE
)
# Add gifts and refresh category to ensure the relationship is established
db_session.add_all([gift1, gift2, gift3])
db_session.commit()
db_session.refresh(gift_category_fixture)
# Act: Reorder gifts using the gift IDs (as UUID objects, not strings)
new_order = [gift3.id, gift1.id, gift2.id]
gift_category_fixture.reorder_gifts(new_order)
db_session.commit() # Make sure to commit the changes
# Refresh everything to ensure we get the latest data
db_session.refresh(gift1)
db_session.refresh(gift2)
db_session.refresh(gift3)
# Assert: Verify the display orders are updated correctly
assert gift1.display_order == 1
assert gift2.display_order == 2
assert gift3.display_order == 0
def test_reorder_gifts_invalid_id(gift_category_fixture, db_session):
"""
Test that reorder_gifts raises a ValueError when an invalid gift ID is provided.
"""
# Arrange: Ensure the category and database session are ready
db_session.add(gift_category_fixture)
db_session.commit()
# Act and Assert: Pass an invalid gift ID and assert it raises the correct exception
invalid_gift_id = "nonexistent-id"
with pytest.raises(ValueError, match=f"Gift ID {invalid_gift_id} not found in category"):
gift_category_fixture.reorder_gifts([invalid_gift_id])
# ================================
# GiftPurchase Test Cases
@@ -195,4 +338,11 @@ def test_link_purchase_to_gift(db_session, gift_item_fixture):
# Assert
assert len(gift_purchases) == 1
assert gift_purchases[0].quantity == 1
assert gift_purchases[0].purchase_price == 25.00
assert gift_purchases[0].purchase_price == 25.00
def test_gift_purchase_repr(db_session, gift_purchase_fixture):
# Act
repr_output = repr(gift_purchase_fixture)
# Assert
assert repr_output == f"<GiftPurchase gift_id={gift_purchase_fixture.gift_id} guest_id={gift_purchase_fixture.guest_id}>"

View File

@@ -103,4 +103,22 @@ def test_dietary_requirements(rsvp_fixture):
# Update and re-check
rsvp_fixture.dietary_requirements = "No preference"
assert rsvp_fixture.dietary_requirements == "No preference"
assert rsvp_fixture.dietary_requirements == "No preference"
def test_rsvp_repr(db_session):
# Arrange
rsvp = RSVP(
id=uuid.uuid4(),
event_id=uuid.uuid4(),
guest_id=uuid.uuid4(),
status=RSVPStatus.ATTENDING,
number_of_guests=3,
)
db_session.add(rsvp)
db_session.commit()
# Act
result = repr(rsvp)
# Assert
assert result == f"<RSVP guest_id={rsvp.guest_id} status=attending>"