diff --git a/tests/test_portal.py b/tests/test_portal.py index 05d9d81..7f6063b 100644 --- a/tests/test_portal.py +++ b/tests/test_portal.py @@ -1,9 +1,73 @@ """Tests for the Portal class.""" +import pytest + from mudlib.object import Object +from mudlib.player import Player from mudlib.portal import Portal from mudlib.thing import Thing from mudlib.zone import Zone +from mudlib.zones import register_zone, zone_registry + +# --- 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 zone_a(): + terrain = [["." for _ in range(10)] for _ in range(10)] + return Zone( + name="zone_a", + width=10, + height=10, + toroidal=True, + terrain=terrain, + ) + + +@pytest.fixture +def zone_b(): + terrain = [["." for _ in range(10)] for _ in range(10)] + return Zone( + name="zone_b", + 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 + + +@pytest.fixture(autouse=True) +def clear_zones(): + """Clear zone registry before and after each test.""" + zone_registry.clear() + yield + zone_registry.clear() + # --- construction --- @@ -46,3 +110,140 @@ def test_portal_rejects_things(): p = Portal(name="portal") thing = Thing(name="sword") assert p.can_accept(thing) is False + + +# --- portal display --- + + +@pytest.mark.asyncio +async def test_look_shows_portal_at_position(player, test_zone, mock_writer): + """look command shows portals at player position.""" + from mudlib.commands.look import cmd_look + + Portal( + name="shimmering doorway", + location=test_zone, + x=5, + y=5, + target_zone="elsewhere", + target_x=0, + target_y=0, + ) + + await cmd_look(player, "") + output = "".join([call[0][0] for call in mock_writer.write.call_args_list]) + # New format: "You see {portal.name}." + assert "you see shimmering doorway." in output.lower() + + +@pytest.mark.asyncio +async def test_look_shows_multiple_portals(player, test_zone, mock_writer): + """look command shows multiple portals at player position.""" + from mudlib.commands.look import cmd_look + + Portal( + name="red portal", + location=test_zone, + x=5, + y=5, + target_zone="redzone", + target_x=0, + target_y=0, + ) + Portal( + name="blue portal", + location=test_zone, + x=5, + y=5, + target_zone="bluezone", + target_x=0, + target_y=0, + ) + + await cmd_look(player, "") + output = "".join([call[0][0] for call in mock_writer.write.call_args_list]) + assert "red portal" in output.lower() + assert "blue portal" in output.lower() + + +@pytest.mark.asyncio +async def test_look_no_portals_at_position(player, test_zone, mock_writer): + """look command doesn't show portals when none at position.""" + from mudlib.commands.look import cmd_look + + Portal( + name="distant portal", + location=test_zone, + x=8, + y=8, + target_zone="elsewhere", + target_x=0, + target_y=0, + ) + + await cmd_look(player, "") + output = "".join([call[0][0] for call in mock_writer.write.call_args_list]) + # Should not mention portals when none are at player position + assert "portal" not in output.lower() or "distant portal" not in output.lower() + + +# --- two-way portal transitions --- + + +@pytest.mark.asyncio +async def test_two_way_portal_transitions(mock_reader, mock_writer, zone_a, zone_b): + """Portals work bidirectionally between zones.""" + from mudlib.commands.portals import cmd_enter + + # Create player in zone_a at (2, 2) + player = Player( + name="TestPlayer", + x=2, + y=2, + reader=mock_reader, + writer=mock_writer, + location=zone_a, + ) + + # Register zones + register_zone("zone_a", zone_a) + register_zone("zone_b", zone_b) + + # Create portal in zone A pointing to zone B + Portal( + name="doorway to B", + location=zone_a, + x=2, + y=2, + target_zone="zone_b", + target_x=7, + target_y=7, + ) + + # Create portal in zone B pointing to zone A + Portal( + name="doorway to A", + location=zone_b, + x=7, + y=7, + target_zone="zone_a", + target_x=2, + target_y=2, + ) + + # Player starts in zone A at (2, 2) + assert player.location is zone_a + assert player.x == 2 + assert player.y == 2 + + # Enter portal to zone B + await cmd_enter(player, "doorway to B") + assert player.location is zone_b + assert player.x == 7 + assert player.y == 7 + + # Enter portal back to zone A + await cmd_enter(player, "doorway to A") + assert player.location is zone_a + assert player.x == 2 + assert player.y == 2 diff --git a/tests/test_portal_display.py b/tests/test_portal_display.py deleted file mode 100644 index b36b0b8..0000000 --- a/tests/test_portal_display.py +++ /dev/null @@ -1,104 +0,0 @@ -"""Tests for portal display in look command.""" - -import pytest - -from mudlib.player import Player -from mudlib.portal import Portal -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 - - -@pytest.mark.asyncio -async def test_look_shows_portal_at_position(player, test_zone, mock_writer): - """look command shows portals at player position.""" - from mudlib.commands.look import cmd_look - - Portal( - name="shimmering doorway", - location=test_zone, - x=5, - y=5, - target_zone="elsewhere", - target_x=0, - target_y=0, - ) - - await cmd_look(player, "") - output = "".join([call[0][0] for call in mock_writer.write.call_args_list]) - # New format: "You see {portal.name}." - assert "you see shimmering doorway." in output.lower() - - -@pytest.mark.asyncio -async def test_look_shows_multiple_portals(player, test_zone, mock_writer): - """look command shows multiple portals at player position.""" - from mudlib.commands.look import cmd_look - - Portal( - name="red portal", - location=test_zone, - x=5, - y=5, - target_zone="redzone", - target_x=0, - target_y=0, - ) - Portal( - name="blue portal", - location=test_zone, - x=5, - y=5, - target_zone="bluezone", - target_x=0, - target_y=0, - ) - - await cmd_look(player, "") - output = "".join([call[0][0] for call in mock_writer.write.call_args_list]) - assert "red portal" in output.lower() - assert "blue portal" in output.lower() - - -@pytest.mark.asyncio -async def test_look_no_portals_at_position(player, test_zone, mock_writer): - """look command doesn't show portals when none at position.""" - from mudlib.commands.look import cmd_look - - Portal( - name="distant portal", - location=test_zone, - x=8, - y=8, - target_zone="elsewhere", - target_x=0, - target_y=0, - ) - - await cmd_look(player, "") - output = "".join([call[0][0] for call in mock_writer.write.call_args_list]) - # Should not mention portals when none are at player position - assert "portal" not in output.lower() or "distant portal" not in output.lower() diff --git a/tests/test_two_way_portals.py b/tests/test_two_way_portals.py deleted file mode 100644 index 8133f3e..0000000 --- a/tests/test_two_way_portals.py +++ /dev/null @@ -1,102 +0,0 @@ -"""Tests for two-way portal transitions.""" - -import pytest - -from mudlib.player import Player -from mudlib.portal import Portal -from mudlib.zone import Zone -from mudlib.zones import register_zone, zone_registry - - -@pytest.fixture -def zone_a(): - terrain = [["." for _ in range(10)] for _ in range(10)] - return Zone( - name="zone_a", - width=10, - height=10, - toroidal=True, - terrain=terrain, - ) - - -@pytest.fixture -def zone_b(): - terrain = [["." for _ in range(10)] for _ in range(10)] - return Zone( - name="zone_b", - width=10, - height=10, - toroidal=True, - terrain=terrain, - ) - - -@pytest.fixture -def player(mock_reader, mock_writer, zone_a): - p = Player( - name="TestPlayer", - x=2, - y=2, - reader=mock_reader, - writer=mock_writer, - location=zone_a, - ) - return p - - -@pytest.fixture(autouse=True) -def clear_zones(): - """Clear zone registry before and after each test.""" - zone_registry.clear() - yield - zone_registry.clear() - - -@pytest.mark.asyncio -async def test_two_way_portal_transitions(player, zone_a, zone_b): - """Portals work bidirectionally between zones.""" - from mudlib.commands.portals import cmd_enter - - # Register zones - register_zone("zone_a", zone_a) - register_zone("zone_b", zone_b) - - # Create portal in zone A pointing to zone B - Portal( - name="doorway to B", - location=zone_a, - x=2, - y=2, - target_zone="zone_b", - target_x=7, - target_y=7, - ) - - # Create portal in zone B pointing to zone A - Portal( - name="doorway to A", - location=zone_b, - x=7, - y=7, - target_zone="zone_a", - target_x=2, - target_y=2, - ) - - # Player starts in zone A at (2, 2) - assert player.location is zone_a - assert player.x == 2 - assert player.y == 2 - - # Enter portal to zone B - await cmd_enter(player, "doorway to B") - assert player.location is zone_b - assert player.x == 7 - assert player.y == 7 - - # Enter portal back to zone A - await cmd_enter(player, "doorway to A") - assert player.location is zone_a - assert player.x == 2 - assert player.y == 2