"""Tests for the store (persistence) module.""" import os import tempfile from pathlib import Path import pytest from mudlib.player import Player from mudlib.store import ( account_exists, authenticate, 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) def test_init_db_creates_file(temp_db): """init_db creates the database file.""" assert Path(temp_db).exists() def test_create_account_success(temp_db): """create_account creates a new account.""" assert create_account("Alice", "password123") assert account_exists("Alice") def test_create_account_case_insensitive(temp_db): """Account names are case-insensitive.""" create_account("Bob", "password123") assert account_exists("bob") assert account_exists("BOB") assert account_exists("Bob") def test_create_account_duplicate_fails(temp_db): """create_account fails if name is already taken.""" assert create_account("Charlie", "password123") assert not create_account("Charlie", "different_password") assert not create_account("charlie", "different_password") # case insensitive def test_authenticate_success(temp_db): """authenticate returns True for correct password.""" create_account("Dave", "correct_password") assert authenticate("Dave", "correct_password") def test_authenticate_case_insensitive_name(temp_db): """authenticate works with case-insensitive names.""" create_account("Eve", "password123") assert authenticate("eve", "password123") assert authenticate("EVE", "password123") def test_authenticate_wrong_password(temp_db): """authenticate returns False for wrong password.""" create_account("Frank", "correct_password") assert not authenticate("Frank", "wrong_password") def test_authenticate_nonexistent_account(temp_db): """authenticate returns False for nonexistent account.""" assert not authenticate("Ghost", "any_password") def test_save_and_load_player_data(temp_db): """save_player and load_player_data persist player state.""" # Create account first create_account("Grace", "password123") # Create a player with non-default values player = Player( name="Grace", x=42, y=17, pl=85.5, stamina=60.0, max_stamina=120.0, flying=True, ) # Save and load save_player(player) data = load_player_data("Grace") assert data is not None assert data["x"] == 42 assert data["y"] == 17 assert data["pl"] == 85.5 assert data["stamina"] == 60.0 assert data["max_stamina"] == 120.0 assert data["flying"] is True def test_load_player_data_case_insensitive(temp_db): """load_player_data works with case-insensitive names.""" create_account("Henry", "password123") player = Player(name="Henry", x=10, y=20) save_player(player) data_lower = load_player_data("henry") data_upper = load_player_data("HENRY") assert data_lower is not None assert data_upper is not None assert data_lower["x"] == 10 assert data_upper["x"] == 10 def test_load_player_data_nonexistent(temp_db): """load_player_data returns None for nonexistent account.""" assert load_player_data("Nobody") is None def test_save_player_updates_existing(temp_db): """save_player updates existing player data.""" create_account("Iris", "password123") # First save player = Player(name="Iris", x=10, y=20, pl=100.0) save_player(player) # Update and save again player.x = 50 player.y = 60 player.pl = 75.0 save_player(player) # Load and verify data = load_player_data("Iris") assert data is not None assert data["x"] == 50 assert data["y"] == 60 assert data["pl"] == 75.0 def test_default_values(temp_db): """New accounts have default values.""" create_account("Jack", "password123") data = load_player_data("Jack") assert data is not None assert data["x"] == 0 assert data["y"] == 0 assert data["pl"] == 100.0 assert data["stamina"] == 100.0 assert data["max_stamina"] == 100.0 assert data["flying"] is False def test_password_hashing_different_salts(temp_db): """Different accounts with same password have different hashes.""" create_account("Kate", "same_password") create_account("Leo", "same_password") # Both should authenticate assert authenticate("Kate", "same_password") assert authenticate("Leo", "same_password") # This just verifies the API works correctly - we can't easily check # the hashes are different without exposing internal details