Removed identical local copies from 45 test files. These fixtures are already defined in conftest.py.
180 lines
5.2 KiB
Python
180 lines
5.2 KiB
Python
"""Tests for verb dispatch fallback in command system."""
|
|
|
|
import pytest
|
|
|
|
from mudlib.commands import dispatch
|
|
from mudlib.player import Player
|
|
from mudlib.thing import Thing
|
|
from mudlib.verbs import verb
|
|
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, terrain=terrain)
|
|
|
|
|
|
@pytest.fixture
|
|
def player(mock_reader, mock_writer, test_zone):
|
|
return Player(
|
|
name="TestPlayer",
|
|
x=5,
|
|
y=5,
|
|
reader=mock_reader,
|
|
writer=mock_writer,
|
|
location=test_zone,
|
|
)
|
|
|
|
|
|
class Fountain(Thing):
|
|
"""Test object with drink verb."""
|
|
|
|
@verb("drink")
|
|
async def drink(self, player, args):
|
|
await player.send("You drink from the fountain.\r\n")
|
|
|
|
@verb("splash")
|
|
async def splash(self, player, args):
|
|
await player.send(f"You splash the fountain{' ' + args if args else ''}.\r\n")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verb_dispatch_simple(player, test_zone):
|
|
"""Test 'drink fountain' dispatches to fountain's drink verb."""
|
|
_fountain = Fountain(
|
|
name="fountain",
|
|
description="a stone fountain",
|
|
portable=False,
|
|
location=test_zone,
|
|
x=5,
|
|
y=5,
|
|
)
|
|
|
|
await dispatch(player, "drink fountain")
|
|
|
|
player.writer.write.assert_called_once_with("You drink from the fountain.\r\n")
|
|
player.writer.drain.assert_awaited_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verb_dispatch_with_extra_args(player, test_zone):
|
|
"""Test 'splash fountain hard' passes 'hard' as extra args."""
|
|
_fountain = Fountain(
|
|
name="fountain",
|
|
description="a stone fountain",
|
|
portable=False,
|
|
location=test_zone,
|
|
x=5,
|
|
y=5,
|
|
)
|
|
|
|
await dispatch(player, "splash fountain hard")
|
|
|
|
player.writer.write.assert_called_once_with("You splash the fountain hard.\r\n")
|
|
player.writer.drain.assert_awaited_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verb_dispatch_object_lacks_verb(player, test_zone):
|
|
"""Test 'drink rock' fails if rock doesn't have drink verb."""
|
|
_rock = Thing(
|
|
name="rock",
|
|
description="a plain rock",
|
|
portable=True,
|
|
location=test_zone,
|
|
x=5,
|
|
y=5,
|
|
)
|
|
|
|
await dispatch(player, "drink rock")
|
|
|
|
player.writer.write.assert_called_once_with("Unknown command: drink\r\n")
|
|
player.writer.drain.assert_awaited_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verb_dispatch_object_not_found(player, test_zone):
|
|
"""Test 'drink flurb' fails if flurb doesn't exist."""
|
|
await dispatch(player, "drink flurb")
|
|
|
|
player.writer.write.assert_called_once_with("Unknown command: drink\r\n")
|
|
player.writer.drain.assert_awaited_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verb_dispatch_no_args(player, test_zone):
|
|
"""Test 'drink' with no args doesn't try verb dispatch."""
|
|
await dispatch(player, "drink")
|
|
|
|
player.writer.write.assert_called_once_with("Unknown command: drink\r\n")
|
|
player.writer.drain.assert_awaited_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verb_dispatch_doesnt_intercept_real_commands(player, test_zone):
|
|
"""Test that verb dispatch doesn't interfere with registered commands."""
|
|
from mudlib.commands import CommandDefinition, register, unregister
|
|
|
|
called = False
|
|
|
|
async def test_command(player, args):
|
|
nonlocal called
|
|
called = True
|
|
await player.send("Real command executed.\r\n")
|
|
|
|
register(CommandDefinition("test", test_command))
|
|
try:
|
|
await dispatch(player, "test something")
|
|
assert called
|
|
player.writer.write.assert_called_once_with("Real command executed.\r\n")
|
|
finally:
|
|
unregister("test")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verb_dispatch_finds_inventory_object(player, test_zone):
|
|
"""Test verb dispatch finds object in inventory."""
|
|
|
|
class Potion(Thing):
|
|
@verb("drink")
|
|
async def drink(self, player, args):
|
|
await player.send("You drink the potion.\r\n")
|
|
|
|
_potion = Potion(
|
|
name="potion",
|
|
description="a health potion",
|
|
portable=True,
|
|
location=player,
|
|
)
|
|
|
|
await dispatch(player, "drink potion")
|
|
|
|
player.writer.write.assert_called_once_with("You drink the potion.\r\n")
|
|
player.writer.drain.assert_awaited_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verb_dispatch_doesnt_fire_on_ambiguous_command(player, test_zone):
|
|
"""Test verb dispatch doesn't fire when command is ambiguous."""
|
|
from mudlib.commands import CommandDefinition, register, unregister
|
|
|
|
async def test_one(player, args):
|
|
await player.send("test one\r\n")
|
|
|
|
async def test_two(player, args):
|
|
await player.send("test two\r\n")
|
|
|
|
register(CommandDefinition("testone", test_one))
|
|
register(CommandDefinition("testtwo", test_two))
|
|
try:
|
|
# "test" matches both testone and testtwo
|
|
await dispatch(player, "test something")
|
|
|
|
# Should get ambiguous command message, not verb dispatch
|
|
written_text = player.writer.write.call_args[0][0].lower()
|
|
# The ambiguous message is "testone or testtwo?" not "ambiguous"
|
|
assert "or" in written_text and "?" in written_text
|
|
finally:
|
|
unregister("testone")
|
|
unregister("testtwo")
|