Follow-up to PR #862 (local skills classification by arceus77-7): - Remove unnecessary isinstance guard on _read_manifest() return value — it always returns Dict[str, str], so set() on it suffices. - Extract repeated hub-dir monkeypatching into a shared pytest fixture (hub_env). - Add three_source_env fixture for source-classification tests. - Add _read_manifest monkeypatch to test_do_list_initializes_hub_dir (was fragile — relied on empty skills list masking the real manifest). - Add test coverage for --source hub and --source builtin filters. - Extract _capture() helper to reduce console/StringIO boilerplate. 5 tests, all green.
125 lines
3.9 KiB
Python
125 lines
3.9 KiB
Python
from io import StringIO
|
|
|
|
import pytest
|
|
from rich.console import Console
|
|
|
|
from hermes_cli.skills_hub import do_list
|
|
|
|
|
|
class _DummyLockFile:
|
|
def __init__(self, installed):
|
|
self._installed = installed
|
|
|
|
def list_installed(self):
|
|
return self._installed
|
|
|
|
|
|
@pytest.fixture()
|
|
def hub_env(monkeypatch, tmp_path):
|
|
"""Set up isolated hub directory paths and return (monkeypatch, tmp_path)."""
|
|
import tools.skills_hub as hub
|
|
|
|
hub_dir = tmp_path / "skills" / ".hub"
|
|
monkeypatch.setattr(hub, "SKILLS_DIR", tmp_path / "skills")
|
|
monkeypatch.setattr(hub, "HUB_DIR", hub_dir)
|
|
monkeypatch.setattr(hub, "LOCK_FILE", hub_dir / "lock.json")
|
|
monkeypatch.setattr(hub, "QUARANTINE_DIR", hub_dir / "quarantine")
|
|
monkeypatch.setattr(hub, "AUDIT_LOG", hub_dir / "audit.log")
|
|
monkeypatch.setattr(hub, "TAPS_FILE", hub_dir / "taps.json")
|
|
monkeypatch.setattr(hub, "INDEX_CACHE_DIR", hub_dir / "index-cache")
|
|
|
|
return hub_dir
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Fixtures for common skill setups
|
|
# ---------------------------------------------------------------------------
|
|
|
|
_HUB_ENTRY = {"name": "hub-skill", "source": "github", "trust_level": "community"}
|
|
|
|
_ALL_THREE_SKILLS = [
|
|
{"name": "hub-skill", "category": "x", "description": "hub"},
|
|
{"name": "builtin-skill", "category": "x", "description": "builtin"},
|
|
{"name": "local-skill", "category": "x", "description": "local"},
|
|
]
|
|
|
|
_BUILTIN_MANIFEST = {"builtin-skill": "abc123"}
|
|
|
|
|
|
@pytest.fixture()
|
|
def three_source_env(monkeypatch, hub_env):
|
|
"""Populate hub/builtin/local skills for source-classification tests."""
|
|
import tools.skills_hub as hub
|
|
import tools.skills_sync as skills_sync
|
|
import tools.skills_tool as skills_tool
|
|
|
|
monkeypatch.setattr(hub, "HubLockFile", lambda: _DummyLockFile([_HUB_ENTRY]))
|
|
monkeypatch.setattr(skills_tool, "_find_all_skills", lambda: list(_ALL_THREE_SKILLS))
|
|
monkeypatch.setattr(skills_sync, "_read_manifest", lambda: dict(_BUILTIN_MANIFEST))
|
|
|
|
return hub_env
|
|
|
|
|
|
def _capture(source_filter: str = "all") -> str:
|
|
"""Run do_list into a string buffer and return the output."""
|
|
sink = StringIO()
|
|
console = Console(file=sink, force_terminal=False, color_system=None)
|
|
do_list(source_filter=source_filter, console=console)
|
|
return sink.getvalue()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Tests
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_do_list_initializes_hub_dir(monkeypatch, hub_env):
|
|
import tools.skills_sync as skills_sync
|
|
import tools.skills_tool as skills_tool
|
|
|
|
monkeypatch.setattr(skills_tool, "_find_all_skills", lambda: [])
|
|
monkeypatch.setattr(skills_sync, "_read_manifest", lambda: {})
|
|
|
|
hub_dir = hub_env
|
|
assert not hub_dir.exists()
|
|
|
|
_capture()
|
|
|
|
assert hub_dir.exists()
|
|
assert (hub_dir / "lock.json").exists()
|
|
assert (hub_dir / "quarantine").is_dir()
|
|
assert (hub_dir / "index-cache").is_dir()
|
|
|
|
|
|
def test_do_list_distinguishes_hub_builtin_and_local(three_source_env):
|
|
output = _capture()
|
|
|
|
assert "hub-skill" in output
|
|
assert "builtin-skill" in output
|
|
assert "local-skill" in output
|
|
assert "1 hub-installed, 1 builtin, 1 local" in output
|
|
|
|
|
|
def test_do_list_filter_local(three_source_env):
|
|
output = _capture(source_filter="local")
|
|
|
|
assert "local-skill" in output
|
|
assert "builtin-skill" not in output
|
|
assert "hub-skill" not in output
|
|
|
|
|
|
def test_do_list_filter_hub(three_source_env):
|
|
output = _capture(source_filter="hub")
|
|
|
|
assert "hub-skill" in output
|
|
assert "builtin-skill" not in output
|
|
assert "local-skill" not in output
|
|
|
|
|
|
def test_do_list_filter_builtin(three_source_env):
|
|
output = _capture(source_filter="builtin")
|
|
|
|
assert "builtin-skill" in output
|
|
assert "hub-skill" not in output
|
|
assert "local-skill" not in output
|