"""Tests for get and drop commands.""" import pytest from mudlib.commands import _registry from mudlib.entity import Entity from mudlib.player import Player from mudlib.thing import Thing from mudlib.zone import Zone @pytest.fixture def test_zone(): terrain = [["." for _ in range(10)] for _ in range(10)] return Zone( name="testzone", width=10, height=10, toroidal=True, terrain=terrain, ) @pytest.fixture def player(mock_reader, mock_writer, test_zone): p = Player( name="TestPlayer", x=5, y=5, reader=mock_reader, writer=mock_writer, location=test_zone, ) return p # --- Object.move_to --- def test_move_to_updates_location(): """move_to changes the object's location pointer.""" terrain = [["." for _ in range(10)] for _ in range(10)] zone = Zone(name="test", width=10, height=10, terrain=terrain) entity = Entity(name="player", location=zone, x=5, y=5) rock = Thing(name="rock", location=zone, x=5, y=5) rock.move_to(entity) assert rock.location is entity def test_move_to_removes_from_old_contents(): """move_to removes object from old location's contents.""" terrain = [["." for _ in range(10)] for _ in range(10)] zone = Zone(name="test", width=10, height=10, terrain=terrain) entity = Entity(name="player", location=zone, x=5, y=5) rock = Thing(name="rock", location=zone, x=5, y=5) rock.move_to(entity) assert rock not in zone.contents def test_move_to_adds_to_new_contents(): """move_to adds object to new location's contents.""" terrain = [["." for _ in range(10)] for _ in range(10)] zone = Zone(name="test", width=10, height=10, terrain=terrain) entity = Entity(name="player", location=zone, x=5, y=5) rock = Thing(name="rock", location=zone, x=5, y=5) rock.move_to(entity) assert rock in entity.contents def test_move_to_from_none(): """move_to works from location=None (template to world).""" terrain = [["." for _ in range(10)] for _ in range(10)] zone = Zone(name="test", width=10, height=10, terrain=terrain) rock = Thing(name="rock") rock.move_to(zone, x=3, y=7) assert rock.location is zone assert rock.x == 3 assert rock.y == 7 assert rock in zone.contents def test_move_to_sets_coordinates(): """move_to can set x/y coordinates.""" terrain = [["." for _ in range(10)] for _ in range(10)] zone = Zone(name="test", width=10, height=10, terrain=terrain) rock = Thing(name="rock", location=zone, x=1, y=1) entity = Entity(name="player", location=zone, x=5, y=5) rock.move_to(entity) # When moving to inventory, coordinates should be cleared assert rock.x is None assert rock.y is None def test_move_to_zone_sets_coordinates(): """move_to a zone sets x/y from args.""" terrain = [["." for _ in range(10)] for _ in range(10)] zone = Zone(name="test", width=10, height=10, terrain=terrain) entity = Entity(name="player", location=zone, x=5, y=5) rock = Thing(name="rock", location=entity) rock.move_to(zone, x=3, y=7) assert rock.x == 3 assert rock.y == 7 # --- cmd_get --- @pytest.mark.asyncio async def test_get_picks_up_thing(player, test_zone): """get moves a thing from zone to player inventory.""" from mudlib.commands.things import cmd_get rock = Thing(name="rock", location=test_zone, x=5, y=5) await cmd_get(player, "rock") assert rock.location is player assert rock in player.contents assert rock not in test_zone.contents @pytest.mark.asyncio async def test_get_sends_confirmation(player, test_zone, mock_writer): """get sends feedback to the player.""" from mudlib.commands.things import cmd_get Thing(name="rock", location=test_zone, x=5, y=5) await cmd_get(player, "rock") output = mock_writer.write.call_args_list[-1][0][0] assert "rock" in output.lower() @pytest.mark.asyncio async def test_get_nothing_there(player, test_zone, mock_writer): """get with no matching item gives feedback.""" from mudlib.commands.things import cmd_get await cmd_get(player, "sword") output = mock_writer.write.call_args_list[-1][0][0] assert "don't see" in output.lower() or "nothing" in output.lower() @pytest.mark.asyncio async def test_get_non_portable(player, test_zone, mock_writer): """get rejects non-portable things.""" from mudlib.commands.things import cmd_get fountain = Thing( name="fountain", location=test_zone, x=5, y=5, portable=False, ) await cmd_get(player, "fountain") # Fountain should still be in zone, not in player assert fountain.location is test_zone assert fountain not in player.contents output = mock_writer.write.call_args_list[-1][0][0] assert "can't" in output.lower() @pytest.mark.asyncio async def test_get_no_args(player, mock_writer): """get with no arguments gives usage hint.""" from mudlib.commands.things import cmd_get await cmd_get(player, "") output = mock_writer.write.call_args_list[-1][0][0] assert "get what" in output.lower() or "what" in output.lower() @pytest.mark.asyncio async def test_get_matches_aliases(player, test_zone): """get matches thing aliases.""" from mudlib.commands.things import cmd_get can = Thing( name="pepsi can", aliases=["can", "pepsi"], location=test_zone, x=5, y=5, ) await cmd_get(player, "pepsi") assert can.location is player # --- cmd_drop --- @pytest.mark.asyncio async def test_drop_puts_thing_on_ground(player, test_zone): """drop moves a thing from inventory to zone at player's position.""" from mudlib.commands.things import cmd_drop rock = Thing(name="rock", location=player) await cmd_drop(player, "rock") assert rock.location is test_zone assert rock.x == player.x assert rock.y == player.y assert rock in test_zone.contents assert rock not in player.contents @pytest.mark.asyncio async def test_drop_sends_confirmation(player, test_zone, mock_writer): """drop sends feedback to the player.""" from mudlib.commands.things import cmd_drop Thing(name="rock", location=player) await cmd_drop(player, "rock") output = mock_writer.write.call_args_list[-1][0][0] assert "rock" in output.lower() @pytest.mark.asyncio async def test_drop_not_carrying(player, mock_writer): """drop with item not in inventory gives feedback.""" from mudlib.commands.things import cmd_drop await cmd_drop(player, "sword") output = mock_writer.write.call_args_list[-1][0][0] assert "not carrying" in output.lower() or "don't have" in output.lower() @pytest.mark.asyncio async def test_drop_no_args(player, mock_writer): """drop with no arguments gives usage hint.""" from mudlib.commands.things import cmd_drop await cmd_drop(player, "") output = mock_writer.write.call_args_list[-1][0][0] assert "drop what" in output.lower() or "what" in output.lower() @pytest.mark.asyncio async def test_drop_requires_zone(player, mock_writer): """drop without a zone location gives error.""" from mudlib.commands.things import cmd_drop player.location = None Thing(name="rock", location=player) await cmd_drop(player, "rock") output = mock_writer.write.call_args_list[-1][0][0] assert "nowhere" in output.lower() or "can't" in output.lower() @pytest.mark.asyncio async def test_drop_matches_aliases(player, test_zone): """drop matches thing aliases.""" from mudlib.commands.things import cmd_drop can = Thing( name="pepsi can", aliases=["can", "pepsi"], location=player, ) await cmd_drop(player, "can") assert can.location is test_zone # --- command registration --- def test_get_command_registered(): """get command is registered.""" import mudlib.commands.things # noqa: F401 assert "get" in _registry def test_drop_command_registered(): """drop command is registered.""" import mudlib.commands.things # noqa: F401 assert "drop" in _registry