Allows players to set custom descriptions for their home zones. Only works in the player's own home zone. Saves to TOML file.
151 lines
4.2 KiB
Python
151 lines
4.2 KiB
Python
"""Tests for the describe command."""
|
|
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
import pytest
|
|
|
|
from mudlib.commands.describe import cmd_describe
|
|
from mudlib.housing import init_housing
|
|
from mudlib.player import Player
|
|
from mudlib.zone import Zone
|
|
from mudlib.zones import register_zone, zone_registry
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _clean_registries():
|
|
saved = dict(zone_registry)
|
|
zone_registry.clear()
|
|
yield
|
|
zone_registry.clear()
|
|
zone_registry.update(saved)
|
|
|
|
|
|
@pytest.fixture
|
|
def _init_housing(tmp_path):
|
|
from mudlib.store import create_account, init_db
|
|
|
|
init_housing(tmp_path / "player_zones")
|
|
init_db(tmp_path / "test.db")
|
|
# Create accounts for test players
|
|
for name in ["alice", "bob", "charlie"]:
|
|
create_account(name, "testpass")
|
|
|
|
|
|
def _make_home_zone(player_name="alice"):
|
|
name = f"home:{player_name}"
|
|
terrain = []
|
|
for y in range(9):
|
|
row = []
|
|
for x in range(9):
|
|
if x == 0 or x == 8 or y == 0 or y == 8:
|
|
row.append("#")
|
|
else:
|
|
row.append(".")
|
|
terrain.append(row)
|
|
zone = Zone(
|
|
name=name,
|
|
description=f"{player_name}'s home",
|
|
width=9,
|
|
height=9,
|
|
terrain=terrain,
|
|
toroidal=False,
|
|
impassable={"#", "^", "~"},
|
|
spawn_x=4,
|
|
spawn_y=4,
|
|
safe=True,
|
|
)
|
|
register_zone(name, zone)
|
|
return zone
|
|
|
|
|
|
def _make_player(name="alice", zone=None, x=4, y=4):
|
|
mock_writer = MagicMock()
|
|
mock_writer.write = MagicMock()
|
|
mock_writer.drain = AsyncMock()
|
|
p = Player(name=name, location=zone, x=x, y=y, writer=mock_writer)
|
|
p.home_zone = f"home:{name}"
|
|
return p
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_describe_sets_description(_init_housing):
|
|
"""describe <text> sets zone.description."""
|
|
home = _make_home_zone("alice")
|
|
player = _make_player("alice", zone=home)
|
|
|
|
await cmd_describe(player, "a cozy cottage by the sea")
|
|
|
|
assert home.description == "a cozy cottage by the sea"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_describe_not_in_home_zone(_init_housing):
|
|
"""describe fails if not in player's own home zone."""
|
|
_make_home_zone("alice")
|
|
other_zone = Zone(
|
|
name="overworld",
|
|
description="The world",
|
|
width=20,
|
|
height=20,
|
|
terrain=[["." for _ in range(20)] for _ in range(20)],
|
|
toroidal=True,
|
|
)
|
|
register_zone("overworld", other_zone)
|
|
player = _make_player("alice", zone=other_zone)
|
|
|
|
await cmd_describe(player, "trying to describe the overworld")
|
|
|
|
# Should show error message
|
|
assert player.writer.write.called
|
|
output = "".join(c[0][0] for c in player.writer.write.call_args_list)
|
|
assert "only" in output.lower() and "home" in output.lower()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_describe_no_args_shows_current(_init_housing):
|
|
"""describe with no args shows current description."""
|
|
home = _make_home_zone("alice")
|
|
home.description = "a warm and welcoming place"
|
|
player = _make_player("alice", zone=home)
|
|
|
|
await cmd_describe(player, "")
|
|
|
|
assert player.writer.write.called
|
|
output = "".join(c[0][0] for c in player.writer.write.call_args_list)
|
|
assert "a warm and welcoming place" in output
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_describe_saves_zone(_init_housing):
|
|
"""describe saves the zone to disk."""
|
|
import tomllib
|
|
|
|
from mudlib.housing import _zone_path
|
|
|
|
home = _make_home_zone("alice")
|
|
player = _make_player("alice", zone=home)
|
|
|
|
await cmd_describe(player, "a newly described home")
|
|
|
|
# Check TOML file was saved
|
|
zone_path = _zone_path("alice")
|
|
assert zone_path.exists()
|
|
|
|
with open(zone_path, "rb") as f:
|
|
data = tomllib.load(f)
|
|
|
|
assert data["description"] == "a newly described home"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_describe_multiword(_init_housing):
|
|
"""describe handles multiword descriptions."""
|
|
home = _make_home_zone("bob")
|
|
player = _make_player("bob", zone=home)
|
|
|
|
await cmd_describe(player, "a cozy cottage with warm lighting")
|
|
|
|
assert home.description == "a cozy cottage with warm lighting"
|
|
assert player.writer.write.called
|
|
output = "".join(c[0][0] for c in player.writer.write.call_args_list)
|
|
assert "description" in output.lower() or "set" in output.lower()
|