mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-29 18:40:38 +00:00
84 lines
2.9 KiB
Python
84 lines
2.9 KiB
Python
"""End-to-end CLI tests for skill install + sync against fake sources."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import textwrap
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
from click.testing import CliRunner
|
|
|
|
from openjarvis.cli import cli
|
|
|
|
|
|
def _build_fake_hermes_cache(cache_root: Path) -> None:
|
|
"""Build a minimal fake Hermes cache for testing."""
|
|
skills_root = cache_root / "skills"
|
|
(skills_root / "research" / "research-skill").mkdir(parents=True)
|
|
(skills_root / "research" / "research-skill" / "SKILL.md").write_text(
|
|
textwrap.dedent("""\
|
|
---
|
|
name: research-skill
|
|
description: A research skill
|
|
---
|
|
|
|
Use the Bash tool to fetch data, then Read the file.
|
|
""")
|
|
)
|
|
# Fake .git so HermesResolver doesn't try to clone
|
|
(cache_root / ".git").mkdir()
|
|
|
|
|
|
class TestCliInstallE2E:
|
|
def test_install_hermes_skill_e2e(self, tmp_path: Path) -> None:
|
|
"""jarvis skill install hermes:research-skill installs to target dir."""
|
|
from openjarvis.skills.sources.hermes import HermesResolver
|
|
|
|
cache = tmp_path / "hermes-cache"
|
|
target = tmp_path / "target"
|
|
_build_fake_hermes_cache(cache)
|
|
|
|
# Create a HermesResolver pointed at the fake cache
|
|
def _make_resolver(*_args, **_kwargs):
|
|
r = HermesResolver.__new__(HermesResolver)
|
|
r._cache_root = cache
|
|
return r
|
|
|
|
# Patch the helper that builds resolvers in the CLI
|
|
with patch(
|
|
"openjarvis.cli.skill_cmd._get_resolver",
|
|
lambda src, url="": _make_resolver(),
|
|
):
|
|
# Patch HermesResolver.sync to no-op (cache is already built)
|
|
with patch.object(HermesResolver, "sync", lambda self: None):
|
|
# Patch the SkillImporter constructor used inside the install
|
|
# command so it writes to our test target instead of
|
|
# ~/.openjarvis/skills/.
|
|
from openjarvis.skills.importer import SkillImporter as _SI
|
|
|
|
original_init = _SI.__init__
|
|
|
|
def patched_init(self, parser, tool_translator, target_root=None):
|
|
original_init(
|
|
self,
|
|
parser=parser,
|
|
tool_translator=tool_translator,
|
|
target_root=target,
|
|
)
|
|
|
|
with patch.object(_SI, "__init__", patched_init):
|
|
result = CliRunner().invoke(
|
|
cli, ["skill", "install", "hermes:research-skill"]
|
|
)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "Installed" in result.output
|
|
|
|
installed = target / "hermes" / "research-skill" / "SKILL.md"
|
|
assert installed.exists(), (
|
|
f"Expected {installed} to exist; output:\n{result.output}"
|
|
)
|
|
body = installed.read_text()
|
|
assert "shell_exec" in body
|
|
assert "file_read" in body
|