mud/tests/test_examine.py
Jared Miller 9534df8f9c
Add examine command for object inspection
Implements a global examine/ex command that shows detailed descriptions
of objects. Searches inventory first, then ground at player position.
Works with Things, Containers, and Mobs.
2026-02-11 21:47:33 -05:00

206 lines
5.4 KiB
Python

from unittest.mock import AsyncMock, MagicMock
import pytest
from mudlib.commands.examine import cmd_examine
from mudlib.container import Container
from mudlib.entity import Mob
from mudlib.player import Player
from mudlib.thing import Thing
from mudlib.zone import Zone
@pytest.fixture
def mock_writer():
writer = MagicMock()
writer.write = MagicMock()
writer.drain = AsyncMock()
return writer
@pytest.fixture
def mock_reader():
return MagicMock()
@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
def player(mock_reader, mock_writer, test_zone):
return Player(
name="TestPlayer",
x=5,
y=5,
reader=mock_reader,
writer=mock_writer,
location=test_zone,
)
@pytest.mark.asyncio
async def test_examine_no_args(player, mock_writer):
"""examine with no args prompts what to examine"""
await cmd_examine(player, "")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "Examine what?" in output
@pytest.mark.asyncio
async def test_examine_thing_on_ground_by_name(player, test_zone, mock_writer):
"""examine finds Thing on ground by name and shows description"""
_rock = Thing(
name="rock",
x=5,
y=5,
location=test_zone,
description="A smooth gray rock with moss on one side.",
)
await cmd_examine(player, "rock")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "A smooth gray rock with moss on one side." in output
@pytest.mark.asyncio
async def test_examine_thing_on_ground_by_alias(player, test_zone, mock_writer):
"""examine finds Thing on ground by alias"""
_rock = Thing(
name="rock",
x=5,
y=5,
location=test_zone,
aliases=["stone"],
description="A smooth gray rock.",
)
await cmd_examine(player, "stone")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "A smooth gray rock." in output
@pytest.mark.asyncio
async def test_examine_thing_in_inventory_by_name(player, test_zone, mock_writer):
"""examine finds Thing in inventory by name"""
_key = Thing(
name="key",
x=5,
y=5,
location=player,
description="A rusty iron key.",
)
await cmd_examine(player, "key")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "A rusty iron key." in output
@pytest.mark.asyncio
async def test_examine_inventory_before_ground(player, test_zone, mock_writer):
"""examine finds in inventory before ground"""
_ground_rock = Thing(
name="rock",
x=5,
y=5,
location=test_zone,
description="A rock on the ground.",
)
_inventory_rock = Thing(
name="rock",
x=5,
y=5,
location=player,
description="A rock in your pocket.",
)
await cmd_examine(player, "rock")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "A rock in your pocket." in output
assert "A rock on the ground." not in output
@pytest.mark.asyncio
async def test_examine_mob_at_position(player, test_zone, mock_writer):
"""examine finds Mob at same position and shows description"""
_goblin = Mob(
name="goblin",
x=5,
y=5,
location=test_zone,
description="A small, greenish creature with beady eyes.",
)
await cmd_examine(player, "goblin")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "A small, greenish creature with beady eyes." in output
@pytest.mark.asyncio
async def test_examine_not_found(player, mock_writer):
"""examine nonexistent object shows not found message"""
await cmd_examine(player, "flurb")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "You don't see that here." in output
@pytest.mark.asyncio
async def test_examine_thing_with_empty_description(player, test_zone, mock_writer):
"""examine thing with empty description shows default message"""
_rock = Thing(
name="rock",
x=5,
y=5,
location=test_zone,
description="",
)
await cmd_examine(player, "rock")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "You see nothing special." in output
@pytest.mark.asyncio
async def test_examine_container_shows_description(player, test_zone, mock_writer):
"""examine Container shows description"""
_chest = Container(
name="chest",
x=5,
y=5,
location=test_zone,
description="A sturdy wooden chest with brass hinges.",
closed=False,
)
await cmd_examine(player, "chest")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "A sturdy wooden chest with brass hinges." in output
@pytest.mark.asyncio
async def test_examine_alias_ex(player, test_zone, mock_writer):
"""ex alias works"""
_rock = Thing(
name="rock",
x=5,
y=5,
location=test_zone,
description="A smooth rock.",
)
# The command registration will handle the alias, but test function
await cmd_examine(player, "rock")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "A smooth rock." in output