We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Polloinfilzato/dm20-protocol'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""
Tests for Party Mode integration bridge.
Tests response filtering by player role (DM, PLAYER, OBSERVER).
"""
from unittest.mock import MagicMock
import pytest
from dm20_protocol.party.bridge import format_response
from dm20_protocol.permissions import PlayerRole
class TestFormatResponse:
"""Tests for format_response."""
def _mock_resolver(self, role: PlayerRole) -> MagicMock:
"""Create a mock PermissionResolver that returns the given role."""
resolver = MagicMock()
resolver.get_player_role.return_value = role
return resolver
def test_player_gets_public_narrative(self) -> None:
"""Test that players receive public narrative."""
resolver = self._mock_resolver(PlayerRole.PLAYER)
raw = {
"id": "res_0001",
"timestamp": "2026-02-17T20:00:00Z",
"action_id": "act_0001",
"narrative": "The dragon roars!",
}
result = format_response(raw, "thorin", resolver)
assert result["narrative"] == "The dragon roars!"
def test_player_gets_own_private(self) -> None:
"""Test that players get their own private messages only."""
resolver = self._mock_resolver(PlayerRole.PLAYER)
raw = {
"id": "res_0001",
"timestamp": "2026-02-17T20:00:00Z",
"narrative": "You see a chest.",
"private": {
"thorin": "You notice it's trapped",
"legolas": "You hear footsteps behind",
},
}
result = format_response(raw, "thorin", resolver)
assert result["private"] == "You notice it's trapped"
assert "all_private" not in result
def test_player_no_dm_only(self) -> None:
"""Test that dm_only content is stripped for players."""
resolver = self._mock_resolver(PlayerRole.PLAYER)
raw = {
"id": "res_0001",
"timestamp": "2026-02-17T20:00:00Z",
"narrative": "The NPC smiles.",
"dm_only": "NPC is planning betrayal",
}
result = format_response(raw, "thorin", resolver)
assert "dm_only" not in result
def test_dm_gets_everything(self) -> None:
"""Test that DM gets all content including dm_only and all private."""
resolver = self._mock_resolver(PlayerRole.DM)
raw = {
"id": "res_0001",
"timestamp": "2026-02-17T20:00:00Z",
"narrative": "The party enters the cave.",
"private": {
"thorin": "Trap ahead",
"legolas": "Shadows moving",
},
"dm_only": "BBEG is watching from above",
}
result = format_response(raw, "dm_user", resolver)
assert result["narrative"] == "The party enters the cave."
assert result["dm_only"] == "BBEG is watching from above"
assert result["all_private"]["thorin"] == "Trap ahead"
assert result["all_private"]["legolas"] == "Shadows moving"
def test_observer_gets_only_narrative(self) -> None:
"""Test that observers get only public narrative."""
resolver = self._mock_resolver(PlayerRole.OBSERVER)
raw = {
"id": "res_0001",
"timestamp": "2026-02-17T20:00:00Z",
"narrative": "Combat begins!",
"private": {"thorin": "secret"},
"dm_only": "hidden info",
}
result = format_response(raw, "observer_1", resolver)
assert result["narrative"] == "Combat begins!"
assert "private" not in result
assert "dm_only" not in result
assert "all_private" not in result
def test_player_without_private_message(self) -> None:
"""Test player who has no private messages in response."""
resolver = self._mock_resolver(PlayerRole.PLAYER)
raw = {
"id": "res_0001",
"timestamp": "2026-02-17T20:00:00Z",
"narrative": "Nothing special happens.",
"private": {"legolas": "only for legolas"},
}
result = format_response(raw, "thorin", resolver)
assert "private" not in result