Phase 7: End-to-End API Testing - Database setup, migrations, and application fixes

- Switched from psycopg2 to asyncpg for async SQLAlchemy support
- Fixed router registration in main.py - removed duplicate prefixes
- Added user_data export to routers/__init__.py
- Refactored decks router to use DeckManager service layer
- Integrated FuzzyCardMatcher into card_router search endpoints
- Made WishlistCreate.card_id optional for proper schema validation
- Set PostgreSQL password and configured scram-sha-256 auth
- Updated alembic.ini to use local PostgreSQL instead of Docker hostname
- Created generic_schemas.py for reusable schema patterns
- Added test_routers.py and test_schema_validation.py test files
- All 6 Alembic migrations applied successfully (37 tables created)
- Application running on port 8000 with all services connected
This commit is contained in:
2026-08-18 03:35:19 +00:00
parent bea91db64d
commit 1df04aea52
20 changed files with 862 additions and 513 deletions
+13 -21
View File
@@ -3,7 +3,7 @@ Pydantic schemas for request/response validation.
Provides typed data structures for API endpoints.
"""
from pydantic import BaseModel, EmailStr, Field
from pydantic import BaseModel, EmailStr, Field, ConfigDict
from typing import Optional, List, Dict
from datetime import datetime
@@ -49,8 +49,8 @@ class UserCreate(UserBase):
"""User registration fields."""
password: str = Field(..., min_length=8)
class Config:
json_schema_extra = {
model_config = ConfigDict(
json_schema_extra={
"example": {
"username": "player123",
"password": "securepassword123",
@@ -58,6 +58,7 @@ class UserCreate(UserBase):
"country": "US"
}
}
)
class UserUpdate(BaseModel):
@@ -83,8 +84,7 @@ class UserResponse(BaseModel):
creation_date: datetime
last_login: Optional[datetime]
class Config:
from_attributes = True
model_config = ConfigDict(from_attributes=True)
# ===== Deck Schemas =====
@@ -117,8 +117,7 @@ class DeckResponse(BaseModel):
owner_id: int
creation_date: datetime
class Config:
from_attributes = True
model_config = ConfigDict(from_attributes=True)
class FolderCreate(BaseModel):
@@ -135,8 +134,7 @@ class FolderResponse(BaseModel):
owner_id: int
creation_date: datetime
class Config:
from_attributes = True
model_config = ConfigDict(from_attributes=True)
# ===== Game Schemas =====
@@ -161,8 +159,7 @@ class GameResponse(BaseModel):
started: bool
creation_date: datetime
class Config:
from_attributes = True
model_config = ConfigDict(from_attributes=True)
# ===== Room Schemas =====
@@ -177,8 +174,7 @@ class RoomResponse(BaseModel):
player_count: int = 0
creation_date: datetime
class Config:
from_attributes = True
model_config = ConfigDict(from_attributes=True)
# ===== Ban Schemas =====
@@ -200,8 +196,7 @@ class BanResponse(BaseModel):
active: bool
creation_date: datetime
class Config:
from_attributes = True
model_config = ConfigDict(from_attributes=True)
# ===== Auth Error Responses =====
@@ -261,8 +256,7 @@ class CardMirrorResponse(BaseModel):
synced_at: Optional[datetime]
created_at: datetime
class Config:
from_attributes = True
model_config = ConfigDict(from_attributes=True)
class DeckCardLinkResponse(BaseModel):
@@ -274,8 +268,7 @@ class DeckCardLinkResponse(BaseModel):
zone: str
card: CardMirrorResponse
class Config:
from_attributes = True
model_config = ConfigDict(from_attributes=True)
class DeckWithCardsResponse(BaseModel):
@@ -290,5 +283,4 @@ class DeckWithCardsResponse(BaseModel):
creation_date: datetime
card_links: List[DeckCardLinkResponse] = []
class Config:
from_attributes = True
model_config = ConfigDict(from_attributes=True)