Adds login/registration prompts on connection, database initialization on startup, and periodic auto-save every 5 minutes in the game loop. Player state is now tied to authenticated accounts.
164 lines
4.1 KiB
Python
164 lines
4.1 KiB
Python
"""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")
|