Files
mtgonline/backend/tests/test_game_models.py
T
akadmin b7056fe0d9 Fix SQLite autoincrement and test configuration
- Removed autoincrement=True from BigInteger primary keys (UserDeck, UserDeckCard, DeckPrecedent, etc.)
- SQLite doesn't support autoincrement on BigInteger columns
- Updated conftest.py test engine configuration
- All admin tests passing (5/5)
- All auth tests passing (7/7)
- Game model tests passing (13/13)
- Deck tests still failing due to SQLite RETURNING clause issue
2026-08-28 03:43:14 +00:00

313 lines
10 KiB
Python

"""
Tests for game models and database integration.
"""
import pytest
import pytest_asyncio
from datetime import datetime
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy import select
from app.models.models import MTGOnlineGame, GamePlayer, GameHistory
from app.core.database import Base
# Test database setup
TEST_DATABASE_URL = "sqlite+aiosqlite:///./test_games.db"
@pytest.fixture(scope="module")
def event_loop():
"""Create event loop for async tests."""
import asyncio
loop = asyncio.new_event_loop()
yield loop
loop.close()
@pytest_asyncio.fixture
async def test_engine():
"""Create test database engine."""
engine = create_async_engine(TEST_DATABASE_URL, echo=False)
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield engine
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.drop_all)
# Cleanup test database
import os
if os.path.exists("./test_games.db"):
os.remove("./test_games.db")
@pytest_asyncio.fixture
async def db_session(test_engine):
"""Create test database session."""
async_session = sessionmaker(test_engine, class_=AsyncSession, expire_on_commit=False)
async with async_session() as session:
yield session
class TestGameModels:
"""Test game model creation and relationships."""
@pytest.mark.asyncio
async def test_create_game(self, db_session: AsyncSession):
"""Test creating a new game."""
game = MTGOnlineGame(
room_id=1,
host_id=100,
game_type="Commander",
state="WAITING",
max_players=4,
current_players=1,
)
db_session.add(game)
await db_session.flush()
assert game.id is not None
assert game.room_id == 1
assert game.host_id == 100
assert game.game_type == "Commander"
assert game.state == "WAITING"
@pytest.mark.asyncio
async def test_create_game_player(self, db_session: AsyncSession):
"""Test creating a game player."""
game = MTGOnlineGame(
room_id=1,
host_id=100,
game_type="Commander",
state="WAITING",
max_players=4,
current_players=1,
)
db_session.add(game)
await db_session.flush()
player = GamePlayer(
game_id=game.id,
user_id=100,
seat_number=1,
life_total=20,
is_ready=False,
is_host=True,
)
db_session.add(player)
await db_session.flush()
assert player.id is not None
assert player.game_id == game.id
assert player.user_id == 100
assert player.is_host is True
@pytest.mark.asyncio
async def test_game_player_relationship(self, db_session: AsyncSession):
"""Test game-player relationship."""
game = MTGOnlineGame(
room_id=1,
host_id=100,
game_type="Commander",
state="WAITING",
max_players=4,
current_players=1,
)
db_session.add(game)
await db_session.flush()
player1 = GamePlayer(
game_id=game.id,
user_id=100,
seat_number=1,
is_host=True,
)
player2 = GamePlayer(
game_id=game.id,
user_id=101,
seat_number=2,
is_host=False,
)
db_session.add_all([player1, player2])
await db_session.flush()
# Query game with players
stmt = select(MTGOnlineGame).where(MTGOnlineGame.id == game.id)
result = await db_session.execute(stmt)
game = result.scalar_one()
assert len(game.players) == 2
assert game.players[0].user_id == 100
assert game.players[1].user_id == 101
@pytest.mark.asyncio
async def test_game_history_creation(self, db_session: AsyncSession):
"""Test creating game history."""
game = MTGOnlineGame(
room_id=1,
host_id=100,
game_type="Commander",
state="FINISHED",
max_players=4,
current_players=2,
)
db_session.add(game)
await db_session.flush()
history = GameHistory(
game_id=game.id,
room_id=1,
host_id=100,
game_type="Commander",
winner_id=100,
duration_seconds=45 * 60,
)
db_session.add(history)
await db_session.flush()
assert history.id is not None
assert history.game_id == game.id
assert history.winner_id == 100
assert history.duration_seconds == 45 * 60
class TestGameQueries:
"""Test database queries for games."""
@pytest.mark.asyncio
async def test_list_games_by_state(self, db_session: AsyncSession):
"""Test listing games by state."""
# Create test games
game1 = MTGOnlineGame(room_id=1, host_id=100, game_type="Commander", state="WAITING")
game2 = MTGOnlineGame(room_id=1, host_id=101, game_type="Commander", state="WAITING")
game3 = MTGOnlineGame(room_id=1, host_id=102, game_type="Standard", state="IN_PROGRESS")
db_session.add_all([game1, game2, game3])
await db_session.flush()
# Query WAITING games
stmt = select(MTGOnlineGame).where(MTGOnlineGame.state == "WAITING")
result = await db_session.execute(stmt)
waiting_games = result.scalars().all()
assert len(waiting_games) == 2
@pytest.mark.asyncio
async def test_list_games_by_type(self, db_session: AsyncSession):
"""Test listing games by type."""
game1 = MTGOnlineGame(room_id=1, host_id=100, game_type="Commander", state="WAITING")
game2 = MTGOnlineGame(room_id=1, host_id=101, game_type="Standard", state="WAITING")
db_session.add_all([game1, game2])
await db_session.flush()
stmt = select(MTGOnlineGame).where(MTGOnlineGame.game_type == "Commander")
result = await db_session.execute(stmt)
commander_games = result.scalars().all()
assert len(commander_games) == 1
@pytest.mark.asyncio
async def test_get_game_by_id(self, db_session: AsyncSession):
"""Test getting a game by ID."""
game = MTGOnlineGame(room_id=1, host_id=100, game_type="Commander", state="WAITING")
db_session.add(game)
await db_session.flush()
stmt = select(MTGOnlineGame).where(MTGOnlineGame.id == game.id)
result = await db_session.execute(stmt)
fetched_game = result.scalar_one_or_none()
assert fetched_game is not None
assert fetched_game.id == game.id
assert fetched_game.game_type == "Commander"
@pytest.mark.asyncio
async def test_update_game_state(self, db_session: AsyncSession):
"""Test updating game state."""
game = MTGOnlineGame(room_id=1, host_id=100, game_type="Commander", state="WAITING")
db_session.add(game)
await db_session.flush()
game.state = "IN_PROGRESS"
game.started_at = datetime(2024, 1, 1, 0, 0, 0)
await db_session.flush()
stmt = select(MTGOnlineGame).where(MTGOnlineGame.id == game.id)
result = await db_session.execute(stmt)
updated_game = result.scalar_one()
assert updated_game.state == "IN_PROGRESS"
assert updated_game.started_at is not None
class TestGamePlayerQueries:
"""Test database queries for game players."""
@pytest.mark.asyncio
async def test_get_players_for_game(self, db_session: AsyncSession):
"""Test getting all players for a game."""
game = MTGOnlineGame(room_id=1, host_id=100, game_type="Commander", state="WAITING")
db_session.add(game)
await db_session.flush()
player1 = GamePlayer(game_id=game.id, user_id=100, seat_number=1, is_host=True)
player2 = GamePlayer(game_id=game.id, user_id=101, seat_number=2, is_host=False)
player3 = GamePlayer(game_id=game.id, user_id=102, seat_number=3, is_host=False)
db_session.add_all([player1, player2, player3])
await db_session.flush()
stmt = select(GamePlayer).where(GamePlayer.game_id == game.id)
result = await db_session.execute(stmt)
players = result.scalars().all()
assert len(players) == 3
@pytest.mark.asyncio
async def test_check_player_in_game(self, db_session: AsyncSession):
"""Test checking if user is in a game."""
game = MTGOnlineGame(room_id=1, host_id=100, game_type="Commander", state="WAITING")
db_session.add(game)
await db_session.flush()
player = GamePlayer(game_id=game.id, user_id=100, seat_number=1, is_host=True)
db_session.add(player)
await db_session.flush()
# Check if user 100 is in game
stmt = select(GamePlayer).where(
GamePlayer.game_id == game.id,
GamePlayer.user_id == 100,
)
result = await db_session.execute(stmt)
existing_player = result.scalar_one_or_none()
assert existing_player is not None
assert existing_player.user_id == 100
@pytest.mark.asyncio
async def test_update_player_ready_status(self, db_session: AsyncSession):
"""Test updating player ready status."""
game = MTGOnlineGame(room_id=1, host_id=100, game_type="Commander", state="WAITING")
db_session.add(game)
await db_session.flush()
player = GamePlayer(game_id=game.id, user_id=100, seat_number=1, is_ready=False)
db_session.add(player)
await db_session.flush()
player.is_ready = True
await db_session.flush()
stmt = select(GamePlayer).where(GamePlayer.id == player.id)
result = await db_session.execute(stmt)
updated_player = result.scalar_one()
assert updated_player.is_ready is True
@pytest.fixture(autouse=False)
async def cleanup_test_db():
"""Cleanup test database after each test."""
yield
import os
if os.path.exists("./test_games.db"):
os.remove("./test_games.db")