"""Tests for the WorldInterface contract and type system.""" import pytest from infrastructure.world.interface import WorldInterface from infrastructure.world.types import ( ActionResult, ActionStatus, CommandInput, PerceptionOutput, ) # --------------------------------------------------------------------------- # Type construction # --------------------------------------------------------------------------- class TestPerceptionOutput: def test_defaults(self): p = PerceptionOutput() assert p.location == "" assert p.entities == [] assert p.events == [] assert p.raw == {} assert p.timestamp is not None def test_custom_values(self): p = PerceptionOutput( location="Balmora", entities=["Guard", "Merchant"], events=["door_opened"], ) assert p.location == "Balmora" assert len(p.entities) == 2 assert "door_opened" in p.events class TestCommandInput: def test_minimal(self): c = CommandInput(action="move") assert c.action == "move" assert c.target is None assert c.parameters == {} def test_with_target_and_params(self): c = CommandInput(action="attack", target="Rat", parameters={"weapon": "sword"}) assert c.target == "Rat" assert c.parameters["weapon"] == "sword" class TestActionResult: def test_defaults(self): r = ActionResult() assert r.status == ActionStatus.SUCCESS assert r.message == "" def test_failure(self): r = ActionResult(status=ActionStatus.FAILURE, message="blocked") assert r.status == ActionStatus.FAILURE class TestActionStatus: def test_values(self): assert ActionStatus.SUCCESS.value == "success" assert ActionStatus.FAILURE.value == "failure" assert ActionStatus.PENDING.value == "pending" assert ActionStatus.NOOP.value == "noop" # --------------------------------------------------------------------------- # Abstract contract # --------------------------------------------------------------------------- class TestWorldInterfaceContract: """Verify the ABC cannot be instantiated directly.""" def test_cannot_instantiate(self): with pytest.raises(TypeError): WorldInterface() def test_subclass_must_implement_observe(self): class Incomplete(WorldInterface): def act(self, command): pass def speak(self, message, target=None): pass with pytest.raises(TypeError): Incomplete() def test_subclass_must_implement_act(self): class Incomplete(WorldInterface): def observe(self): return PerceptionOutput() def speak(self, message, target=None): pass with pytest.raises(TypeError): Incomplete() def test_subclass_must_implement_speak(self): class Incomplete(WorldInterface): def observe(self): return PerceptionOutput() def act(self, command): return ActionResult() with pytest.raises(TypeError): Incomplete() def test_complete_subclass_instantiates(self): class Complete(WorldInterface): def observe(self): return PerceptionOutput() def act(self, command): return ActionResult() def speak(self, message, target=None): pass adapter = Complete() assert adapter.is_connected is True # default assert isinstance(adapter.observe(), PerceptionOutput) assert isinstance(adapter.act(CommandInput(action="test")), ActionResult)