mud/tests/test_container.py

220 lines
6.9 KiB
Python

"""Tests for the Container class."""
import pytest
from mudlib.container import Container
from mudlib.object import Object
from mudlib.player import Player
from mudlib.thing import Thing
from mudlib.zone import Zone
# --- fixtures ---
@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
# --- construction ---
# --- can_accept ---
def test_container_accepts_thing_when_open():
"""Container accepts Things when open and has capacity."""
c = Container(name="chest")
sword = Thing(name="sword")
assert c.can_accept(sword) is True
def test_container_rejects_when_closed():
"""Container rejects Things when closed."""
c = Container(name="chest", closed=True)
sword = Thing(name="sword")
assert c.can_accept(sword) is False
def test_container_rejects_when_at_capacity():
"""Container rejects Things when at capacity."""
c = Container(name="pouch", capacity=2)
# Add two items
Thing(name="rock1", location=c)
Thing(name="rock2", location=c)
# Third should be rejected
rock3 = Thing(name="rock3")
assert c.can_accept(rock3) is False
def test_container_accepts_when_below_capacity():
"""Container accepts Things when below capacity."""
c = Container(name="pouch", capacity=2)
Thing(name="rock1", location=c)
# Second item should be accepted
rock2 = Thing(name="rock2")
assert c.can_accept(rock2) is True
def test_container_rejects_non_thing():
"""Container rejects objects that aren't Things."""
c = Container(name="chest")
other = Object(name="abstract")
assert c.can_accept(other) is False
def test_container_locked_is_just_flag():
"""Locked flag is stored but doesn't affect can_accept (used by commands)."""
c = Container(name="chest", locked=True, closed=False)
sword = Thing(name="sword")
# can_accept doesn't check locked (commands will check it separately)
# This test documents current behavior — locked is for command layer
assert c.locked is True
# can_accept only checks closed and capacity
assert c.can_accept(sword) is True
# --- integration with zones ---
def test_container_in_zone():
"""Container can be placed in a zone with coordinates."""
terrain = [["." for _ in range(10)] for _ in range(10)]
zone = Zone(name="test", width=10, height=10, terrain=terrain)
chest = Container(name="chest", location=zone, x=5, y=5)
assert chest.location is zone
assert chest.x == 5
assert chest.y == 5
assert chest in zone.contents
def test_container_with_contents():
"""Container can hold Things."""
chest = Container(name="chest")
sword = Thing(name="sword", location=chest)
gem = Thing(name="gem", location=chest)
assert sword in chest.contents
assert gem in chest.contents
assert len(chest.contents) == 2
# --- look command container display ---
@pytest.mark.asyncio
async def test_look_shows_closed_container(player, test_zone, mock_writer):
"""look shows closed containers with (closed) suffix."""
from mudlib.commands.look import cmd_look
Container(name="chest", location=test_zone, x=5, y=5, closed=True)
await cmd_look(player, "")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "chest (closed)" in output
@pytest.mark.asyncio
async def test_look_shows_open_empty_container(player, test_zone, mock_writer):
"""look shows open empty containers with (open, empty) suffix."""
from mudlib.commands.look import cmd_look
Container(name="chest", location=test_zone, x=5, y=5, closed=False)
await cmd_look(player, "")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "chest (open, empty)" in output
@pytest.mark.asyncio
async def test_look_shows_open_container_with_contents(player, test_zone, mock_writer):
"""look shows open containers with their contents."""
from mudlib.commands.look import cmd_look
chest = Container(name="chest", location=test_zone, x=5, y=5, closed=False)
Thing(name="rock", location=chest)
Thing(name="coin", location=chest)
await cmd_look(player, "")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "chest (open, containing: rock, coin)" in output
@pytest.mark.asyncio
async def test_look_shows_regular_things_unchanged(player, test_zone, mock_writer):
"""look shows regular Things without container suffixes."""
from mudlib.commands.look import cmd_look
Thing(name="rock", location=test_zone, x=5, y=5)
await cmd_look(player, "")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "On the ground: rock" in output
assert "(closed)" not in output
assert "(open" not in output
# --- inventory command container display ---
@pytest.mark.asyncio
async def test_inventory_shows_closed_container(player, mock_writer):
"""inventory shows closed containers with (closed) suffix."""
from mudlib.commands.things import cmd_inventory
Container(name="sack", location=player, closed=True)
await cmd_inventory(player, "")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "sack (closed)" in output
@pytest.mark.asyncio
async def test_inventory_shows_open_empty_container(player, mock_writer):
"""inventory shows open empty containers with (open, empty) suffix."""
from mudlib.commands.things import cmd_inventory
Container(name="sack", location=player, closed=False)
await cmd_inventory(player, "")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "sack (open, empty)" in output
@pytest.mark.asyncio
async def test_inventory_shows_container_with_contents(player, mock_writer):
"""inventory shows open containers with their contents."""
from mudlib.commands.things import cmd_inventory
sack = Container(name="sack", location=player, closed=False)
Thing(name="rock", location=sack)
Thing(name="gem", location=sack)
await cmd_inventory(player, "")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert "sack (open, containing: rock, gem)" in output
@pytest.mark.asyncio
async def test_inventory_shows_regular_things_unchanged(player, mock_writer):
"""inventory shows regular Things without container suffixes."""
from mudlib.commands.things import cmd_inventory
Thing(name="rock", location=player)
await cmd_inventory(player, "")
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
assert " rock\r\n" in output
assert "(closed)" not in output
assert "(open" not in output