feat: Add intelligent auto-router and enhanced integrations
- Add intelligent-router.sh hook for automatic agent routing - Add AUTO-TRIGGER-SUMMARY.md documentation - Add FINAL-INTEGRATION-SUMMARY.md documentation - Complete Prometheus integration (6 commands + 4 tools) - Complete Dexto integration (12 commands + 5 tools) - Enhanced Ralph with access to all agents - Fix /clawd command (removed disable-model-invocation) - Update hooks.json to v5 with intelligent routing - 291 total skills now available - All 21 commands with automatic routing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
197
prometheus/tests/app/services/test_repository_service.py
Normal file
197
prometheus/tests/app/services/test_repository_service.py
Normal file
@@ -0,0 +1,197 @@
|
||||
from pathlib import Path
|
||||
from unittest.mock import create_autospec, patch
|
||||
|
||||
import pytest
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from prometheus.app.entity.repository import Repository
|
||||
from prometheus.app.services.database_service import DatabaseService
|
||||
from prometheus.app.services.knowledge_graph_service import KnowledgeGraphService
|
||||
from prometheus.app.services.repository_service import RepositoryService
|
||||
from prometheus.git.git_repository import GitRepository
|
||||
from tests.test_utils.fixtures import postgres_container_fixture # noqa: F401
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_kg_service():
|
||||
# Mock KnowledgeGraphService; RepositoryService only reads its attributes in other paths
|
||||
kg_service = create_autospec(KnowledgeGraphService, instance=True)
|
||||
kg_service.max_ast_depth = 3
|
||||
kg_service.chunk_size = 1000
|
||||
kg_service.chunk_overlap = 100
|
||||
return kg_service
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def mock_database_service(postgres_container_fixture): # noqa: F811
|
||||
service = DatabaseService(postgres_container_fixture.get_connection_url())
|
||||
await service.start()
|
||||
yield service
|
||||
await service.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_git_repository():
|
||||
repo = create_autospec(GitRepository, instance=True)
|
||||
repo.get_working_directory.return_value = Path("/test/working/dir/repositories/repo")
|
||||
return repo
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def service(mock_kg_service, mock_database_service, monkeypatch):
|
||||
working_dir = "/test/working/dir"
|
||||
# Avoid touching the real filesystem when creating the base repo folder
|
||||
monkeypatch.setattr(Path, "mkdir", lambda *args, **kwargs: None)
|
||||
return RepositoryService(
|
||||
kg_service=mock_kg_service,
|
||||
database_service=mock_database_service, # <-- use the correct fixture here
|
||||
working_dir=working_dir,
|
||||
)
|
||||
|
||||
|
||||
async def test_clone_new_github_repo(service, mock_git_repository, monkeypatch):
|
||||
# Arrange
|
||||
test_url = "https://github.com/test/repo"
|
||||
test_commit = "abc123"
|
||||
test_github_token = "test_token"
|
||||
expected_path = Path("/test/working/dir/repositories/repo")
|
||||
|
||||
# Force get_new_playground_path() to return a deterministic path for assertions
|
||||
monkeypatch.setattr(service, "get_new_playground_path", lambda: expected_path)
|
||||
|
||||
# Patch GitRepository so its constructor returns our mock instance
|
||||
with patch(
|
||||
"prometheus.app.services.repository_service.GitRepository",
|
||||
return_value=mock_git_repository,
|
||||
) as mock_git_class:
|
||||
# Act
|
||||
result_path = await service.clone_github_repo(test_github_token, test_url, test_commit)
|
||||
|
||||
# Assert
|
||||
|
||||
# GitRepository should be instantiated without args (per current implementation)
|
||||
mock_git_class.assert_called_once_with()
|
||||
|
||||
# Ensure the clone method was invoked with correct parameters
|
||||
mock_git_repository.from_clone_repository.assert_called_once_with(
|
||||
test_url, test_github_token, expected_path
|
||||
)
|
||||
|
||||
# Verify the requested commit was checked out
|
||||
mock_git_repository.checkout_commit.assert_called_once_with(test_commit)
|
||||
|
||||
# The returned path should be the working directory of the mocked repo
|
||||
assert result_path == expected_path
|
||||
|
||||
|
||||
def test_get_new_playground_path(service):
|
||||
expected_uuid = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
expected_path = service.target_directory / expected_uuid
|
||||
with patch("uuid.uuid4") as mock_uuid:
|
||||
mock_uuid.return_value.hex = expected_uuid
|
||||
result = service.get_new_playground_path()
|
||||
|
||||
assert result == expected_path
|
||||
|
||||
|
||||
def test_clean_repository_removes_dir_and_parent(service, monkeypatch):
|
||||
"""
|
||||
Should call shutil.rmtree on the repository path and remove its parent directory
|
||||
when the path exists.
|
||||
"""
|
||||
repo_path = Path("/tmp/repositories/abc123")
|
||||
repository = Repository(playground_path=str(repo_path))
|
||||
|
||||
# Patch path.exists() to return True
|
||||
monkeypatch.setattr(Path, "exists", lambda self: self == repo_path)
|
||||
|
||||
# Track calls to shutil.rmtree and Path.rmdir
|
||||
removed = {"rmtree": None, "rmdir": []}
|
||||
|
||||
monkeypatch.setattr(
|
||||
"shutil.rmtree",
|
||||
lambda target: removed.update(rmtree=target),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
Path,
|
||||
"rmdir",
|
||||
lambda self: removed["rmdir"].append(self),
|
||||
)
|
||||
|
||||
service.clean_repository(repository)
|
||||
|
||||
# Assert rmtree called with correct path string
|
||||
assert removed["rmtree"] == str(repo_path)
|
||||
# Assert rmdir called on the parent directory
|
||||
assert repo_path.parent in removed["rmdir"]
|
||||
|
||||
|
||||
def test_clean_repository_skips_when_not_exists(service, monkeypatch):
|
||||
"""
|
||||
Should not call rmtree or rmdir when the repository path does not exist.
|
||||
"""
|
||||
repo_path = Path("/tmp/repositories/abc123")
|
||||
repository = Repository(playground_path=str(repo_path))
|
||||
|
||||
# Path.exists returns False
|
||||
monkeypatch.setattr(Path, "exists", lambda self: False)
|
||||
|
||||
monkeypatch.setattr("shutil.rmtree", lambda target: pytest.fail("rmtree should not be called"))
|
||||
monkeypatch.setattr(Path, "rmdir", lambda self: pytest.fail("rmdir should not be called"))
|
||||
|
||||
# No exception means pass
|
||||
service.clean_repository(repository)
|
||||
|
||||
|
||||
def test_get_repository_returns_git_repo_instance(service):
|
||||
"""
|
||||
Should create a GitRepository, call from_local_repository with the given path,
|
||||
and return the GitRepository instance.
|
||||
"""
|
||||
test_path = "/some/local/path"
|
||||
|
||||
mock_git_repo_instance = create_autospec(GitRepository, instance=True)
|
||||
|
||||
# Patch GitRepository() constructor to return our mock instance
|
||||
with patch(
|
||||
"prometheus.app.services.repository_service.GitRepository",
|
||||
return_value=mock_git_repo_instance,
|
||||
) as mock_git_class:
|
||||
result = service.get_repository(test_path)
|
||||
|
||||
# Verify GitRepository() was called with no args
|
||||
mock_git_class.assert_called_once_with()
|
||||
|
||||
# Verify from_local_repository was called with the correct Path object
|
||||
mock_git_repo_instance.from_local_repository.assert_called_once_with(Path(test_path))
|
||||
|
||||
# Verify the returned object is the same as the mock instance
|
||||
assert result == mock_git_repo_instance
|
||||
|
||||
|
||||
async def test_create_new_repository(service):
|
||||
# Exercise
|
||||
await service.create_new_repository(
|
||||
url="https://github.com/test/repo",
|
||||
commit_id="abc123",
|
||||
playground_path="/tmp/repositories/repo",
|
||||
user_id=None,
|
||||
kg_root_node_id=0,
|
||||
)
|
||||
|
||||
# Verify the object is persisted in the database
|
||||
async with AsyncSession(service.engine) as session:
|
||||
db_obj = await session.get(Repository, 1)
|
||||
assert db_obj is not None
|
||||
assert db_obj.url == "https://github.com/test/repo"
|
||||
assert db_obj.commit_id == "abc123"
|
||||
assert db_obj.playground_path == "/tmp/repositories/repo"
|
||||
assert db_obj.user_id is None
|
||||
assert db_obj.kg_root_node_id == 0
|
||||
|
||||
|
||||
async def test_get_all_repositories(service):
|
||||
# Exercise
|
||||
repos = await service.get_all_repositories()
|
||||
# Verify
|
||||
assert len(repos) == 1
|
||||
Reference in New Issue
Block a user