Add event schema models and corresponding test cases
All checks were successful
Build and Push Docker Images / changes (push) Successful in 4s
Build and Push Docker Images / build-backend (push) Successful in 50s
Build and Push Docker Images / build-frontend (push) Has been skipped

Introduce Pydantic models for event creation, updates, and responses, including validation for fields such as timezone, event date, and RSVP deadline. Add comprehensive pytest test cases to ensure correct behavior and data validation. This provides a robust foundation for event-related functionalities.
This commit is contained in:
2025-03-05 12:48:25 +01:00
parent cbcd04d8e1
commit 0b6f47a602
2 changed files with 178 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
from datetime import datetime, time
from typing import Dict, Optional, List, Union
from uuid import UUID
from pydantic import BaseModel, Field, field_validator
from zoneinfo import ZoneInfo
class EventBase(BaseModel):
title: str = Field(..., min_length=1, max_length=200)
description: Optional[str] = None
location_name: Optional[str] = None
location_address: Optional[str] = None
location_url: Optional[str] = None
event_date: datetime
event_start_time: Optional[time] = None
event_end_time: Optional[time] = None
timezone: str
rsvp_deadline: Optional[datetime] = None
is_public: bool = False
access_code: Optional[str] = None
theme_id: Optional[UUID] = None
custom_theme_settings: Optional[Dict] = None
additional_info: Optional[Dict] = None
is_active: bool = True
rsvp_enabled: bool = True
gift_registry_enabled: bool = True
updates_enabled: bool = True
max_guests_per_invitation: Optional[int] = Field(None, ge=1)
contact_email: Optional[str] = None
contact_phone: Optional[str] = None
@field_validator('timezone')
def validate_timezone(cls, v):
try:
ZoneInfo(v)
return v
except Exception:
raise ValueError("Invalid timezone")
@field_validator('event_date')
def validate_event_date(cls, v):
if v < datetime.now(ZoneInfo('UTC')):
raise ValueError("Event date cannot be in the past")
return v
@field_validator('rsvp_deadline')
def validate_rsvp_deadline(cls, v, values):
if v and 'event_date' in values.data:
if v > values.data['event_date']:
raise ValueError("RSVP deadline must be before event date")
return v
class EventCreate(EventBase):
slug: str = Field(..., min_length=1, pattern="^[a-z0-9-]+$")
class EventUpdate(EventBase):
title: Optional[str] = None
event_date: Optional[datetime] = None
timezone: Optional[str] = None
slug: Optional[str] = Field(None, min_length=1, pattern="^[a-z0-9-]+$")
class EventInDBBase(EventBase):
id: UUID
created_by: UUID
created_at: datetime
updated_at: datetime
slug: str
class Config:
from_attributes = True
class EventResponse(EventInDBBase):
pass
class Event(EventInDBBase):
pass

View File

@@ -0,0 +1,97 @@
import pytest
from datetime import datetime, time, timedelta
from uuid import uuid4, UUID
from zoneinfo import ZoneInfo
from app.schemas.events import EventCreate, EventUpdate, EventResponse
def test_valid_event_create():
event_date = datetime.now(ZoneInfo('UTC')) + timedelta(days=1)
event_data = {
"title": "Emma's First Birthday",
"slug": "emmas-first-birthday",
"description": "Join us for Emma's first birthday celebration!",
"event_date": event_date,
"timezone": "America/New_York",
"location_name": "Central Park",
"is_public": False,
"access_code": "EMMA2024"
}
event = EventCreate(**event_data)
assert event.title == "Emma's First Birthday"
assert event.slug == "emmas-first-birthday"
assert event.timezone == "America/New_York"
def test_invalid_event_create():
event_date = datetime.now(ZoneInfo('UTC')) - timedelta(days=1)
with pytest.raises(ValueError):
EventCreate(
title="Past Event",
slug="past-event",
event_date=event_date,
timezone="America/New_York"
)
def test_invalid_timezone():
with pytest.raises(ValueError):
EventCreate(
title="Test Event",
slug="test-event",
event_date=datetime.now(ZoneInfo('UTC')) + timedelta(days=1),
timezone="Invalid/Timezone"
)
def test_event_update_partial():
update_data = {
"title": "Updated Title",
"description": "Updated description"
}
event_update = EventUpdate(**update_data)
assert event_update.title == "Updated Title"
assert event_update.description == "Updated description"
def test_event_response():
event_date = datetime.now(ZoneInfo('UTC')) + timedelta(days=1)
event_data = {
"id": uuid4(),
"title": "Test Event",
"slug": "test-event",
"event_date": event_date,
"timezone": "UTC",
"created_by": uuid4(),
"created_at": datetime.now(ZoneInfo('UTC')),
"updated_at": datetime.now(ZoneInfo('UTC'))
}
event_response = EventResponse(**event_data)
assert event_response.title == "Test Event"
assert isinstance(event_response.id, UUID)
def test_invalid_slug_format():
event_date = datetime.now(ZoneInfo('UTC')) + timedelta(days=1)
with pytest.raises(ValueError):
EventCreate(
title="Test Event",
slug="Invalid Slug!", # Invalid slug format
event_date=event_date,
timezone="UTC"
)
def test_rsvp_deadline_validation():
event_date = datetime.now(ZoneInfo('UTC')) + timedelta(days=10)
invalid_deadline = event_date + timedelta(days=1)
with pytest.raises(ValueError):
EventCreate(
title="Test Event",
slug="test-event",
event_date=event_date,
timezone="UTC",
rsvp_deadline=invalid_deadline
)