mud/tests/test_inventory_persistence.py
Jared Miller 6081c90ad1
Add inventory persistence to player saves
Inventory saved as JSON list of thing template names in an inventory
column. Migration adds column to existing databases. load_player_data
returns inventory list, save_player serializes Thing names from contents.
2026-02-11 20:29:58 -05:00

152 lines
3.5 KiB
Python

"""Tests for inventory persistence."""
import json
import pytest
from mudlib.player import Player
from mudlib.store import (
create_account,
init_db,
load_player_data,
save_player,
)
from mudlib.thing import Thing
from mudlib.things import ThingTemplate, thing_templates
from mudlib.zone import Zone
@pytest.fixture
def db(tmp_path):
"""Initialize a temporary database."""
db_path = tmp_path / "test.db"
init_db(db_path)
return db_path
@pytest.fixture
def test_zone():
terrain = [["." for _ in range(10)] for _ in range(10)]
return Zone(
name="testzone",
width=10,
height=10,
terrain=terrain,
)
@pytest.fixture(autouse=True)
def register_templates():
"""Register test templates."""
thing_templates.clear()
thing_templates["rock"] = ThingTemplate(
name="rock",
description="a rock",
aliases=["stone"],
)
thing_templates["sword"] = ThingTemplate(
name="sword",
description="a sword",
)
yield
thing_templates.clear()
# --- save ---
def test_save_player_with_inventory(db, test_zone):
"""save_player persists inventory as JSON list of template names."""
import sqlite3
create_account("Alice", "pass123")
player = Player(
name="Alice",
x=5,
y=5,
location=test_zone,
)
Thing(name="rock", location=player)
Thing(name="sword", location=player)
save_player(player)
# Check raw DB value
conn = sqlite3.connect(str(db))
cursor = conn.cursor()
cursor.execute("SELECT inventory FROM accounts WHERE name = ?", ("Alice",))
row = cursor.fetchone()
conn.close()
assert row is not None
inventory = json.loads(row[0])
assert sorted(inventory) == ["rock", "sword"]
def test_save_player_empty_inventory(db, test_zone):
"""save_player stores empty list when no inventory."""
import sqlite3
create_account("Bob", "pass123")
player = Player(
name="Bob",
x=5,
y=5,
location=test_zone,
)
save_player(player)
conn = sqlite3.connect(str(db))
cursor = conn.cursor()
cursor.execute("SELECT inventory FROM accounts WHERE name = ?", ("Bob",))
row = cursor.fetchone()
conn.close()
assert row is not None
assert json.loads(row[0]) == []
# --- load ---
def test_load_player_data_includes_inventory(db):
"""load_player_data returns inventory list."""
import sqlite3
create_account("Alice", "pass123")
# Manually set inventory in DB
conn = sqlite3.connect(str(db))
cursor = conn.cursor()
cursor.execute(
"UPDATE accounts SET inventory = ? WHERE name = ?",
(json.dumps(["rock", "sword"]), "Alice"),
)
conn.commit()
conn.close()
data = load_player_data("Alice")
assert data is not None
assert sorted(data["inventory"]) == ["rock", "sword"]
def test_load_player_data_empty_inventory(db):
"""load_player_data returns empty list for no inventory."""
create_account("Bob", "pass123")
data = load_player_data("Bob")
assert data is not None
assert data["inventory"] == []
def test_load_player_data_migration_no_column(db):
"""Old DB without inventory column returns empty list."""
create_account("Charlie", "pass123")
# init_db already ran the migration adding the inventory column,
# so this just verifies a fresh account gets empty inventory
data = load_player_data("Charlie")
assert data is not None
assert data["inventory"] == []