"""Tests for the spawn command.""" from unittest.mock import AsyncMock, MagicMock import pytest from mudlib.commands.spawn import cmd_spawn from mudlib.mobs import MobTemplate, mob_templates, mobs from mudlib.player import Player, players from mudlib.zone import Zone @pytest.fixture(autouse=True) def clear_state(): """Clear mobs, templates, and players.""" mobs.clear() mob_templates.clear() players.clear() yield mobs.clear() mob_templates.clear() players.clear() @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(): """Create a test zone for spawning.""" terrain = [["." for _ in range(256)] for _ in range(256)] zone = Zone( name="testzone", width=256, height=256, toroidal=True, terrain=terrain, impassable=set(), ) return zone @pytest.fixture def player(mock_reader, mock_writer, test_zone): p = Player(name="Goku", x=10, y=20, reader=mock_reader, writer=mock_writer) p.location = test_zone test_zone._contents.append(p) players[p.name] = p return p @pytest.fixture def goblin_template(): t = MobTemplate( name="goblin", description="a snarling goblin", pl=50.0, stamina=40.0, max_stamina=40.0, moves=["punch left"], ) mob_templates["goblin"] = t return t @pytest.mark.asyncio async def test_spawn_valid_mob(player, goblin_template): """Spawn creates a mob at the player's position.""" await cmd_spawn(player, "goblin") assert len(mobs) == 1 mob = mobs[0] assert mob.name == "goblin" assert mob.x == player.x assert mob.y == player.y messages = [call[0][0] for call in player.writer.write.call_args_list] assert any("goblin" in msg.lower() and "appears" in msg.lower() for msg in messages) @pytest.mark.asyncio async def test_spawn_invalid_type(player, goblin_template): """Spawn with unknown type shows available mobs.""" await cmd_spawn(player, "dragon") assert len(mobs) == 0 messages = [call[0][0] for call in player.writer.write.call_args_list] assert any("unknown" in msg.lower() for msg in messages) assert any("goblin" in msg.lower() for msg in messages) @pytest.mark.asyncio async def test_spawn_no_args(player, goblin_template): """Spawn with no args shows usage.""" await cmd_spawn(player, "") assert len(mobs) == 0 messages = [call[0][0] for call in player.writer.write.call_args_list] assert any("usage" in msg.lower() for msg in messages)