"""Tests for persistence behavior (save on quit/disconnect).""" import os import tempfile from unittest.mock import AsyncMock, MagicMock import pytest from mudlib.commands.quit import cmd_quit from mudlib.player import Player, players from mudlib.store import create_account, init_db, load_player_data, save_player @pytest.fixture def temp_db(): """Create a temporary database for testing.""" with tempfile.NamedTemporaryFile(delete=False, suffix=".db") as f: db_path = f.name init_db(db_path) yield db_path # Cleanup os.unlink(db_path) @pytest.fixture def mock_writer(): writer = MagicMock() writer.write = MagicMock() writer.drain = AsyncMock() writer.close = MagicMock() writer.is_closing = MagicMock(return_value=False) return writer @pytest.fixture def mock_reader(): return MagicMock() @pytest.mark.asyncio async def test_quit_saves_player_state(temp_db, mock_reader, mock_writer): """Quit command saves player state before disconnecting.""" # Create an account create_account("TestPlayer", "password") # Create player with modified state player = Player( name="TestPlayer", x=42, y=17, pl=85.0, stamina=60.0, max_stamina=120.0, flying=True, reader=mock_reader, writer=mock_writer, ) # Add to player registry players["TestPlayer"] = player # Execute quit command await cmd_quit(player, "") # Verify player was saved data = load_player_data("TestPlayer") assert data is not None assert data["x"] == 42 assert data["y"] == 17 assert data["pl"] == 85.0 assert data["stamina"] == 60.0 assert data["max_stamina"] == 120.0 assert data["flying"] is True # Verify player was removed from registry assert "TestPlayer" not in players @pytest.mark.asyncio async def test_save_multiple_times(temp_db, mock_reader, mock_writer): """Player state can be saved multiple times (updates).""" create_account("TestPlayer", "password") player = Player( name="TestPlayer", x=10, y=20, reader=mock_reader, writer=mock_writer, ) # Save initial state players["TestPlayer"] = player await cmd_quit(player, "") # Verify initial save data = load_player_data("TestPlayer") assert data is not None assert data["x"] == 10 assert data["y"] == 20 # Create new player instance with different position player2 = Player( name="TestPlayer", x=50, y=60, reader=mock_reader, writer=mock_writer, ) # Save again players["TestPlayer"] = player2 await cmd_quit(player2, "") # Verify updated state data = load_player_data("TestPlayer") assert data is not None assert data["x"] == 50 assert data["y"] == 60 @pytest.mark.asyncio async def test_autosave_persists_player_changes(temp_db, mock_reader, mock_writer): """Auto-save persists player state changes during gameplay.""" create_account("TestPlayer", "password") # Create player player = Player( name="TestPlayer", x=10, y=20, pl=100.0, reader=mock_reader, writer=mock_writer, ) # Simulate player moving and taking damage player.x = 25 player.y = 35 player.pl = 75.0 # Manually trigger save (simulating auto-save) save_player(player) # Verify state was saved data = load_player_data("TestPlayer") assert data is not None assert data["x"] == 25 assert data["y"] == 35 assert data["pl"] == 75.0