/ tests / agent / test_display_emoji.py
test_display_emoji.py
  1  """Tests for get_tool_emoji in agent/display.py — skin + registry integration."""
  2  
  3  from unittest.mock import patch as mock_patch, MagicMock
  4  
  5  from agent.display import get_tool_emoji
  6  
  7  
  8  class TestGetToolEmoji:
  9      """Verify the skin → registry → fallback resolution chain."""
 10  
 11      def test_returns_registry_emoji_when_no_skin(self):
 12          """Registry-registered emoji is used when no skin is active."""
 13          mock_registry = MagicMock()
 14          mock_registry.get_emoji.return_value = "🎨"
 15          with mock_patch("agent.display._get_skin", return_value=None), \
 16               mock_patch("agent.display.registry", mock_registry, create=True):
 17              # Need to patch the import inside get_tool_emoji
 18              pass
 19          # Direct test: patch the lazy import path
 20          with mock_patch("agent.display._get_skin", return_value=None):
 21              # get_tool_emoji will try to import registry — mock that
 22              mock_reg = MagicMock()
 23              mock_reg.get_emoji.return_value = "📖"
 24              with mock_patch.dict("sys.modules", {}):
 25                  import sys
 26                  # Patch tools.registry module
 27                  mock_module = MagicMock()
 28                  mock_module.registry = mock_reg
 29                  with mock_patch.dict(sys.modules, {"tools.registry": mock_module}):
 30                      result = get_tool_emoji("read_file")
 31                      assert result == "📖"
 32  
 33      def test_skin_override_takes_precedence(self):
 34          """Skin tool_emojis override registry defaults."""
 35          skin = MagicMock()
 36          skin.tool_emojis = {"terminal": "⚔"}
 37          with mock_patch("agent.display._get_skin", return_value=skin):
 38              result = get_tool_emoji("terminal")
 39              assert result == "⚔"
 40  
 41      def test_skin_empty_dict_falls_through(self):
 42          """Empty skin tool_emojis falls through to registry."""
 43          skin = MagicMock()
 44          skin.tool_emojis = {}
 45          mock_reg = MagicMock()
 46          mock_reg.get_emoji.return_value = "💻"
 47          import sys
 48          mock_module = MagicMock()
 49          mock_module.registry = mock_reg
 50          with mock_patch("agent.display._get_skin", return_value=skin), \
 51               mock_patch.dict(sys.modules, {"tools.registry": mock_module}):
 52              result = get_tool_emoji("terminal")
 53              assert result == "💻"
 54  
 55      def test_fallback_default(self):
 56          """When neither skin nor registry has an emoji, use the default."""
 57          skin = MagicMock()
 58          skin.tool_emojis = {}
 59          mock_reg = MagicMock()
 60          mock_reg.get_emoji.return_value = ""
 61          import sys
 62          mock_module = MagicMock()
 63          mock_module.registry = mock_reg
 64          with mock_patch("agent.display._get_skin", return_value=skin), \
 65               mock_patch.dict(sys.modules, {"tools.registry": mock_module}):
 66              result = get_tool_emoji("unknown_tool")
 67              assert result == "⚡"
 68  
 69      def test_custom_default(self):
 70          """Custom default is returned when nothing matches."""
 71          with mock_patch("agent.display._get_skin", return_value=None):
 72              mock_reg = MagicMock()
 73              mock_reg.get_emoji.return_value = ""
 74              import sys
 75              mock_module = MagicMock()
 76              mock_module.registry = mock_reg
 77              with mock_patch.dict(sys.modules, {"tools.registry": mock_module}):
 78                  result = get_tool_emoji("x", default="⚙️")
 79                  assert result == "⚙️"
 80  
 81      def test_skin_override_only_for_matching_tool(self):
 82          """Skin override for one tool doesn't affect others."""
 83          skin = MagicMock()
 84          skin.tool_emojis = {"terminal": "⚔"}
 85          mock_reg = MagicMock()
 86          mock_reg.get_emoji.return_value = "🔍"
 87          import sys
 88          mock_module = MagicMock()
 89          mock_module.registry = mock_reg
 90          with mock_patch("agent.display._get_skin", return_value=skin), \
 91               mock_patch.dict(sys.modules, {"tools.registry": mock_module}):
 92              assert get_tool_emoji("terminal") == "⚔"  # skin override
 93              assert get_tool_emoji("web_search") == "🔍"  # registry fallback
 94  
 95  
 96  class TestSkinConfigToolEmojis:
 97      """Verify SkinConfig handles tool_emojis field correctly."""
 98  
 99      def test_skin_config_has_tool_emojis_field(self):
100          from hermes_cli.skin_engine import SkinConfig
101          skin = SkinConfig(name="test")
102          assert skin.tool_emojis == {}
103  
104      def test_skin_config_accepts_tool_emojis(self):
105          from hermes_cli.skin_engine import SkinConfig
106          emojis = {"terminal": "⚔", "web_search": "🔮"}
107          skin = SkinConfig(name="test", tool_emojis=emojis)
108          assert skin.tool_emojis == emojis
109  
110      def test_build_skin_config_includes_tool_emojis(self):
111          from hermes_cli.skin_engine import _build_skin_config
112          data = {
113              "name": "custom",
114              "tool_emojis": {"terminal": "🗡️", "patch": "⚒️"},
115          }
116          skin = _build_skin_config(data)
117          assert skin.tool_emojis == {"terminal": "🗡️", "patch": "⚒️"}
118  
119      def test_build_skin_config_empty_tool_emojis_default(self):
120          from hermes_cli.skin_engine import _build_skin_config
121          data = {"name": "minimal"}
122          skin = _build_skin_config(data)
123          assert skin.tool_emojis == {}