Skip to main content
Glama
test_repository_manager.py•15.2 kB
"""Tests for repository management service.""" import json from datetime import datetime from pathlib import Path from unittest.mock import MagicMock, patch import git import pytest from mcp_skills.services.repository_manager import Repository, RepositoryManager class TestRepository: """Test suite for Repository dataclass.""" def test_repository_to_dict(self, tmp_path: Path) -> None: """Test converting Repository to dictionary.""" repo = Repository( id="test/repo", url="https://github.com/test/repo.git", local_path=tmp_path / "test/repo", priority=50, last_updated=datetime(2024, 1, 1, 12, 0, 0), skill_count=5, license="MIT", ) data = repo.to_dict() assert data["id"] == "test/repo" assert data["url"] == "https://github.com/test/repo.git" assert data["local_path"] == str(tmp_path / "test/repo") assert data["priority"] == 50 assert data["last_updated"] == "2024-01-01T12:00:00" assert data["skill_count"] == 5 assert data["license"] == "MIT" def test_repository_from_dict(self, tmp_path: Path) -> None: """Test creating Repository from dictionary.""" data = { "id": "test/repo", "url": "https://github.com/test/repo.git", "local_path": str(tmp_path / "test/repo"), "priority": 50, "last_updated": "2024-01-01T12:00:00", "skill_count": 5, "license": "MIT", } repo = Repository.from_dict(data) assert repo.id == "test/repo" assert repo.url == "https://github.com/test/repo.git" assert repo.local_path == tmp_path / "test/repo" assert repo.priority == 50 assert repo.last_updated == datetime(2024, 1, 1, 12, 0, 0) assert repo.skill_count == 5 assert repo.license == "MIT" class TestRepositoryManager: """Test suite for RepositoryManager.""" def test_manager_initialization(self, tmp_path: Path) -> None: """Test repository manager can be initialized.""" manager = RepositoryManager(base_dir=tmp_path / "repos") assert manager is not None assert manager.base_dir.exists() # metadata_file is in parent of base_dir assert manager.metadata_file == tmp_path / "repos.json" def test_default_repos_defined(self) -> None: """Test default repositories are defined.""" assert hasattr(RepositoryManager, "DEFAULT_REPOS") assert isinstance(RepositoryManager.DEFAULT_REPOS, list) assert len(RepositoryManager.DEFAULT_REPOS) > 0 def test_list_repositories_returns_list(self, tmp_path: Path) -> None: """Test list_repositories returns empty list initially.""" manager = RepositoryManager(base_dir=tmp_path / "repos") repos = manager.list_repositories() assert isinstance(repos, list) assert len(repos) == 0 def test_get_repository_returns_optional(self, tmp_path: Path) -> None: """Test get_repository returns None for non-existent repo.""" manager = RepositoryManager(base_dir=tmp_path / "repos") repo = manager.get_repository("non-existent") assert repo is None def test_add_repository_validates_url(self, tmp_path: Path) -> None: """Test add_repository validates git URL format.""" manager = RepositoryManager(base_dir=tmp_path / "repos") with pytest.raises(ValueError, match="Invalid git URL"): manager.add_repository(url="not-a-valid-url", priority=50) with pytest.raises(ValueError, match="Invalid git URL"): manager.add_repository(url="", priority=50) def test_add_repository_validates_priority(self, tmp_path: Path) -> None: """Test add_repository validates priority range.""" manager = RepositoryManager(base_dir=tmp_path / "repos") with pytest.raises(ValueError, match="Priority must be between 0-100"): manager.add_repository(url="https://github.com/test/repo.git", priority=-1) with pytest.raises(ValueError, match="Priority must be between 0-100"): manager.add_repository(url="https://github.com/test/repo.git", priority=101) @patch("git.Repo.clone_from") def test_add_repository_clones_successfully( self, mock_clone: MagicMock, tmp_path: Path ) -> None: """Test add_repository clones repository.""" manager = RepositoryManager(base_dir=tmp_path / "repos") # Create fake skill files repo_path = tmp_path / "repos" / "test/repo" repo_path.mkdir(parents=True) (repo_path / "SKILL.md").write_text("# Test Skill") repo = manager.add_repository( url="https://github.com/test/repo.git", priority=50, license="MIT" ) # Verify clone was called mock_clone.assert_called_once() assert mock_clone.call_args[0][0] == "https://github.com/test/repo.git" # Verify repository metadata assert repo.id == "test/repo" assert repo.url == "https://github.com/test/repo.git" assert repo.priority == 50 assert repo.license == "MIT" assert repo.skill_count == 1 @patch("git.Repo.clone_from") def test_add_repository_detects_duplicates( self, mock_clone: MagicMock, tmp_path: Path ) -> None: """Test add_repository prevents duplicate repositories.""" manager = RepositoryManager(base_dir=tmp_path / "repos") # Create fake repo directory repo_path = tmp_path / "repos" / "test/repo" repo_path.mkdir(parents=True) # Add first repository manager.add_repository( url="https://github.com/test/repo.git", priority=50, license="MIT" ) # Try to add duplicate with pytest.raises(ValueError, match="Repository already exists"): manager.add_repository( url="https://github.com/test/repo.git", priority=60, license="MIT" ) @patch("git.Repo.clone_from") def test_add_repository_handles_clone_failure( self, mock_clone: MagicMock, tmp_path: Path ) -> None: """Test add_repository handles git clone failures.""" manager = RepositoryManager(base_dir=tmp_path / "repos") # Simulate clone failure mock_clone.side_effect = git.exc.GitCommandError( "clone", "fatal: repository not found" ) with pytest.raises(ValueError, match="Failed to clone repository"): manager.add_repository( url="https://github.com/test/nonexistent.git", priority=50 ) @patch("git.Repo.clone_from") def test_list_repositories_sorted_by_priority( self, mock_clone: MagicMock, tmp_path: Path ) -> None: """Test list_repositories returns repos sorted by priority.""" manager = RepositoryManager(base_dir=tmp_path / "repos") # Create multiple repos with different priorities for name, priority in [("repo1", 30), ("repo2", 90), ("repo3", 50)]: repo_path = tmp_path / "repos" / f"test/{name}" repo_path.mkdir(parents=True) manager.add_repository( url=f"https://github.com/test/{name}.git", priority=priority, license="MIT", ) repos = manager.list_repositories() # Verify sorted by priority descending assert len(repos) == 3 assert repos[0].priority == 90 assert repos[1].priority == 50 assert repos[2].priority == 30 @patch("git.Repo.clone_from") def test_get_repository_finds_existing( self, mock_clone: MagicMock, tmp_path: Path ) -> None: """Test get_repository finds existing repository.""" manager = RepositoryManager(base_dir=tmp_path / "repos") # Add repository repo_path = tmp_path / "repos" / "test/repo" repo_path.mkdir(parents=True) added = manager.add_repository( url="https://github.com/test/repo.git", priority=50, license="MIT" ) # Retrieve repository found = manager.get_repository("test/repo") assert found is not None assert found.id == added.id assert found.url == added.url @patch("git.Repo") @patch("git.Repo.clone_from") def test_update_repository_pulls_changes( self, mock_clone: MagicMock, mock_repo_class: MagicMock, tmp_path: Path ) -> None: """Test update_repository pulls latest changes.""" manager = RepositoryManager(base_dir=tmp_path / "repos") # Add repository repo_path = tmp_path / "repos" / "test/repo" repo_path.mkdir(parents=True) (repo_path / "SKILL.md").write_text("# Skill 1") manager.add_repository( url="https://github.com/test/repo.git", priority=50, license="MIT" ) # Mock git operations for update mock_repo_instance = MagicMock() mock_origin = MagicMock() mock_repo_instance.remotes.origin = mock_origin mock_repo_class.return_value = mock_repo_instance # Add new skill file to simulate changes (repo_path / "subdir").mkdir() (repo_path / "subdir" / "SKILL.md").write_text("# Skill 2") # Update repository updated = manager.update_repository("test/repo") # Verify pull was called mock_origin.pull.assert_called_once() # Verify skill count updated assert updated.skill_count == 2 def test_update_repository_not_found(self, tmp_path: Path) -> None: """Test update_repository raises error for non-existent repo.""" manager = RepositoryManager(base_dir=tmp_path / "repos") with pytest.raises(ValueError, match="Repository not found"): manager.update_repository("non-existent") @patch("git.Repo") @patch("git.Repo.clone_from") def test_update_repository_handles_pull_failure( self, mock_clone: MagicMock, mock_repo_class: MagicMock, tmp_path: Path ) -> None: """Test update_repository handles git pull failures.""" manager = RepositoryManager(base_dir=tmp_path / "repos") # Add repository repo_path = tmp_path / "repos" / "test/repo" repo_path.mkdir(parents=True) manager.add_repository( url="https://github.com/test/repo.git", priority=50, license="MIT" ) # Mock git pull failure mock_repo_instance = MagicMock() mock_origin = MagicMock() mock_origin.pull.side_effect = git.exc.GitCommandError( "pull", "fatal: unable to access repository" ) mock_repo_instance.remotes.origin = mock_origin mock_repo_class.return_value = mock_repo_instance with pytest.raises(ValueError, match="Failed to update repository"): manager.update_repository("test/repo") @patch("git.Repo.clone_from") def test_remove_repository_deletes_successfully( self, mock_clone: MagicMock, tmp_path: Path ) -> None: """Test remove_repository deletes repo and metadata.""" manager = RepositoryManager(base_dir=tmp_path / "repos") # Add repository repo_path = tmp_path / "repos" / "test/repo" repo_path.mkdir(parents=True) manager.add_repository( url="https://github.com/test/repo.git", priority=50, license="MIT" ) # Verify it exists assert manager.get_repository("test/repo") is not None assert repo_path.exists() # Remove repository manager.remove_repository("test/repo") # Verify it's gone assert manager.get_repository("test/repo") is None assert not repo_path.exists() def test_remove_repository_not_found(self, tmp_path: Path) -> None: """Test remove_repository raises error for non-existent repo.""" manager = RepositoryManager(base_dir=tmp_path / "repos") with pytest.raises(ValueError, match="Repository not found"): manager.remove_repository("non-existent") def test_metadata_persistence_across_instances(self, tmp_path: Path) -> None: """Test repository metadata persists across manager instances.""" with patch("git.Repo.clone_from"): # Create first manager and add repository manager1 = RepositoryManager(base_dir=tmp_path / "repos") repo_path = tmp_path / "repos" / "test/repo" repo_path.mkdir(parents=True) manager1.add_repository( url="https://github.com/test/repo.git", priority=50, license="MIT" ) # Create second manager instance manager2 = RepositoryManager(base_dir=tmp_path / "repos") repos = manager2.list_repositories() # Verify repository was persisted assert len(repos) == 1 assert repos[0].id == "test/repo" def test_generate_repo_id_https(self, tmp_path: Path) -> None: """Test repository ID generation from HTTPS URLs.""" manager = RepositoryManager(base_dir=tmp_path / "repos") assert ( manager._generate_repo_id("https://github.com/anthropics/skills.git") == "anthropics/skills" ) assert ( manager._generate_repo_id("https://github.com/test/repo") == "test/repo" ) def test_generate_repo_id_ssh(self, tmp_path: Path) -> None: """Test repository ID generation from SSH URLs.""" manager = RepositoryManager(base_dir=tmp_path / "repos") assert ( manager._generate_repo_id("git@github.com:anthropics/skills.git") == "anthropics/skills" ) def test_count_skills(self, tmp_path: Path) -> None: """Test skill counting in repository.""" manager = RepositoryManager(base_dir=tmp_path / "repos") # Create test repository with skills repo_path = tmp_path / "test_repo" repo_path.mkdir() (repo_path / "SKILL.md").write_text("# Root Skill") (repo_path / "subdir1").mkdir() (repo_path / "subdir1" / "SKILL.md").write_text("# Subdir1 Skill") (repo_path / "subdir2").mkdir() (repo_path / "subdir2" / "SKILL.md").write_text("# Subdir2 Skill") count = manager._count_skills(repo_path) assert count == 3 def test_is_valid_git_url(self, tmp_path: Path) -> None: """Test git URL validation.""" manager = RepositoryManager(base_dir=tmp_path / "repos") # Valid URLs assert manager._is_valid_git_url("https://github.com/test/repo.git") assert manager._is_valid_git_url("http://github.com/test/repo") assert manager._is_valid_git_url("git@github.com:test/repo.git") assert manager._is_valid_git_url("git://github.com/test/repo.git") # Invalid URLs assert not manager._is_valid_git_url("") assert not manager._is_valid_git_url("not-a-url") assert not manager._is_valid_git_url("ftp://example.com/repo")

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bobmatnyc/mcp-skills'

If you have feedback or need assistance with the MCP directory API, please join our Discord server