"""Tests for look command target resolution.""" import pytest from mudlib.commands.look import cmd_look from mudlib.entity import Mob from mudlib.player import Player from mudlib.thing import Thing from mudlib.zone import Zone @pytest.fixture def zone(): """Create a test zone.""" terrain = [["." for _ in range(100)] for _ in range(100)] return Zone( name="test", description="Test Zone", width=100, height=100, toroidal=False, terrain=terrain, ) @pytest.fixture def mock_writer(): """Create a mock writer that captures output.""" from unittest.mock import MagicMock class MockWriter: def __init__(self): self.output = [] # Mock telnet options self.local_option = MagicMock() self.remote_option = MagicMock() self.local_option.enabled = MagicMock(return_value=False) self.remote_option.enabled = MagicMock(return_value=False) def write(self, data): self.output.append(data) async def drain(self): pass def get_output(self): return "".join(self.output) return MockWriter() @pytest.fixture def player(zone, mock_writer): """Create a test player.""" p = Player( name="TestPlayer", location=zone, x=50, y=50, writer=mock_writer, ) return p @pytest.mark.asyncio async def test_look_finds_mob_by_exact_name(player, zone, mock_writer): """look goblin finds mob with exact name.""" _mob = Mob(name="goblin", location=zone, x=50, y=50) await cmd_look(player, "goblin") output = mock_writer.get_output() assert "goblin" in output.lower() @pytest.mark.asyncio async def test_look_finds_mob_by_prefix(player, zone, mock_writer): """look gob prefix matches goblin.""" _mob = Mob(name="goblin", location=zone, x=50, y=50) await cmd_look(player, "gob") output = mock_writer.get_output() assert "goblin" in output.lower() @pytest.mark.asyncio async def test_look_finds_second_mob_with_ordinal(player, zone, mock_writer): """look 2.goblin finds second goblin.""" _mob1 = Mob(name="goblin", location=zone, x=50, y=50) _mob2 = Mob(name="goblin", location=zone, x=50, y=50) await cmd_look(player, "2.goblin") output = mock_writer.get_output() # Should find the second goblin assert "goblin" in output.lower() @pytest.mark.asyncio async def test_look_finds_thing_on_ground(player, zone, mock_writer): """look sword finds thing on ground and shows description.""" _sword = Thing( name="sword", description="A sharp blade.", location=zone, x=50, y=50, ) await cmd_look(player, "sword") output = mock_writer.get_output() assert "A sharp blade." in output @pytest.mark.asyncio async def test_look_shows_error_for_nonexistent(player, zone, mock_writer): """look nonexistent shows 'You don't see that here.'""" await cmd_look(player, "nonexistent") output = mock_writer.get_output() assert "You don't see that here." in output @pytest.mark.asyncio async def test_look_prioritizes_entity_over_thing(player, zone, mock_writer): """look target finds entity before thing with same name.""" _mob = Mob(name="target", location=zone, x=50, y=50) _thing = Thing( name="target", description="A thing.", location=zone, x=50, y=50, ) await cmd_look(player, "target") output = mock_writer.get_output() # Should show entity info (name/posture), not thing description assert "target" in output.lower() # Should not show thing description assert "A thing." not in output @pytest.mark.asyncio async def test_look_skips_dead_mobs(player, zone, mock_writer): """look goblin skips dead mobs.""" _mob = Mob(name="goblin", location=zone, x=50, y=50) _mob.alive = False await cmd_look(player, "goblin") output = mock_writer.get_output() assert "You don't see that here." in output @pytest.mark.asyncio async def test_look_skips_self(player, zone, mock_writer): """look TestPlayer doesn't target the player themselves.""" await cmd_look(player, "TestPlayer") output = mock_writer.get_output() assert "You don't see that here." in output @pytest.mark.asyncio async def test_look_finds_thing_in_inventory(player, zone, mock_writer): """look sword finds thing in inventory when not on ground.""" _sword = Thing( name="sword", description="A sharp blade.", location=player, ) await cmd_look(player, "sword") output = mock_writer.get_output() assert "A sharp blade." in output @pytest.mark.asyncio async def test_look_finds_second_thing_with_ordinal(player, zone, mock_writer): """look 2.sword finds second sword on ground.""" _sword1 = Thing( name="sword", description="A rusty blade.", location=zone, x=50, y=50, ) _sword2 = Thing( name="sword", description="A sharp blade.", location=zone, x=50, y=50, ) await cmd_look(player, "2.sword") output = mock_writer.get_output() # Should show the second sword's description assert "A sharp blade." in output # Should not show the first sword's description assert "A rusty blade." not in output