"""Tests for login and registration flow.""" import os import tempfile import pytest from mudlib.server import handle_login from mudlib.store import account_exists, authenticate, init_db @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.mark.asyncio async def test_login_existing_account_correct_password(temp_db): """Login succeeds with correct password.""" from mudlib.store import create_account create_account("TestUser", "correct_password") # Mock I/O inputs = ["correct_password"] outputs = [] async def mock_write(msg: str): outputs.append(msg) async def mock_read(): if inputs: return inputs.pop(0) return None result = await handle_login("TestUser", mock_read, mock_write) assert result["success"] is True assert result["player_data"] is not None assert result["player_data"]["x"] == 0 assert result["player_data"]["y"] == 0 @pytest.mark.asyncio async def test_login_existing_account_wrong_password(temp_db): """Login fails with wrong password after max attempts.""" from mudlib.store import create_account create_account("TestUser", "correct_password") # Mock I/O - provide wrong password 3 times inputs = ["wrong1", "wrong2", "wrong3"] outputs = [] async def mock_write(msg: str): outputs.append(msg) async def mock_read(): if inputs: return inputs.pop(0) return None result = await handle_login("TestUser", mock_read, mock_write) assert result["success"] is False assert "Too many failed attempts" in "".join(outputs) @pytest.mark.asyncio async def test_login_existing_account_retry_success(temp_db): """Login succeeds after retrying wrong password.""" from mudlib.store import create_account create_account("TestUser", "correct_password") # Mock I/O - wrong password first, then correct inputs = ["wrong_password", "correct_password"] outputs = [] async def mock_write(msg: str): outputs.append(msg) async def mock_read(): if inputs: return inputs.pop(0) return None result = await handle_login("TestUser", mock_read, mock_write) assert result["success"] is True assert result["player_data"] is not None @pytest.mark.asyncio async def test_registration_new_account(temp_db): """Registration creates a new account.""" # Mock I/O - answer 'y' to create account, then provide password twice inputs = ["y", "newpassword", "newpassword"] outputs = [] async def mock_write(msg: str): outputs.append(msg) async def mock_read(): if inputs: return inputs.pop(0) return None result = await handle_login("NewUser", mock_read, mock_write) assert result["success"] is True assert account_exists("NewUser") assert authenticate("NewUser", "newpassword") @pytest.mark.asyncio async def test_registration_password_mismatch(temp_db): """Registration fails if passwords don't match.""" # Mock I/O - answer 'y', then mismatched passwords, then cancel inputs = ["y", "password1", "password2", "n"] outputs = [] async def mock_write(msg: str): outputs.append(msg) async def mock_read(): if inputs: return inputs.pop(0) return None result = await handle_login("NewUser", mock_read, mock_write) assert result["success"] is False assert not account_exists("NewUser") @pytest.mark.asyncio async def test_registration_declined(temp_db): """User declines to create account.""" # Mock I/O - answer 'n' to create account inputs = ["n"] outputs = [] async def mock_write(msg: str): outputs.append(msg) async def mock_read(): if inputs: return inputs.pop(0) return None result = await handle_login("NewUser", mock_read, mock_write) assert result["success"] is False assert not account_exists("NewUser")