220 lines
6.9 KiB
Python
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
|