"""Tests for help command showing unlock status for combat moves.""" from unittest.mock import patch import pytest from mudlib.combat.moves import CombatMove, UnlockCondition from mudlib.commands import dispatch, help # noqa: F401 from mudlib.player import Player, players @pytest.fixture(autouse=True) def clear_state(): """Clear players before and after each test.""" players.clear() yield players.clear() @pytest.fixture def player(mock_writer): return Player(name="Test", writer=mock_writer) @pytest.fixture def mock_move_kill_count(): """Mock move with kill_count unlock condition.""" return CombatMove( name="roundhouse", move_type="attack", stamina_cost=30.0, hit_time_ms=850, aliases=["rh"], description="A powerful spinning kick", damage_pct=0.35, unlock_condition=UnlockCondition(type="kill_count", threshold=5), ) @pytest.fixture def mock_move_mob_kills(): """Mock move with mob_kills unlock condition.""" return CombatMove( name="goblin slayer", move_type="attack", stamina_cost=25.0, hit_time_ms=800, description="Specialized technique against goblins", damage_pct=0.40, unlock_condition=UnlockCondition( type="mob_kills", threshold=3, mob_name="goblin" ), ) @pytest.fixture def mock_move_no_unlock(): """Mock move without unlock condition.""" return CombatMove( name="jab", move_type="attack", stamina_cost=10.0, hit_time_ms=600, description="A quick straight punch", damage_pct=0.15, ) @pytest.mark.asyncio async def test_help_locked_move_shows_kill_count_requirement( player, mock_move_kill_count ): """Help for locked move shows kill count requirement.""" player.unlocked_moves = set() moves = {"roundhouse": mock_move_kill_count, "rh": mock_move_kill_count} with patch("mudlib.combat.commands.combat_moves", moves): await dispatch(player, "help roundhouse") output = "".join([call[0][0] for call in player.writer.write.call_args_list]) assert "LOCKED" in output or "Locked" in output assert "5" in output assert "enemies" in output.lower() or "kills" in output.lower() @pytest.mark.asyncio async def test_help_locked_move_shows_mob_kills_requirement( player, mock_move_mob_kills ): """Help for locked move shows mob-specific kill requirement.""" player.unlocked_moves = set() moves = {"goblin slayer": mock_move_mob_kills} with patch("mudlib.combat.commands.combat_moves", moves): await dispatch(player, "help goblin slayer") output = "".join([call[0][0] for call in player.writer.write.call_args_list]) assert "LOCKED" in output or "Locked" in output assert "3" in output assert "goblin" in output.lower() @pytest.mark.asyncio async def test_help_unlocked_move_no_lock_notice(player, mock_move_kill_count): """Help for unlocked move shows normal help without lock notice.""" # Add move to unlocked_moves player.unlocked_moves = {"roundhouse"} moves = {"roundhouse": mock_move_kill_count, "rh": mock_move_kill_count} with patch("mudlib.combat.commands.combat_moves", moves): await dispatch(player, "help roundhouse") output = "".join([call[0][0] for call in player.writer.write.call_args_list]) assert "LOCKED" not in output and "Locked" not in output assert "roundhouse" in output assert "A powerful spinning kick" in output @pytest.mark.asyncio async def test_help_move_without_unlock_condition(player, mock_move_no_unlock): """Help for move without unlock condition shows normal help.""" player.unlocked_moves = set() with patch("mudlib.combat.commands.combat_moves", {"jab": mock_move_no_unlock}): await dispatch(player, "help jab") output = "".join([call[0][0] for call in player.writer.write.call_args_list]) assert "LOCKED" not in output and "Locked" not in output assert "jab" in output assert "A quick straight punch" in output @pytest.mark.asyncio async def test_help_locked_move_via_alias(player, mock_move_kill_count): """Help via alias for locked move shows unlock requirement.""" player.unlocked_moves = set() moves = {"roundhouse": mock_move_kill_count, "rh": mock_move_kill_count} with patch("mudlib.combat.commands.combat_moves", moves): await dispatch(player, "help rh") output = "".join([call[0][0] for call in player.writer.write.call_args_list]) assert "LOCKED" in output or "Locked" in output assert "5" in output