- Update _find_container to use targeting module (prefix + ordinal) - Update cmd_put to use find_in_inventory directly - Add 'get all from <container>' support with portable item filtering - Add comprehensive tests for all container grammar features
143 lines
5.1 KiB
Python
143 lines
5.1 KiB
Python
"""Tests for container grammar with targeting and get-all support."""
|
|
|
|
import pytest
|
|
|
|
from mudlib.commands.containers import cmd_open, cmd_put
|
|
from mudlib.commands.things import cmd_get
|
|
from mudlib.container import Container
|
|
from mudlib.player import Player
|
|
from mudlib.thing import Thing
|
|
from mudlib.zone import Zone
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_from_container_basic(mock_writer):
|
|
"""Test basic 'get item from container' command."""
|
|
zone = Zone(name="test", width=10, height=10)
|
|
player = Player(name="test", x=5, y=5, location=zone, writer=mock_writer)
|
|
chest = Container(name="chest", x=5, y=5, location=zone)
|
|
sword = Thing(name="sword", location=chest)
|
|
|
|
await cmd_open(player, "chest")
|
|
await cmd_get(player, "sword from chest")
|
|
|
|
assert sword.location is player
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_from_container_prefix_match_item(mock_writer):
|
|
"""Test 'get sw from chest' — prefix match item in container."""
|
|
zone = Zone(name="test", width=10, height=10)
|
|
player = Player(name="test", x=5, y=5, location=zone, writer=mock_writer)
|
|
chest = Container(name="chest", x=5, y=5, location=zone)
|
|
sword = Thing(name="sword", location=chest)
|
|
|
|
await cmd_open(player, "chest")
|
|
await cmd_get(player, "sw from chest")
|
|
|
|
assert sword.location is player
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_from_container_ordinal(mock_writer):
|
|
"""Test 'get 2.sword from chest' — ordinal in container."""
|
|
zone = Zone(name="test", width=10, height=10)
|
|
player = Player(name="test", x=5, y=5, location=zone, writer=mock_writer)
|
|
chest = Container(name="chest", x=5, y=5, location=zone)
|
|
sword1 = Thing(name="sword", location=chest)
|
|
sword2 = Thing(name="sword", location=chest)
|
|
|
|
await cmd_open(player, "chest")
|
|
await cmd_get(player, "2.sword from chest")
|
|
|
|
assert sword2.location is player
|
|
assert sword1.location is chest
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_all_from_container(mock_writer):
|
|
"""Test 'get all from chest' — take everything."""
|
|
zone = Zone(name="test", width=10, height=10)
|
|
player = Player(name="test", x=5, y=5, location=zone, writer=mock_writer)
|
|
chest = Container(name="chest", x=5, y=5, location=zone)
|
|
sword = Thing(name="sword", location=chest)
|
|
shield = Thing(name="shield", location=chest)
|
|
helmet = Thing(name="helmet", location=chest)
|
|
|
|
await cmd_open(player, "chest")
|
|
await cmd_get(player, "all from chest")
|
|
|
|
assert sword.location is player
|
|
assert shield.location is player
|
|
assert helmet.location is player
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_all_from_empty_container(mock_writer):
|
|
"""Test 'get all from chest' when empty — no items moved."""
|
|
zone = Zone(name="test", width=10, height=10)
|
|
player = Player(name="test", x=5, y=5, location=zone, writer=mock_writer)
|
|
chest = Container(name="chest", x=5, y=5, location=zone)
|
|
|
|
await cmd_open(player, "chest")
|
|
await cmd_get(player, "all from chest")
|
|
|
|
# Verify no items were added to inventory
|
|
assert len([obj for obj in player.contents if isinstance(obj, Thing)]) == 0
|
|
assert chest.location is zone # chest should remain on ground
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_put_in_container_prefix_match(mock_writer):
|
|
"""Test 'put sw in chest' — prefix match in inventory for put."""
|
|
zone = Zone(name="test", width=10, height=10)
|
|
player = Player(name="test", x=5, y=5, location=zone, writer=mock_writer)
|
|
chest = Container(name="chest", x=5, y=5, location=zone)
|
|
sword = Thing(name="sword", location=player)
|
|
|
|
await cmd_open(player, "chest")
|
|
await cmd_put(player, "sw in chest")
|
|
|
|
assert sword.location is chest
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_open_container_prefix_match(mock_writer):
|
|
"""Test 'open che' — prefix match container name."""
|
|
zone = Zone(name="test", width=10, height=10)
|
|
player = Player(name="test", x=5, y=5, location=zone, writer=mock_writer)
|
|
chest = Container(name="chest", x=5, y=5, location=zone, closed=True)
|
|
|
|
await cmd_open(player, "che")
|
|
|
|
assert not chest.closed
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_from_container_prefix_match_container(mock_writer):
|
|
"""Test 'get sword from che' — prefix match container name."""
|
|
zone = Zone(name="test", width=10, height=10)
|
|
player = Player(name="test", x=5, y=5, location=zone, writer=mock_writer)
|
|
chest = Container(name="chest", x=5, y=5, location=zone)
|
|
sword = Thing(name="sword", location=chest)
|
|
|
|
await cmd_open(player, "chest")
|
|
await cmd_get(player, "sword from che")
|
|
|
|
assert sword.location is player
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_all_from_container_skips_non_portable(mock_writer):
|
|
"""Test 'get all from chest' skips items player can't carry."""
|
|
zone = Zone(name="test", width=10, height=10)
|
|
player = Player(name="test", x=5, y=5, location=zone, writer=mock_writer)
|
|
chest = Container(name="chest", x=5, y=5, location=zone)
|
|
sword = Thing(name="sword", location=chest, portable=True)
|
|
anvil = Thing(name="anvil", location=chest, portable=False)
|
|
|
|
await cmd_open(player, "chest")
|
|
await cmd_get(player, "all from chest")
|
|
|
|
assert sword.location is player
|
|
assert anvil.location is chest
|