Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| """ | |
| Unit tests for the Repository Service | |
| """ | |
| import unittest | |
| from unittest.mock import patch, MagicMock | |
| import os | |
| import sys | |
| import shutil | |
| from pathlib import Path | |
| # Add the project root directory to the Python path | |
| project_root = Path(__file__).resolve().parent.parent | |
| sys.path.insert(0, str(project_root)) | |
| from src.services.repository_service import ( | |
| validate_github_url, | |
| normalize_github_url, | |
| extract_repo_name, | |
| clone_repository, | |
| get_repository_info, | |
| cleanup_repository, | |
| cleanup_all_repositories | |
| ) | |
| class TestRepositoryService(unittest.TestCase): | |
| """Test cases for the repository service functions""" | |
| def setUp(self): | |
| """Set up test fixtures""" | |
| self.test_repo_dir = "test_repos" | |
| os.makedirs(self.test_repo_dir, exist_ok=True) | |
| def tearDown(self): | |
| """Tear down test fixtures""" | |
| if os.path.exists(self.test_repo_dir): | |
| shutil.rmtree(self.test_repo_dir) | |
| def test_validate_github_url(self): | |
| """Test validate_github_url function""" | |
| # Valid URLs | |
| self.assertTrue(validate_github_url("https://github.com/user/repo")) | |
| self.assertTrue(validate_github_url("https://github.com/user/repo.git")) | |
| self.assertTrue(validate_github_url("git@github.com:user/repo.git")) | |
| self.assertTrue(validate_github_url("https://github.com/user/repo-with-dash")) | |
| self.assertTrue(validate_github_url("https://github.com/user/repo_with_underscore")) | |
| # Invalid URLs | |
| self.assertFalse(validate_github_url("https://gitlab.com/user/repo")) | |
| self.assertFalse(validate_github_url("https://github.com")) | |
| self.assertFalse(validate_github_url("https://github.com/user")) | |
| self.assertFalse(validate_github_url("not a url")) | |
| def test_normalize_github_url(self): | |
| """Test normalize_github_url function""" | |
| # HTTPS URLs | |
| self.assertEqual( | |
| normalize_github_url("https://github.com/user/repo"), | |
| "https://github.com/user/repo.git" | |
| ) | |
| self.assertEqual( | |
| normalize_github_url("https://github.com/user/repo.git"), | |
| "https://github.com/user/repo.git" | |
| ) | |
| # SSH URLs | |
| self.assertEqual( | |
| normalize_github_url("git@github.com:user/repo.git"), | |
| "https://github.com/user/repo.git" | |
| ) | |
| self.assertEqual( | |
| normalize_github_url("git@github.com:user/repo"), | |
| "https://github.com/user/repo.git" | |
| ) | |
| # URLs with trailing slashes | |
| self.assertEqual( | |
| normalize_github_url("https://github.com/user/repo/"), | |
| "https://github.com/user/repo.git" | |
| ) | |
| # Invalid URLs should return None | |
| self.assertIsNone(normalize_github_url("https://gitlab.com/user/repo")) | |
| self.assertIsNone(normalize_github_url("not a url")) | |
| def test_extract_repo_name(self): | |
| """Test extract_repo_name function""" | |
| self.assertEqual(extract_repo_name("https://github.com/user/repo"), "repo") | |
| self.assertEqual(extract_repo_name("https://github.com/user/repo.git"), "repo") | |
| self.assertEqual(extract_repo_name("git@github.com:user/repo.git"), "repo") | |
| self.assertEqual(extract_repo_name("https://github.com/user/repo-with-dash"), "repo-with-dash") | |
| # Invalid URLs should return None | |
| self.assertIsNone(extract_repo_name("https://github.com")) | |
| self.assertIsNone(extract_repo_name("not a url")) | |
| def test_clone_repository(self, mock_clone_from): | |
| """Test clone_repository function""" | |
| # Mock the Git clone operation | |
| mock_repo = MagicMock() | |
| mock_clone_from.return_value = mock_repo | |
| # Test with default branch | |
| repo_path = clone_repository( | |
| "https://github.com/user/repo", | |
| output_dir=self.test_repo_dir | |
| ) | |
| # Verify the result | |
| expected_path = os.path.join(self.test_repo_dir, "repo") | |
| self.assertEqual(repo_path, expected_path) | |
| mock_clone_from.assert_called_once() | |
| # Test with specific branch | |
| mock_clone_from.reset_mock() | |
| repo_path = clone_repository( | |
| "https://github.com/user/repo", | |
| branch="dev", | |
| output_dir=self.test_repo_dir | |
| ) | |
| # Verify the result | |
| self.assertEqual(repo_path, expected_path) | |
| mock_clone_from.assert_called_once() | |
| # Test with invalid URL | |
| with self.assertRaises(ValueError): | |
| clone_repository( | |
| "not a url", | |
| output_dir=self.test_repo_dir | |
| ) | |
| def test_get_repository_info(self, mock_walk, mock_getsize, mock_repo): | |
| """Test get_repository_info function""" | |
| # Mock the Git repository | |
| mock_repo_instance = MagicMock() | |
| mock_repo.return_value = mock_repo_instance | |
| # Mock the active branch | |
| mock_branch = MagicMock() | |
| mock_branch.name = "main" | |
| mock_repo_instance.active_branch = mock_branch | |
| # Mock the head commit | |
| mock_commit = MagicMock() | |
| mock_commit.hexsha = "abc123" | |
| mock_repo_instance.head.commit = mock_commit | |
| # Mock the remote URL | |
| mock_remote = MagicMock() | |
| mock_remote.url = "https://github.com/user/repo.git" | |
| mock_repo_instance.remotes.origin = mock_remote | |
| # Mock the repository size | |
| mock_getsize.return_value = 1024 | |
| # Mock the file count | |
| mock_walk.return_value = [ | |
| ("/test/repo", ["dir1"], ["file1.py", "file2.py"]), | |
| ("/test/repo/dir1", [], ["file3.py"]) | |
| ] | |
| # Test the function | |
| repo_info = get_repository_info("/test/repo") | |
| # Verify the result | |
| self.assertEqual(repo_info["branch"], "main") | |
| self.assertEqual(repo_info["commit"], "abc123") | |
| self.assertEqual(repo_info["remote_url"], "https://github.com/user/repo.git") | |
| self.assertEqual(repo_info["size"], 1024) | |
| self.assertEqual(repo_info["file_count"], 3) | |
| def test_cleanup_repository(self, mock_exists, mock_rmtree): | |
| """Test cleanup_repository function""" | |
| # Mock the path exists check | |
| mock_exists.return_value = True | |
| # Test the function | |
| cleanup_repository("/test/repo") | |
| # Verify the result | |
| mock_exists.assert_called_once_with("/test/repo") | |
| mock_rmtree.assert_called_once_with("/test/repo") | |
| # Test with non-existent path | |
| mock_exists.reset_mock() | |
| mock_rmtree.reset_mock() | |
| mock_exists.return_value = False | |
| cleanup_repository("/test/repo") | |
| mock_exists.assert_called_once_with("/test/repo") | |
| mock_rmtree.assert_not_called() | |
| def test_cleanup_all_repositories(self, mock_rmtree, mock_isdir, mock_listdir): | |
| """Test cleanup_all_repositories function""" | |
| # Mock the directory listing | |
| mock_listdir.return_value = ["repo1", "repo2", "file.txt"] | |
| # Mock the isdir check | |
| mock_isdir.side_effect = lambda path: path.endswith("repo1") or path.endswith("repo2") | |
| # Test the function | |
| cleanup_all_repositories(self.test_repo_dir) | |
| # Verify the result | |
| mock_listdir.assert_called_once_with(self.test_repo_dir) | |
| self.assertEqual(mock_isdir.call_count, 3) # Called for each item in the directory | |
| self.assertEqual(mock_rmtree.call_count, 2) # Called for each directory | |
| if __name__ == "__main__": | |
| unittest.main() |