mirror of
https://github.com/jonasrosland/gitmirror.git
synced 2025-05-11 04:15:34 +02:00
First commit
Signed-off-by: Jonas Rosland <jonas.rosland@gmail.com>
This commit is contained in:
parent
c7c3a91f62
commit
06a77bb5e6
65 changed files with 8470 additions and 0 deletions
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
163
tests/conftest.py
Normal file
163
tests/conftest.py
Normal file
|
@ -0,0 +1,163 @@
|
|||
import os
|
||||
import pytest
|
||||
import logging
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
# Configure logging for tests
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
@pytest.fixture
|
||||
def mock_github_token():
|
||||
"""Fixture to provide a mock GitHub token."""
|
||||
return "mock_github_token"
|
||||
|
||||
@pytest.fixture
|
||||
def mock_gitea_token():
|
||||
"""Fixture to provide a mock Gitea token."""
|
||||
return "mock_gitea_token"
|
||||
|
||||
@pytest.fixture
|
||||
def mock_gitea_url():
|
||||
"""Fixture to provide a mock Gitea URL."""
|
||||
return "http://mock.gitea.url"
|
||||
|
||||
@pytest.fixture
|
||||
def mock_github_repo():
|
||||
"""Fixture to provide a mock GitHub repository."""
|
||||
return "mock_owner/mock_repo"
|
||||
|
||||
@pytest.fixture
|
||||
def mock_gitea_owner():
|
||||
"""Fixture to provide a mock Gitea owner."""
|
||||
return "mock_gitea_owner"
|
||||
|
||||
@pytest.fixture
|
||||
def mock_gitea_repo():
|
||||
"""Fixture to provide a mock Gitea repository."""
|
||||
return "mock_gitea_repo"
|
||||
|
||||
@pytest.fixture
|
||||
def mock_repo_config():
|
||||
"""Fixture to provide a mock repository configuration."""
|
||||
return {
|
||||
"mirror_metadata": True,
|
||||
"mirror_issues": True,
|
||||
"mirror_pull_requests": True,
|
||||
"mirror_labels": True,
|
||||
"mirror_milestones": True,
|
||||
"mirror_wiki": True,
|
||||
"mirror_releases": True
|
||||
}
|
||||
|
||||
@pytest.fixture
|
||||
def mock_github_release():
|
||||
"""Fixture to provide a mock GitHub release."""
|
||||
release = MagicMock()
|
||||
release.tag_name = "v1.0.0"
|
||||
release.name = "Release 1.0.0"
|
||||
release.body = "Release notes for 1.0.0"
|
||||
release.draft = False
|
||||
release.prerelease = False
|
||||
release.created_at = "2023-01-01T00:00:00Z"
|
||||
release.published_at = "2023-01-01T00:00:00Z"
|
||||
release.assets = []
|
||||
return release
|
||||
|
||||
@pytest.fixture
|
||||
def mock_github_api_responses():
|
||||
"""Fixture to provide mock responses for GitHub API calls."""
|
||||
return {
|
||||
"releases": [
|
||||
{
|
||||
"tag_name": "v1.0.0",
|
||||
"name": "Release 1.0.0",
|
||||
"body": "Release notes for 1.0.0",
|
||||
"draft": False,
|
||||
"prerelease": False,
|
||||
"created_at": "2023-01-01T00:00:00Z",
|
||||
"published_at": "2023-01-01T00:00:00Z",
|
||||
"assets": []
|
||||
}
|
||||
],
|
||||
"issues": [
|
||||
{
|
||||
"number": 1,
|
||||
"title": "Test Issue",
|
||||
"body": "This is a test issue",
|
||||
"state": "open",
|
||||
"created_at": "2023-01-01T00:00:00Z",
|
||||
"updated_at": "2023-01-01T00:00:00Z",
|
||||
"labels": [],
|
||||
"user": {"login": "test_user"}
|
||||
}
|
||||
],
|
||||
"pull_requests": [
|
||||
{
|
||||
"number": 2,
|
||||
"title": "Test PR",
|
||||
"body": "This is a test PR",
|
||||
"state": "open",
|
||||
"created_at": "2023-01-01T00:00:00Z",
|
||||
"updated_at": "2023-01-01T00:00:00Z",
|
||||
"labels": [],
|
||||
"user": {"login": "test_user"},
|
||||
"head": {"ref": "feature-branch"},
|
||||
"base": {"ref": "main"}
|
||||
}
|
||||
],
|
||||
"labels": [
|
||||
{
|
||||
"name": "bug",
|
||||
"color": "ff0000",
|
||||
"description": "Bug report"
|
||||
}
|
||||
],
|
||||
"milestones": [
|
||||
{
|
||||
"title": "v1.0",
|
||||
"description": "Version 1.0 milestone",
|
||||
"state": "open",
|
||||
"due_on": "2023-12-31T00:00:00Z"
|
||||
}
|
||||
],
|
||||
"has_wiki": True
|
||||
}
|
||||
|
||||
@pytest.fixture
|
||||
def mock_gitea_api_responses():
|
||||
"""Fixture to provide mock responses for Gitea API calls."""
|
||||
return {
|
||||
"repos": [
|
||||
{
|
||||
"name": "mock_gitea_repo",
|
||||
"owner": {"login": "mock_gitea_owner"},
|
||||
"mirror": True,
|
||||
"description": '{"github_repo": "mock_owner/mock_repo"}'
|
||||
}
|
||||
],
|
||||
"releases": [],
|
||||
"issues": [],
|
||||
"labels": [],
|
||||
"milestones": []
|
||||
}
|
||||
|
||||
@pytest.fixture
|
||||
def mock_environment(monkeypatch):
|
||||
"""Fixture to set up a mock environment for testing."""
|
||||
# Mock environment variables
|
||||
monkeypatch.setenv("GITHUB_TOKEN", "mock_github_token")
|
||||
monkeypatch.setenv("GITEA_TOKEN", "mock_gitea_token")
|
||||
monkeypatch.setenv("GITEA_URL", "http://mock.gitea.url")
|
||||
|
||||
# Create a temporary directory for test data
|
||||
os.makedirs("./test_data", exist_ok=True)
|
||||
|
||||
yield
|
||||
|
||||
# Clean up
|
||||
import shutil
|
||||
if os.path.exists("./test_data"):
|
||||
shutil.rmtree("./test_data")
|
230
tests/integration/test_mirror_integration.py
Normal file
230
tests/integration/test_mirror_integration.py
Normal file
|
@ -0,0 +1,230 @@
|
|||
import pytest
|
||||
import os
|
||||
import tempfile
|
||||
import json
|
||||
from unittest.mock import patch, MagicMock
|
||||
from gitmirror.mirror import mirror_repository
|
||||
from gitmirror.utils.config import get_repo_config, save_repo_config
|
||||
from gitmirror.github.api import get_github_releases
|
||||
from gitmirror.gitea.repository import get_gitea_repos
|
||||
from gitmirror.gitea.issue import mirror_github_issues
|
||||
from gitmirror.gitea.metadata import mirror_github_metadata
|
||||
|
||||
class TestMirrorIntegration:
|
||||
"""Integration tests for mirror functionality."""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_config_dir(self):
|
||||
"""Create a temporary directory for config files."""
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
original_config_dir = os.environ.get('GITMIRROR_CONFIG_DIR')
|
||||
os.environ['GITMIRROR_CONFIG_DIR'] = temp_dir
|
||||
yield temp_dir
|
||||
if original_config_dir:
|
||||
os.environ['GITMIRROR_CONFIG_DIR'] = original_config_dir
|
||||
else:
|
||||
os.environ.pop('GITMIRROR_CONFIG_DIR', None)
|
||||
|
||||
@patch('gitmirror.mirror.mirror_github_metadata')
|
||||
@patch('gitmirror.mirror.create_gitea_release')
|
||||
@patch('gitmirror.mirror.get_github_releases')
|
||||
@patch('gitmirror.mirror.trigger_mirror_sync')
|
||||
@patch('gitmirror.mirror.create_or_update_repo')
|
||||
def test_mirror_repository_integration(
|
||||
self,
|
||||
mock_create_or_update_repo,
|
||||
mock_trigger_mirror_sync,
|
||||
mock_get_github_releases,
|
||||
mock_create_gitea_release,
|
||||
mock_mirror_github_metadata,
|
||||
temp_config_dir
|
||||
):
|
||||
"""Test the integration of mirror_repository with its components."""
|
||||
# Set up mocks
|
||||
mock_create_or_update_repo.return_value = True
|
||||
mock_trigger_mirror_sync.return_value = True
|
||||
|
||||
mock_release = MagicMock()
|
||||
mock_release.tag_name = "v1.0.0"
|
||||
mock_get_github_releases.return_value = [mock_release]
|
||||
|
||||
mock_mirror_github_metadata.return_value = {
|
||||
"overall_success": True,
|
||||
"has_errors": False,
|
||||
"components": {}
|
||||
}
|
||||
|
||||
# Create a test config
|
||||
config = {
|
||||
'mirror_metadata': True,
|
||||
'mirror_issues': True,
|
||||
'mirror_pull_requests': True,
|
||||
'mirror_labels': True,
|
||||
'mirror_milestones': True,
|
||||
'mirror_wiki': True,
|
||||
'mirror_releases': True
|
||||
}
|
||||
save_repo_config('owner/repo', 'gitea_owner', 'gitea_repo', config)
|
||||
|
||||
# Call the function
|
||||
result = mirror_repository(
|
||||
'github_token',
|
||||
'gitea_token',
|
||||
'http://gitea.example.com',
|
||||
'owner/repo',
|
||||
'gitea_owner',
|
||||
'gitea_repo',
|
||||
force_recreate=False
|
||||
)
|
||||
|
||||
# Assertions
|
||||
assert result == True
|
||||
mock_create_or_update_repo.assert_called_once_with(
|
||||
'gitea_token',
|
||||
'http://gitea.example.com',
|
||||
'gitea_owner',
|
||||
'gitea_repo',
|
||||
'owner/repo',
|
||||
'github_token',
|
||||
force_recreate=False,
|
||||
mirror_options={
|
||||
'mirror_issues': True,
|
||||
'mirror_pull_requests': True,
|
||||
'mirror_labels': True,
|
||||
'mirror_milestones': True,
|
||||
'mirror_wiki': True,
|
||||
'mirror_releases': True
|
||||
}
|
||||
)
|
||||
mock_trigger_mirror_sync.assert_called_once()
|
||||
mock_get_github_releases.assert_called_once()
|
||||
mock_create_gitea_release.assert_called_once()
|
||||
mock_mirror_github_metadata.assert_called_once()
|
||||
|
||||
# Verify config was updated
|
||||
updated_config = get_repo_config('owner/repo', 'gitea_owner', 'gitea_repo')
|
||||
assert 'last_mirror_timestamp' in updated_config
|
||||
assert 'last_mirror_date' in updated_config
|
||||
|
||||
@patch('gitmirror.gitea.issue.requests.get')
|
||||
@patch('gitmirror.gitea.issue.requests.post')
|
||||
def test_issues_mirroring_integration(self, mock_post, mock_get, temp_config_dir):
|
||||
"""Test the integration of GitHub issues API with Gitea issues API."""
|
||||
# Set up GitHub API mock
|
||||
github_response = MagicMock()
|
||||
github_response.status_code = 200
|
||||
github_response.json.return_value = [
|
||||
{
|
||||
'number': 1,
|
||||
'title': 'Test Issue',
|
||||
'body': 'This is a test issue',
|
||||
'state': 'open',
|
||||
'user': {'login': 'testuser'},
|
||||
'created_at': '2023-01-01T00:00:00Z',
|
||||
'updated_at': '2023-01-02T00:00:00Z',
|
||||
'labels': [{'name': 'bug'}],
|
||||
'comments_url': 'https://api.github.com/repos/owner/repo/issues/1/comments',
|
||||
'html_url': 'https://github.com/owner/repo/issues/1',
|
||||
'milestone': None,
|
||||
'assignees': [],
|
||||
'closed_at': None
|
||||
}
|
||||
]
|
||||
|
||||
# Set up Gitea API mock
|
||||
gitea_response = MagicMock()
|
||||
gitea_response.status_code = 201
|
||||
gitea_response.json.return_value = {
|
||||
'id': 1,
|
||||
'number': 1,
|
||||
'title': 'Test Issue',
|
||||
'body': 'This is a test issue',
|
||||
'state': 'open'
|
||||
}
|
||||
|
||||
# Set up GitHub comments API mock
|
||||
github_comments_response = MagicMock()
|
||||
github_comments_response.status_code = 200
|
||||
github_comments_response.json.return_value = []
|
||||
|
||||
# Set up Gitea issues API mock
|
||||
gitea_issues_response = MagicMock()
|
||||
gitea_issues_response.status_code = 200
|
||||
gitea_issues_response.json.return_value = [] # No existing issues
|
||||
|
||||
# Configure mocks
|
||||
mock_get.side_effect = [github_response, gitea_issues_response, github_comments_response, gitea_issues_response]
|
||||
mock_post.return_value = gitea_response
|
||||
|
||||
# Set environment variables
|
||||
os.environ['GITHUB_TOKEN'] = 'github_token'
|
||||
os.environ['GITEA_TOKEN'] = 'gitea_token'
|
||||
os.environ['GITEA_URL'] = 'http://gitea.example.com'
|
||||
|
||||
# Call the function
|
||||
result = mirror_github_issues('gitea_token', 'http://gitea.example.com', 'gitea_owner', 'gitea_repo', 'owner/repo', 'github_token')
|
||||
|
||||
# Assertions
|
||||
assert result == True
|
||||
mock_get.assert_called()
|
||||
mock_post.assert_called_once()
|
||||
|
||||
# Clean up
|
||||
os.environ.pop('GITHUB_TOKEN', None)
|
||||
os.environ.pop('GITEA_TOKEN', None)
|
||||
os.environ.pop('GITEA_URL', None)
|
||||
|
||||
@patch('gitmirror.gitea.repository.requests.get')
|
||||
def test_repo_config_integration(self, mock_get, temp_config_dir):
|
||||
"""Test the integration of repo config with Gitea API."""
|
||||
# Set up mock
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = [
|
||||
{
|
||||
'id': 1,
|
||||
'name': 'repo1',
|
||||
'owner': {'username': 'owner1'},
|
||||
'description': 'Test repository 1',
|
||||
'mirror': True,
|
||||
'original_url': 'https://github.com/github_owner1/github_repo1',
|
||||
'mirror_interval': '8h0m0s'
|
||||
}
|
||||
]
|
||||
mock_get.return_value = mock_response
|
||||
|
||||
# Create a test config
|
||||
config = {
|
||||
'mirror_metadata': True,
|
||||
'mirror_issues': True,
|
||||
'mirror_pull_requests': True,
|
||||
'mirror_labels': True,
|
||||
'mirror_milestones': True,
|
||||
'mirror_wiki': True,
|
||||
'mirror_releases': True
|
||||
}
|
||||
save_repo_config('github_owner1/github_repo1', 'owner1', 'repo1', config)
|
||||
|
||||
# Get repos from Gitea
|
||||
repos = get_gitea_repos('token', 'http://gitea.example.com')
|
||||
|
||||
# Get config for the repo
|
||||
repo_config = get_repo_config('github_owner1/github_repo1', 'owner1', 'repo1')
|
||||
|
||||
# Assertions
|
||||
assert len(repos) == 1
|
||||
assert repos[0]['gitea_owner'] == 'owner1'
|
||||
assert repos[0]['gitea_repo'] == 'repo1'
|
||||
assert repos[0]['github_repo'] == 'github_owner1/github_repo1'
|
||||
assert repo_config['mirror_metadata'] == True
|
||||
assert repo_config['mirror_issues'] == True
|
||||
|
||||
# Modify config
|
||||
repo_config['mirror_issues'] = False
|
||||
save_repo_config('github_owner1/github_repo1', 'owner1', 'repo1', repo_config)
|
||||
|
||||
# Get updated config
|
||||
updated_config = get_repo_config('github_owner1/github_repo1', 'owner1', 'repo1')
|
||||
|
||||
# Assertions
|
||||
assert updated_config['mirror_issues'] == False
|
129
tests/test_config.py
Normal file
129
tests/test_config.py
Normal file
|
@ -0,0 +1,129 @@
|
|||
import unittest
|
||||
import os
|
||||
import json
|
||||
import tempfile
|
||||
import shutil
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
from gitmirror.utils.config import (
|
||||
load_config,
|
||||
get_default_config,
|
||||
save_default_config,
|
||||
get_repo_config,
|
||||
save_repo_config,
|
||||
get_all_repo_configs
|
||||
)
|
||||
|
||||
class TestConfig(unittest.TestCase):
|
||||
"""Test the configuration module"""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test environment"""
|
||||
# Create a temporary directory for config files
|
||||
self.temp_dir = tempfile.mkdtemp()
|
||||
self.patcher = patch('gitmirror.utils.config.get_config_dir')
|
||||
self.mock_get_config_dir = self.patcher.start()
|
||||
self.mock_get_config_dir.return_value = self.temp_dir
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up test environment"""
|
||||
self.patcher.stop()
|
||||
shutil.rmtree(self.temp_dir)
|
||||
|
||||
@patch('gitmirror.utils.config.load_dotenv')
|
||||
@patch('gitmirror.utils.config.os.getenv')
|
||||
def test_load_config(self, mock_getenv, mock_load_dotenv):
|
||||
"""Test loading configuration from environment variables"""
|
||||
# Mock environment variables
|
||||
mock_getenv.side_effect = lambda key, default=None: {
|
||||
'GITHUB_TOKEN': 'test_github_token',
|
||||
'GITEA_TOKEN': 'test_gitea_token',
|
||||
'GITEA_URL': 'https://test-gitea.com'
|
||||
}.get(key, default)
|
||||
|
||||
# Call the function
|
||||
config = load_config()
|
||||
|
||||
# Verify the result
|
||||
self.assertEqual(config['github_token'], 'test_github_token')
|
||||
self.assertEqual(config['gitea_token'], 'test_gitea_token')
|
||||
self.assertEqual(config['gitea_url'], 'https://test-gitea.com')
|
||||
|
||||
# Verify load_dotenv was called
|
||||
mock_load_dotenv.assert_called_once()
|
||||
|
||||
def test_get_default_config(self):
|
||||
"""Test getting default configuration"""
|
||||
# Create a default config file
|
||||
default_config = {
|
||||
'mirror_metadata': True,
|
||||
'mirror_issues': True,
|
||||
'mirror_pull_requests': False
|
||||
}
|
||||
|
||||
os.makedirs(self.temp_dir, exist_ok=True)
|
||||
with open(os.path.join(self.temp_dir, 'default.json'), 'w') as f:
|
||||
json.dump(default_config, f)
|
||||
|
||||
# Call the function
|
||||
config = get_default_config()
|
||||
|
||||
# Verify the result
|
||||
self.assertEqual(config['mirror_metadata'], True)
|
||||
self.assertEqual(config['mirror_issues'], True)
|
||||
self.assertEqual(config['mirror_pull_requests'], False)
|
||||
|
||||
def test_save_repo_config(self):
|
||||
"""Test saving repository configuration"""
|
||||
# Test data
|
||||
github_repo = 'owner/repo'
|
||||
gitea_owner = 'gitea_owner'
|
||||
gitea_repo = 'gitea_repo'
|
||||
config = {
|
||||
'mirror_metadata': True,
|
||||
'mirror_releases': False
|
||||
}
|
||||
|
||||
# Call the function
|
||||
result = save_repo_config(github_repo, gitea_owner, gitea_repo, config)
|
||||
|
||||
# Verify the result
|
||||
self.assertTrue(result)
|
||||
|
||||
# Verify the file was created
|
||||
config_path = os.path.join(self.temp_dir, f"{github_repo.replace('/', '_')}_{gitea_owner}_{gitea_repo}.json")
|
||||
self.assertTrue(os.path.exists(config_path))
|
||||
|
||||
# Verify the content
|
||||
with open(config_path, 'r') as f:
|
||||
saved_config = json.load(f)
|
||||
|
||||
self.assertEqual(saved_config['mirror_metadata'], True)
|
||||
self.assertEqual(saved_config['mirror_releases'], False)
|
||||
|
||||
def test_get_repo_config(self):
|
||||
"""Test getting repository configuration"""
|
||||
# Test data
|
||||
github_repo = 'owner/repo'
|
||||
gitea_owner = 'gitea_owner'
|
||||
gitea_repo = 'gitea_repo'
|
||||
config = {
|
||||
'mirror_metadata': True,
|
||||
'mirror_releases': False
|
||||
}
|
||||
|
||||
# Create a config file
|
||||
os.makedirs(self.temp_dir, exist_ok=True)
|
||||
config_path = os.path.join(self.temp_dir, f"{github_repo.replace('/', '_')}_{gitea_owner}_{gitea_repo}.json")
|
||||
with open(config_path, 'w') as f:
|
||||
json.dump(config, f)
|
||||
|
||||
# Call the function
|
||||
result = get_repo_config(github_repo, gitea_owner, gitea_repo)
|
||||
|
||||
# Verify the result
|
||||
self.assertEqual(result['mirror_metadata'], True)
|
||||
self.assertEqual(result['mirror_releases'], False)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
193
tests/unit/test_cli.py
Normal file
193
tests/unit/test_cli.py
Normal file
|
@ -0,0 +1,193 @@
|
|||
import pytest
|
||||
import sys
|
||||
import os
|
||||
from unittest.mock import patch, MagicMock
|
||||
from gitmirror.cli import main
|
||||
|
||||
class TestCLI:
|
||||
"""Test cases for CLI functionality."""
|
||||
|
||||
@patch('gitmirror.cli.mirror_repository')
|
||||
@patch('gitmirror.cli.process_all_repositories')
|
||||
@patch('os.getenv')
|
||||
def test_main_with_repo_args(
|
||||
self,
|
||||
mock_getenv,
|
||||
mock_process_all,
|
||||
mock_mirror_repository
|
||||
):
|
||||
"""Test main function with repository arguments."""
|
||||
# Set up mocks
|
||||
mock_getenv.side_effect = lambda key, default=None: {
|
||||
'GITHUB_TOKEN': 'mock_github_token',
|
||||
'GITEA_TOKEN': 'mock_gitea_token',
|
||||
'GITEA_URL': 'http://mock.gitea.url'
|
||||
}.get(key, default)
|
||||
|
||||
mock_mirror_repository.return_value = True
|
||||
|
||||
# Set up command line arguments
|
||||
test_args = ['cli.py', 'owner/repo', 'gitea_owner', 'gitea_repo']
|
||||
with patch.object(sys, 'argv', test_args):
|
||||
# Patch sys.exit to avoid exiting the test
|
||||
with patch('sys.exit') as mock_exit:
|
||||
# Call the function
|
||||
main()
|
||||
|
||||
# Assertions
|
||||
mock_mirror_repository.assert_called_once_with(
|
||||
'mock_github_token',
|
||||
'mock_gitea_token',
|
||||
'http://mock.gitea.url',
|
||||
'owner/repo',
|
||||
'gitea_owner',
|
||||
'gitea_repo',
|
||||
mirror_metadata=False,
|
||||
force_recreate=False
|
||||
)
|
||||
mock_exit.assert_called_once_with(0)
|
||||
|
||||
@patch('gitmirror.cli.process_all_repositories')
|
||||
@patch('os.getenv')
|
||||
def test_main_without_args(
|
||||
self,
|
||||
mock_getenv,
|
||||
mock_process_all
|
||||
):
|
||||
"""Test main function without arguments (auto-discovery mode)."""
|
||||
# Set up mocks
|
||||
mock_getenv.side_effect = lambda key, default=None: {
|
||||
'GITHUB_TOKEN': 'mock_github_token',
|
||||
'GITEA_TOKEN': 'mock_gitea_token',
|
||||
'GITEA_URL': 'http://mock.gitea.url'
|
||||
}.get(key, default)
|
||||
|
||||
mock_process_all.return_value = True
|
||||
|
||||
# Set up command line arguments
|
||||
test_args = ['cli.py']
|
||||
with patch.object(sys, 'argv', test_args):
|
||||
# Patch sys.exit to avoid exiting the test
|
||||
with patch('sys.exit') as mock_exit:
|
||||
# Call the function
|
||||
main()
|
||||
|
||||
# Assertions
|
||||
mock_process_all.assert_called_once_with(
|
||||
'mock_github_token',
|
||||
'mock_gitea_token',
|
||||
'http://mock.gitea.url',
|
||||
force_recreate=False,
|
||||
mirror_metadata=False
|
||||
)
|
||||
mock_exit.assert_called_once_with(0)
|
||||
|
||||
@patch('os.getenv')
|
||||
def test_main_missing_env_vars(self, mock_getenv):
|
||||
"""Test main function with missing environment variables."""
|
||||
# Set up mock to return empty string for GITEA_URL
|
||||
mock_getenv.side_effect = lambda key, default=None: {
|
||||
'GITHUB_TOKEN': 'mock_github_token',
|
||||
'GITEA_TOKEN': 'mock_gitea_token',
|
||||
'GITEA_URL': ''
|
||||
}.get(key, default)
|
||||
|
||||
# Set up command line arguments
|
||||
test_args = ['cli.py', 'owner/repo', 'gitea_owner', 'gitea_repo']
|
||||
with patch.object(sys, 'argv', test_args):
|
||||
# Patch sys.exit to avoid exiting the test
|
||||
with patch('sys.exit') as mock_exit:
|
||||
# We need to patch the load_config function to avoid file system operations
|
||||
with patch('gitmirror.cli.load_config') as mock_load_config:
|
||||
# Configure the mock to return a dictionary with empty GITEA_URL
|
||||
mock_load_config.return_value = {
|
||||
'github_token': 'mock_github_token',
|
||||
'gitea_token': 'mock_gitea_token',
|
||||
'gitea_url': ''
|
||||
}
|
||||
|
||||
# Patch mirror_repository to avoid file system operations
|
||||
with patch('gitmirror.cli.mirror_repository') as mock_mirror_repository:
|
||||
# Call the function
|
||||
main()
|
||||
|
||||
# Assertions
|
||||
# Check that sys.exit was called with 1 at some point
|
||||
assert mock_exit.call_count > 0
|
||||
assert 1 in [args[0] for args, _ in mock_exit.call_args_list]
|
||||
|
||||
@patch('gitmirror.cli.mirror_repository')
|
||||
@patch('os.getenv')
|
||||
def test_main_with_force_recreate(
|
||||
self,
|
||||
mock_getenv,
|
||||
mock_mirror_repository
|
||||
):
|
||||
"""Test main function with --force-recreate flag."""
|
||||
# Set up mocks
|
||||
mock_getenv.side_effect = lambda key, default=None: {
|
||||
'GITHUB_TOKEN': 'mock_github_token',
|
||||
'GITEA_TOKEN': 'mock_gitea_token',
|
||||
'GITEA_URL': 'http://mock.gitea.url'
|
||||
}.get(key, default)
|
||||
|
||||
mock_mirror_repository.return_value = True
|
||||
|
||||
# Set up command line arguments
|
||||
test_args = ['cli.py', 'owner/repo', 'gitea_owner', 'gitea_repo', '--force-recreate']
|
||||
with patch.object(sys, 'argv', test_args):
|
||||
# Patch sys.exit to avoid exiting the test
|
||||
with patch('sys.exit') as mock_exit:
|
||||
# Call the function
|
||||
main()
|
||||
|
||||
# Assertions
|
||||
mock_mirror_repository.assert_called_once_with(
|
||||
'mock_github_token',
|
||||
'mock_gitea_token',
|
||||
'http://mock.gitea.url',
|
||||
'owner/repo',
|
||||
'gitea_owner',
|
||||
'gitea_repo',
|
||||
mirror_metadata=False,
|
||||
force_recreate=True
|
||||
)
|
||||
mock_exit.assert_called_once_with(0)
|
||||
|
||||
@patch('gitmirror.cli.mirror_repository')
|
||||
@patch('os.getenv')
|
||||
def test_main_with_mirror_metadata(
|
||||
self,
|
||||
mock_getenv,
|
||||
mock_mirror_repository
|
||||
):
|
||||
"""Test main function with --mirror-metadata flag."""
|
||||
# Set up mocks
|
||||
mock_getenv.side_effect = lambda key, default=None: {
|
||||
'GITHUB_TOKEN': 'mock_github_token',
|
||||
'GITEA_TOKEN': 'mock_gitea_token',
|
||||
'GITEA_URL': 'http://mock.gitea.url'
|
||||
}.get(key, default)
|
||||
|
||||
mock_mirror_repository.return_value = True
|
||||
|
||||
# Set up command line arguments
|
||||
test_args = ['cli.py', 'owner/repo', 'gitea_owner', 'gitea_repo', '--mirror-metadata']
|
||||
with patch.object(sys, 'argv', test_args):
|
||||
# Patch sys.exit to avoid exiting the test
|
||||
with patch('sys.exit') as mock_exit:
|
||||
# Call the function
|
||||
main()
|
||||
|
||||
# Assertions
|
||||
mock_mirror_repository.assert_called_once_with(
|
||||
'mock_github_token',
|
||||
'mock_gitea_token',
|
||||
'http://mock.gitea.url',
|
||||
'owner/repo',
|
||||
'gitea_owner',
|
||||
'gitea_repo',
|
||||
mirror_metadata=True,
|
||||
force_recreate=False
|
||||
)
|
||||
mock_exit.assert_called_once_with(0)
|
255
tests/unit/test_gitea_api.py
Normal file
255
tests/unit/test_gitea_api.py
Normal file
|
@ -0,0 +1,255 @@
|
|||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
from gitmirror.gitea.metadata import (
|
||||
mirror_github_labels,
|
||||
mirror_github_milestones
|
||||
)
|
||||
from gitmirror.gitea.issue import mirror_github_issues
|
||||
from gitmirror.gitea.release import create_gitea_release
|
||||
from gitmirror.gitea.repository import get_gitea_repos
|
||||
|
||||
class TestGiteaApi:
|
||||
"""Test cases for Gitea API functionality."""
|
||||
|
||||
@patch('gitmirror.gitea.issue.requests.get')
|
||||
@patch('gitmirror.gitea.issue.requests.post')
|
||||
def test_mirror_github_issues(self, mock_post, mock_get):
|
||||
"""Test mirroring issues from GitHub to Gitea."""
|
||||
# Set up mock for GitHub API
|
||||
github_response = MagicMock()
|
||||
github_response.status_code = 200
|
||||
github_response.json.return_value = [
|
||||
{
|
||||
'number': 1,
|
||||
'title': 'Test Issue',
|
||||
'body': 'This is a test issue',
|
||||
'state': 'open',
|
||||
'user': {'login': 'testuser'},
|
||||
'created_at': '2023-01-01T00:00:00Z',
|
||||
'updated_at': '2023-01-02T00:00:00Z',
|
||||
'labels': [{'name': 'bug'}],
|
||||
'comments_url': 'https://api.github.com/repos/owner/repo/issues/1/comments',
|
||||
'html_url': 'https://github.com/owner/repo/issues/1'
|
||||
}
|
||||
]
|
||||
|
||||
# Set up mock for Gitea API
|
||||
gitea_response = MagicMock()
|
||||
gitea_response.status_code = 201
|
||||
gitea_response.json.return_value = {
|
||||
'id': 1,
|
||||
'number': 1,
|
||||
'title': 'Test Issue',
|
||||
'body': 'This is a test issue',
|
||||
'state': 'open'
|
||||
}
|
||||
|
||||
# Set up mock for GitHub comments API
|
||||
github_comments_response = MagicMock()
|
||||
github_comments_response.status_code = 200
|
||||
github_comments_response.json.return_value = []
|
||||
|
||||
# Configure mocks
|
||||
mock_get.side_effect = [github_response, github_comments_response]
|
||||
mock_post.return_value = gitea_response
|
||||
|
||||
# Call the function
|
||||
result = mirror_github_issues('token', 'http://gitea.example.com', 'gitea_owner', 'gitea_repo', 'owner/repo', 'github_token')
|
||||
|
||||
# Assertions
|
||||
assert result == True
|
||||
|
||||
@patch('gitmirror.gitea.metadata.requests.get')
|
||||
@patch('gitmirror.gitea.metadata.requests.post')
|
||||
def test_mirror_github_labels(self, mock_post, mock_get):
|
||||
"""Test mirroring labels from GitHub to Gitea."""
|
||||
# Set up mock for GitHub API
|
||||
github_response = MagicMock()
|
||||
github_response.status_code = 200
|
||||
github_response.json.return_value = [
|
||||
{
|
||||
'name': 'bug',
|
||||
'color': 'ff0000',
|
||||
'description': 'Bug label'
|
||||
}
|
||||
]
|
||||
|
||||
# Set up mock for Gitea API - get existing labels
|
||||
gitea_get_response = MagicMock()
|
||||
gitea_get_response.status_code = 200
|
||||
gitea_get_response.json.return_value = []
|
||||
|
||||
# Set up mock for Gitea API - create label
|
||||
gitea_post_response = MagicMock()
|
||||
gitea_post_response.status_code = 201
|
||||
gitea_post_response.json.return_value = {
|
||||
'id': 1,
|
||||
'name': 'bug',
|
||||
'color': 'ff0000',
|
||||
'description': 'Bug label'
|
||||
}
|
||||
|
||||
# Configure mocks
|
||||
mock_get.side_effect = [github_response, gitea_get_response]
|
||||
mock_post.return_value = gitea_post_response
|
||||
|
||||
# Call the function
|
||||
result = mirror_github_labels('token', 'http://gitea.example.com', 'gitea_owner', 'gitea_repo', 'owner/repo', 'github_token')
|
||||
|
||||
# Assertions
|
||||
assert result == True
|
||||
|
||||
@patch('gitmirror.gitea.metadata.requests.get')
|
||||
@patch('gitmirror.gitea.metadata.requests.post')
|
||||
def test_mirror_github_milestones(self, mock_post, mock_get):
|
||||
"""Test mirroring milestones from GitHub to Gitea."""
|
||||
# Set up mock for GitHub API
|
||||
github_response = MagicMock()
|
||||
github_response.status_code = 200
|
||||
github_response.json.return_value = [
|
||||
{
|
||||
'title': 'v1.0',
|
||||
'description': 'Version 1.0',
|
||||
'state': 'open',
|
||||
'due_on': '2023-12-31T00:00:00Z'
|
||||
}
|
||||
]
|
||||
|
||||
# Set up mock for Gitea API - get existing milestones
|
||||
gitea_get_response = MagicMock()
|
||||
gitea_get_response.status_code = 200
|
||||
gitea_get_response.json.return_value = []
|
||||
|
||||
# Set up mock for Gitea API - create milestone
|
||||
gitea_post_response = MagicMock()
|
||||
gitea_post_response.status_code = 201
|
||||
gitea_post_response.json.return_value = {
|
||||
'id': 1,
|
||||
'title': 'v1.0',
|
||||
'description': 'Version 1.0',
|
||||
'state': 'open',
|
||||
'due_on': '2023-12-31T00:00:00Z'
|
||||
}
|
||||
|
||||
# Configure mocks
|
||||
mock_get.side_effect = [github_response, gitea_get_response]
|
||||
mock_post.return_value = gitea_post_response
|
||||
|
||||
# Call the function
|
||||
result = mirror_github_milestones('token', 'http://gitea.example.com', 'gitea_owner', 'gitea_repo', 'owner/repo', 'github_token')
|
||||
|
||||
# Assertions
|
||||
assert result == True
|
||||
|
||||
@patch('gitmirror.gitea.release.check_gitea_release_exists')
|
||||
@patch('gitmirror.gitea.release.requests.post')
|
||||
def test_create_gitea_release(self, mock_post, mock_check_exists):
|
||||
"""Test creating a release in Gitea."""
|
||||
# Set up mocks
|
||||
mock_check_exists.return_value = False
|
||||
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 201
|
||||
mock_response.json.return_value = {
|
||||
'id': 1,
|
||||
'tag_name': 'v1.0.0',
|
||||
'name': 'Version 1.0.0',
|
||||
'body': 'Release notes',
|
||||
'draft': False,
|
||||
'prerelease': False
|
||||
}
|
||||
mock_post.return_value = mock_response
|
||||
|
||||
# Set up release data
|
||||
release = MagicMock()
|
||||
release.tag_name = 'v1.0.0'
|
||||
release.title = 'Version 1.0.0'
|
||||
release.body = 'Release notes'
|
||||
release.draft = False
|
||||
release.prerelease = False
|
||||
release.created_at = '2023-01-01T00:00:00Z'
|
||||
release.published_at = '2023-01-02T00:00:00Z'
|
||||
release.assets = []
|
||||
|
||||
# Call the function - the actual implementation doesn't return a value
|
||||
result = create_gitea_release('token', 'http://gitea.example.com', 'owner', 'repo', release)
|
||||
|
||||
# Assertions - we just check that the function completed without errors
|
||||
mock_post.assert_called_once()
|
||||
assert mock_post.call_args[1]['json']['tag_name'] == 'v1.0.0'
|
||||
|
||||
@patch('gitmirror.gitea.release.check_gitea_release_exists')
|
||||
@patch('gitmirror.gitea.release.requests.post')
|
||||
def test_create_gitea_release_error(self, mock_post, mock_check_exists):
|
||||
"""Test error handling when creating a release in Gitea."""
|
||||
# Set up mocks
|
||||
mock_check_exists.return_value = False
|
||||
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 400
|
||||
# Configure the raise_for_status method to raise an exception
|
||||
mock_response.raise_for_status.side_effect = Exception("Bad request")
|
||||
mock_post.return_value = mock_response
|
||||
|
||||
# Set up release data
|
||||
release = MagicMock()
|
||||
release.tag_name = 'v1.0.0'
|
||||
release.title = 'Version 1.0.0'
|
||||
release.body = 'Release notes'
|
||||
release.draft = False
|
||||
release.prerelease = False
|
||||
release.created_at = '2023-01-01T00:00:00Z'
|
||||
release.published_at = '2023-01-02T00:00:00Z'
|
||||
release.assets = []
|
||||
|
||||
# Call the function - should handle the exception gracefully
|
||||
with pytest.raises(Exception):
|
||||
create_gitea_release('token', 'http://gitea.example.com', 'owner', 'repo', release)
|
||||
|
||||
@patch('gitmirror.gitea.repository.requests.get')
|
||||
@patch('gitmirror.gitea.repository.get_repo_config')
|
||||
def test_get_gitea_repos(self, mock_get_repo_config, mock_get):
|
||||
"""Test getting repositories from Gitea."""
|
||||
# Set up mock
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = [
|
||||
{
|
||||
'id': 1,
|
||||
'name': 'repo1',
|
||||
'owner': {'username': 'owner1'},
|
||||
'description': 'Mirror of github_owner1/github_repo1',
|
||||
'mirror': True,
|
||||
'original_url': 'https://github.com/github_owner1/github_repo1',
|
||||
'mirror_interval': '8h0m0s'
|
||||
}
|
||||
]
|
||||
mock_get.return_value = mock_response
|
||||
|
||||
# Mock the get_repo_config function to avoid file system operations
|
||||
mock_get_repo_config.return_value = {}
|
||||
|
||||
# Call the function
|
||||
repos = get_gitea_repos('token', 'http://gitea.example.com')
|
||||
|
||||
# Assertions
|
||||
assert len(repos) == 1
|
||||
assert repos[0]['gitea_owner'] == 'owner1'
|
||||
assert repos[0]['gitea_repo'] == 'repo1'
|
||||
assert repos[0]['github_repo'] == 'github_owner1/github_repo1'
|
||||
assert repos[0]['is_mirror'] == True
|
||||
assert repos[0]['mirror_interval'] == '8h0m0s'
|
||||
|
||||
@patch('gitmirror.gitea.repository.requests.get')
|
||||
def test_get_gitea_repos_error(self, mock_get):
|
||||
"""Test error handling when getting repositories from Gitea."""
|
||||
# Set up mock
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 400
|
||||
mock_get.return_value = mock_response
|
||||
|
||||
# Call the function
|
||||
repos = get_gitea_repos('token', 'http://gitea.example.com')
|
||||
|
||||
# Assertions
|
||||
assert repos == []
|
229
tests/unit/test_gitea_repository.py
Normal file
229
tests/unit/test_gitea_repository.py
Normal file
|
@ -0,0 +1,229 @@
|
|||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
from gitmirror.gitea.repository import (
|
||||
get_gitea_repos,
|
||||
create_or_update_repo,
|
||||
trigger_mirror_sync
|
||||
)
|
||||
from gitmirror.gitea.repository import get_repo_config
|
||||
|
||||
class TestGiteaRepository:
|
||||
"""Test cases for Gitea repository functionality."""
|
||||
|
||||
@patch('gitmirror.gitea.repository.requests.get')
|
||||
@patch('gitmirror.gitea.repository.get_repo_config')
|
||||
def test_get_gitea_repos_success(self, mock_get_repo_config, mock_get):
|
||||
"""Test getting repositories from Gitea successfully."""
|
||||
# Set up mock
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = [
|
||||
{
|
||||
'id': 1,
|
||||
'name': 'repo1',
|
||||
'owner': {'username': 'owner1'},
|
||||
'description': 'Mirror of github_owner1/github_repo1',
|
||||
'mirror': True,
|
||||
'original_url': 'https://github.com/github_owner1/github_repo1'
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
'name': 'repo2',
|
||||
'owner': {'username': 'owner2'},
|
||||
'description': 'Mirror of github_owner2/github_repo2',
|
||||
'mirror': True,
|
||||
'original_url': 'https://github.com/github_owner2/github_repo2'
|
||||
}
|
||||
]
|
||||
mock_get.return_value = mock_response
|
||||
|
||||
# Mock the get_repo_config function to avoid file system operations
|
||||
mock_get_repo_config.return_value = {}
|
||||
|
||||
# Call the function
|
||||
repos = get_gitea_repos('token', 'http://mock.gitea.url')
|
||||
|
||||
# Assertions
|
||||
assert len(repos) == 2
|
||||
assert repos[0]["gitea_repo"] == "repo1"
|
||||
assert repos[0]["gitea_owner"] == "owner1"
|
||||
assert repos[0]["github_repo"] == "github_owner1/github_repo1"
|
||||
assert repos[0]["is_mirror"] == True
|
||||
|
||||
@patch('gitmirror.gitea.repository.requests.get')
|
||||
def test_get_gitea_repos_with_error(self, mock_get):
|
||||
"""Test getting repositories from Gitea with an error."""
|
||||
# Set up mock
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 401
|
||||
mock_get.return_value = mock_response
|
||||
|
||||
# Call the function
|
||||
repos = get_gitea_repos('token', 'http://mock.gitea.url')
|
||||
|
||||
# Assertions
|
||||
assert repos == []
|
||||
|
||||
@patch('gitmirror.gitea.repository.requests.get')
|
||||
def test_get_gitea_repos_with_exception(self, mock_get):
|
||||
"""Test getting repositories from Gitea with an exception."""
|
||||
# Set up mock to raise an exception
|
||||
mock_get.side_effect = Exception('Test exception')
|
||||
|
||||
# Call the function
|
||||
repos = get_gitea_repos('token', 'http://mock.gitea.url')
|
||||
|
||||
# Assertions
|
||||
assert repos == []
|
||||
|
||||
@patch('gitmirror.gitea.repository.requests.patch')
|
||||
@patch('gitmirror.gitea.repository.requests.get')
|
||||
@patch('gitmirror.gitea.repository.get_repo_config')
|
||||
def test_create_or_update_repo_existing(self, mock_get_repo_config, mock_get, mock_patch):
|
||||
"""Test updating an existing Gitea repository."""
|
||||
# Set up mock responses for the repository check
|
||||
mock_get_response = MagicMock()
|
||||
mock_get_response.status_code = 200
|
||||
# The API returns a dictionary, not a list
|
||||
mock_get_response.json.return_value = {
|
||||
"id": 1,
|
||||
"name": "mock_repo",
|
||||
"owner": {"login": "mock_owner"},
|
||||
"mirror": False
|
||||
}
|
||||
|
||||
# Set up mock for commits check
|
||||
mock_commits_response = MagicMock()
|
||||
mock_commits_response.status_code = 200
|
||||
mock_commits_response.json.return_value = [] # Empty repository
|
||||
|
||||
# Configure the get mock to return different responses for different URLs
|
||||
def get_side_effect(url, **kwargs):
|
||||
if url.endswith('/mock_repo'):
|
||||
return mock_get_response
|
||||
elif url.endswith('/commits'):
|
||||
return mock_commits_response
|
||||
return MagicMock()
|
||||
|
||||
mock_get.side_effect = get_side_effect
|
||||
|
||||
# Mock the delete response
|
||||
mock_delete_response = MagicMock()
|
||||
mock_delete_response.status_code = 204
|
||||
|
||||
# Mock the post response for creating a new repository
|
||||
mock_post_response = MagicMock()
|
||||
mock_post_response.status_code = 201
|
||||
|
||||
# Mock the get_repo_config function
|
||||
mock_get_repo_config.return_value = {}
|
||||
|
||||
# Mock the delete and post requests
|
||||
with patch('gitmirror.gitea.repository.requests.delete') as mock_delete:
|
||||
mock_delete.return_value = mock_delete_response
|
||||
|
||||
with patch('gitmirror.gitea.repository.requests.post') as mock_post:
|
||||
mock_post.return_value = mock_post_response
|
||||
|
||||
# Call the function with force_recreate=True
|
||||
result = create_or_update_repo(
|
||||
"mock_token",
|
||||
"http://mock.gitea.url",
|
||||
"mock_owner",
|
||||
"mock_repo",
|
||||
"github_owner/github_repo",
|
||||
"mock_github_token",
|
||||
force_recreate=True
|
||||
)
|
||||
|
||||
# Assertions
|
||||
assert result == True
|
||||
mock_delete.assert_called_once()
|
||||
mock_post.assert_called_once()
|
||||
|
||||
# Check that the JSON payload contains the expected fields
|
||||
json_payload = mock_post.call_args[1]["json"]
|
||||
assert "repo_name" in json_payload
|
||||
assert json_payload["repo_name"] == "mock_repo"
|
||||
assert json_payload["mirror"] == True
|
||||
assert "description" in json_payload
|
||||
assert "Mirror of github_owner/github_repo" in json_payload["description"]
|
||||
|
||||
@patch('gitmirror.gitea.repository.requests.post')
|
||||
@patch('gitmirror.gitea.repository.requests.get')
|
||||
def test_create_or_update_repo_new(self, mock_get, mock_post):
|
||||
"""Test creating a new Gitea repository."""
|
||||
# Set up mock responses
|
||||
mock_get_response = MagicMock()
|
||||
mock_get_response.status_code = 404
|
||||
mock_get.return_value = mock_get_response
|
||||
|
||||
mock_post_response = MagicMock()
|
||||
mock_post_response.status_code = 201
|
||||
mock_post.return_value = mock_post_response
|
||||
|
||||
# Call the function
|
||||
result = create_or_update_repo(
|
||||
"mock_token",
|
||||
"http://mock.gitea.url",
|
||||
"mock_owner",
|
||||
"mock_repo",
|
||||
"github_owner/github_repo",
|
||||
"mock_github_token",
|
||||
force_recreate=False
|
||||
)
|
||||
|
||||
# Assertions
|
||||
mock_get.assert_called_once()
|
||||
mock_post.assert_called_once()
|
||||
|
||||
# Check that the JSON payload contains the expected fields
|
||||
json_payload = mock_post.call_args[1]["json"]
|
||||
assert "repo_name" in json_payload
|
||||
assert json_payload["repo_name"] == "mock_repo"
|
||||
assert "mirror" in json_payload
|
||||
assert json_payload["mirror"] == True
|
||||
assert "description" in json_payload
|
||||
assert "Mirror of github_owner/github_repo" in json_payload["description"]
|
||||
|
||||
@patch('gitmirror.gitea.repository.requests.post')
|
||||
def test_trigger_mirror_sync_success(self, mock_post):
|
||||
"""Test triggering mirror sync successfully."""
|
||||
# Set up mock
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_post.return_value = mock_response
|
||||
|
||||
# Call the function
|
||||
result = trigger_mirror_sync('token', 'http://mock.gitea.url', 'owner', 'repo')
|
||||
|
||||
# Assertions
|
||||
assert result == True
|
||||
mock_post.assert_called_once()
|
||||
|
||||
# Check that the request was made with the correct URL and headers
|
||||
args, kwargs = mock_post.call_args
|
||||
assert args[0] == 'http://mock.gitea.url/api/v1/repos/owner/repo/mirror-sync'
|
||||
assert kwargs['headers']['Authorization'] == 'token token'
|
||||
assert kwargs['headers']['Content-Type'] == 'application/json'
|
||||
|
||||
@patch('gitmirror.gitea.repository.requests.post')
|
||||
def test_trigger_mirror_sync_failure(self, mock_post):
|
||||
"""Test triggering mirror sync with a failure."""
|
||||
# Set up mock
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 404
|
||||
mock_post.return_value = mock_response
|
||||
|
||||
# Call the function
|
||||
result = trigger_mirror_sync('token', 'http://mock.gitea.url', 'owner', 'repo')
|
||||
|
||||
# Assertions
|
||||
assert result == False
|
||||
mock_post.assert_called_once()
|
||||
|
||||
# Check that the request was made with the correct URL and headers
|
||||
args, kwargs = mock_post.call_args
|
||||
assert args[0] == 'http://mock.gitea.url/api/v1/repos/owner/repo/mirror-sync'
|
||||
assert kwargs['headers']['Authorization'] == 'token token'
|
||||
assert kwargs['headers']['Content-Type'] == 'application/json'
|
137
tests/unit/test_gitea_wiki.py
Normal file
137
tests/unit/test_gitea_wiki.py
Normal file
|
@ -0,0 +1,137 @@
|
|||
import pytest
|
||||
import logging
|
||||
from unittest.mock import patch, MagicMock, call
|
||||
import requests
|
||||
import subprocess
|
||||
from gitmirror.gitea.wiki import mirror_github_wiki, check_git_installed
|
||||
|
||||
class TestGiteaWiki:
|
||||
"""Tests for the Gitea wiki module"""
|
||||
|
||||
def test_check_git_installed_success(self):
|
||||
"""Test check_git_installed when git is installed"""
|
||||
with patch('subprocess.run') as mock_run:
|
||||
mock_run.return_value = MagicMock()
|
||||
result = check_git_installed()
|
||||
assert result is True
|
||||
mock_run.assert_called_once_with(["git", "--version"], check=True, capture_output=True)
|
||||
|
||||
def test_check_git_installed_failure(self):
|
||||
"""Test check_git_installed when git is not installed"""
|
||||
with patch('subprocess.run') as mock_run:
|
||||
mock_run.side_effect = subprocess.SubprocessError()
|
||||
result = check_git_installed()
|
||||
assert result is False
|
||||
mock_run.assert_called_once_with(["git", "--version"], check=True, capture_output=True)
|
||||
|
||||
def test_mirror_github_wiki_no_git(self):
|
||||
"""Test mirror_github_wiki when git is not installed"""
|
||||
with patch('gitmirror.gitea.wiki.check_git_installed', return_value=False):
|
||||
result = mirror_github_wiki('gitea_token', 'gitea_url', 'gitea_owner', 'gitea_repo', 'github_repo')
|
||||
assert result is False
|
||||
|
||||
def test_mirror_github_wiki_no_wiki(self):
|
||||
"""Test mirror_github_wiki when the repository doesn't have a wiki"""
|
||||
with patch('gitmirror.gitea.wiki.check_git_installed', return_value=True):
|
||||
with patch('requests.get') as mock_get:
|
||||
mock_response = MagicMock()
|
||||
mock_response.raise_for_status.return_value = None
|
||||
mock_response.json.return_value = {'has_wiki': False}
|
||||
mock_get.return_value = mock_response
|
||||
|
||||
result = mirror_github_wiki('gitea_token', 'gitea_url', 'gitea_owner', 'gitea_repo', 'github_repo')
|
||||
assert result is False
|
||||
|
||||
def test_mirror_github_wiki_wiki_not_initialized(self):
|
||||
"""Test mirror_github_wiki when the wiki is enabled but not initialized"""
|
||||
with patch('gitmirror.gitea.wiki.check_git_installed', return_value=True):
|
||||
with patch('requests.get') as mock_get:
|
||||
# First call to check if wiki is enabled
|
||||
first_response = MagicMock()
|
||||
first_response.raise_for_status.return_value = None
|
||||
first_response.json.return_value = {'has_wiki': True}
|
||||
|
||||
# Second call to check wiki contents (404 - not found)
|
||||
second_response = MagicMock()
|
||||
second_response.status_code = 404
|
||||
|
||||
# Third call to check wiki repo directly (404 - not found)
|
||||
third_response = MagicMock()
|
||||
third_response.status_code = 404
|
||||
|
||||
mock_get.side_effect = [first_response, second_response, third_response]
|
||||
|
||||
result = mirror_github_wiki('gitea_token', 'gitea_url', 'gitea_owner', 'gitea_repo', 'github_repo')
|
||||
assert result is False
|
||||
|
||||
def test_mirror_github_wiki_success(self, caplog):
|
||||
"""Test mirror_github_wiki when successful"""
|
||||
caplog.set_level(logging.INFO)
|
||||
|
||||
with patch('gitmirror.gitea.wiki.check_git_installed', return_value=True):
|
||||
with patch('requests.get') as mock_get:
|
||||
# First call to check if wiki is enabled
|
||||
first_response = MagicMock()
|
||||
first_response.raise_for_status.return_value = None
|
||||
first_response.json.return_value = {'has_wiki': True}
|
||||
|
||||
# Second call to check wiki contents (200 - found)
|
||||
second_response = MagicMock()
|
||||
second_response.status_code = 200
|
||||
|
||||
# Additional calls for repository checks
|
||||
repo_response = MagicMock()
|
||||
repo_response.status_code = 404 # Wiki repo doesn't exist yet
|
||||
|
||||
# Final call for main repo info
|
||||
main_repo_response = MagicMock()
|
||||
main_repo_response.status_code = 200
|
||||
main_repo_response.json.return_value = {'description': ''}
|
||||
|
||||
mock_get.side_effect = [first_response, second_response, repo_response, main_repo_response]
|
||||
|
||||
with patch('requests.post') as mock_post:
|
||||
create_response = MagicMock()
|
||||
create_response.status_code = 201
|
||||
mock_post.return_value = create_response
|
||||
|
||||
with patch('tempfile.TemporaryDirectory'):
|
||||
with patch('subprocess.run') as mock_run:
|
||||
mock_run.return_value = MagicMock()
|
||||
|
||||
with patch('os.path.exists', return_value=True):
|
||||
with patch('gitmirror.gitea.wiki.update_repo_description') as mock_update:
|
||||
mock_update.return_value = True
|
||||
|
||||
result = mirror_github_wiki('gitea_token', 'gitea_url', 'gitea_owner', 'gitea_repo', 'github_repo', 'github_token')
|
||||
assert result is True
|
||||
|
||||
# Check that token masking is used in logs
|
||||
assert "Using GitHub token (masked: *****token)" in caplog.text
|
||||
|
||||
def test_token_masking_in_logs(self, caplog):
|
||||
"""Test that GitHub token is masked in logs"""
|
||||
caplog.set_level(logging.INFO)
|
||||
|
||||
with patch('gitmirror.gitea.wiki.check_git_installed', return_value=True):
|
||||
with patch('requests.get') as mock_get:
|
||||
# First call to check if wiki is enabled
|
||||
first_response = MagicMock()
|
||||
first_response.raise_for_status.return_value = None
|
||||
first_response.json.return_value = {'has_wiki': True}
|
||||
|
||||
# Second call to check wiki contents (200 - found)
|
||||
second_response = MagicMock()
|
||||
second_response.status_code = 200
|
||||
|
||||
mock_get.side_effect = [first_response, second_response]
|
||||
|
||||
github_token = "github_token_value_that_should_be_masked"
|
||||
|
||||
with patch('tempfile.TemporaryDirectory'):
|
||||
# Just run the function and check that the token is masked in logs
|
||||
result = mirror_github_wiki('gitea_token', 'gitea_url', 'gitea_owner', 'gitea_repo', 'github_repo', github_token)
|
||||
|
||||
# Check that token is masked in logs
|
||||
assert github_token not in caplog.text
|
||||
assert "*****" in caplog.text
|
95
tests/unit/test_github_api.py
Normal file
95
tests/unit/test_github_api.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
from gitmirror.github.api import (
|
||||
parse_github_repo_info,
|
||||
get_github_releases
|
||||
)
|
||||
|
||||
class TestGitHubAPI:
|
||||
"""Test cases for GitHub API functionality."""
|
||||
|
||||
def test_parse_github_repo_info_with_owner_repo_format(self):
|
||||
"""Test parsing GitHub repository info with owner/repo format."""
|
||||
# Call the function
|
||||
result = parse_github_repo_info('owner/repo')
|
||||
|
||||
# Assertions
|
||||
expected = {
|
||||
'owner': 'owner',
|
||||
'repo': 'repo',
|
||||
'url': 'https://github.com/owner/repo.git',
|
||||
'full_name': 'owner/repo'
|
||||
}
|
||||
assert result == expected
|
||||
|
||||
def test_parse_github_repo_info_with_url_format(self):
|
||||
"""Test parsing GitHub repository info with URL format."""
|
||||
# Call the function
|
||||
result = parse_github_repo_info('https://github.com/owner/repo')
|
||||
|
||||
# Assertions
|
||||
expected = {
|
||||
'owner': 'owner',
|
||||
'repo': 'repo',
|
||||
'url': 'https://github.com/owner/repo.git',
|
||||
'full_name': 'owner/repo'
|
||||
}
|
||||
assert result == expected
|
||||
|
||||
def test_parse_github_repo_info_with_invalid_format(self):
|
||||
"""Test parsing GitHub repository info with invalid format."""
|
||||
# The actual implementation returns a dictionary for any URL with owner/repo format
|
||||
result = parse_github_repo_info('https://gitlab.com/owner/repo')
|
||||
|
||||
# Assertions - the function returns a dictionary for any URL with owner/repo format
|
||||
expected = {
|
||||
'owner': 'owner',
|
||||
'repo': 'repo',
|
||||
'url': 'https://gitlab.com/owner/repo.git',
|
||||
'full_name': 'owner/repo'
|
||||
}
|
||||
assert result == expected
|
||||
|
||||
@patch('gitmirror.github.api.Github')
|
||||
def test_get_github_releases(self, mock_github_class):
|
||||
"""Test getting GitHub releases."""
|
||||
# Set up mock
|
||||
mock_github = MagicMock()
|
||||
mock_github_class.return_value = mock_github
|
||||
|
||||
mock_repo = MagicMock()
|
||||
mock_github.get_repo.return_value = mock_repo
|
||||
|
||||
mock_release = MagicMock()
|
||||
mock_release.tag_name = 'v1.0.0'
|
||||
mock_release.title = 'Version 1.0.0'
|
||||
mock_release.body = 'Release notes'
|
||||
mock_release.draft = False
|
||||
mock_release.prerelease = False
|
||||
mock_release.created_at = '2023-01-01T00:00:00Z'
|
||||
mock_release.published_at = '2023-01-02T00:00:00Z'
|
||||
mock_release.assets = []
|
||||
|
||||
mock_repo.get_releases.return_value = [mock_release]
|
||||
|
||||
# Call the function
|
||||
releases = get_github_releases('token', 'owner', 'repo')
|
||||
|
||||
# Assertions
|
||||
assert releases is not None
|
||||
assert len(releases) == 1
|
||||
assert releases[0].tag_name == 'v1.0.0'
|
||||
|
||||
@patch('gitmirror.github.api.Github')
|
||||
def test_get_github_releases_with_exception(self, mock_github_class):
|
||||
"""Test getting GitHub releases with an exception."""
|
||||
# Set up mock to raise an exception
|
||||
mock_github = MagicMock()
|
||||
mock_github_class.return_value = mock_github
|
||||
mock_github.get_repo.side_effect = Exception('Test exception')
|
||||
|
||||
# Call the function
|
||||
releases = get_github_releases('token', 'owner', 'repo')
|
||||
|
||||
# Assertions
|
||||
assert releases is None
|
102
tests/unit/test_imports_and_modules.py
Normal file
102
tests/unit/test_imports_and_modules.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
import pytest
|
||||
import os
|
||||
import logging
|
||||
from unittest.mock import patch
|
||||
|
||||
# Set up logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class TestImportsAndModules:
|
||||
"""Tests for module imports and basic functionality."""
|
||||
|
||||
def test_all_imports(self):
|
||||
"""Test that all modules can be imported."""
|
||||
# Main package
|
||||
import gitmirror
|
||||
|
||||
# Subpackages
|
||||
import gitmirror.github
|
||||
import gitmirror.gitea
|
||||
import gitmirror.utils
|
||||
|
||||
# Modules
|
||||
import gitmirror.github.api
|
||||
import gitmirror.utils.logging
|
||||
import gitmirror.utils.config
|
||||
import gitmirror.mirror
|
||||
import gitmirror.cli
|
||||
import gitmirror.web
|
||||
|
||||
# Refactored modules
|
||||
import gitmirror.gitea.repository
|
||||
import gitmirror.gitea.release
|
||||
import gitmirror.gitea.wiki
|
||||
import gitmirror.gitea.comment
|
||||
import gitmirror.gitea.issue
|
||||
import gitmirror.gitea.pr
|
||||
import gitmirror.gitea.metadata
|
||||
|
||||
# If we got here without errors, all imports were successful
|
||||
assert True
|
||||
|
||||
def test_repository_module(self):
|
||||
"""Test the repository module."""
|
||||
from gitmirror.gitea.repository import get_gitea_repos
|
||||
|
||||
# Verify the function is callable
|
||||
assert callable(get_gitea_repos)
|
||||
|
||||
def test_metadata_module(self):
|
||||
"""Test the metadata module."""
|
||||
from gitmirror.gitea.metadata import mirror_github_metadata
|
||||
|
||||
# Verify the function is callable
|
||||
assert callable(mirror_github_metadata)
|
||||
|
||||
def test_wiki_module(self):
|
||||
"""Test the wiki module."""
|
||||
from gitmirror.gitea.wiki import mirror_github_wiki
|
||||
|
||||
# Verify the function is callable
|
||||
assert callable(mirror_github_wiki)
|
||||
|
||||
def test_issue_module(self):
|
||||
"""Test the issue module."""
|
||||
from gitmirror.gitea.issue import mirror_github_issues, delete_all_issues
|
||||
|
||||
# Verify the functions are callable
|
||||
assert callable(mirror_github_issues)
|
||||
assert callable(delete_all_issues)
|
||||
|
||||
def test_pr_module(self):
|
||||
"""Test the PR module."""
|
||||
from gitmirror.gitea.pr import mirror_github_prs, mirror_github_pr_review_comments
|
||||
|
||||
# Verify the functions are callable
|
||||
assert callable(mirror_github_prs)
|
||||
assert callable(mirror_github_pr_review_comments)
|
||||
|
||||
def test_comment_module(self):
|
||||
"""Test the comment module."""
|
||||
from gitmirror.gitea.comment import mirror_github_issue_comments
|
||||
|
||||
# Verify the function is callable
|
||||
assert callable(mirror_github_issue_comments)
|
||||
|
||||
def test_release_module(self):
|
||||
"""Test the release module."""
|
||||
from gitmirror.gitea.release import (
|
||||
check_gitea_release_exists,
|
||||
create_gitea_release,
|
||||
delete_release,
|
||||
mirror_release_asset,
|
||||
verify_gitea_release
|
||||
)
|
||||
|
||||
# Verify the functions are callable
|
||||
assert callable(check_gitea_release_exists)
|
||||
assert callable(create_gitea_release)
|
||||
assert callable(delete_release)
|
||||
assert callable(mirror_release_asset)
|
||||
assert callable(verify_gitea_release)
|
193
tests/unit/test_mirror.py
Normal file
193
tests/unit/test_mirror.py
Normal file
|
@ -0,0 +1,193 @@
|
|||
import pytest
|
||||
import os
|
||||
import json
|
||||
import tempfile
|
||||
from unittest.mock import patch, MagicMock, mock_open
|
||||
from gitmirror.mirror import (
|
||||
mirror_repository,
|
||||
get_repo_config,
|
||||
save_repo_config
|
||||
)
|
||||
from gitmirror.github.api import get_github_releases
|
||||
from gitmirror.gitea.repository import get_gitea_repos, create_or_update_repo, trigger_mirror_sync
|
||||
from gitmirror.gitea.release import create_gitea_release
|
||||
from gitmirror.gitea.metadata import mirror_github_metadata
|
||||
|
||||
class TestMirror:
|
||||
"""Test cases for mirror functionality."""
|
||||
|
||||
@patch('gitmirror.mirror.mirror_github_metadata')
|
||||
@patch('gitmirror.mirror.create_gitea_release')
|
||||
@patch('gitmirror.mirror.get_github_releases')
|
||||
@patch('gitmirror.mirror.trigger_mirror_sync')
|
||||
@patch('gitmirror.mirror.create_or_update_repo')
|
||||
@patch('gitmirror.mirror.get_repo_config')
|
||||
@patch('gitmirror.mirror.save_repo_config')
|
||||
def test_mirror_repository(
|
||||
self,
|
||||
mock_save_repo_config,
|
||||
mock_get_repo_config,
|
||||
mock_create_or_update_repo,
|
||||
mock_trigger_mirror_sync,
|
||||
mock_get_github_releases,
|
||||
mock_create_gitea_release,
|
||||
mock_mirror_github_metadata
|
||||
):
|
||||
"""Test the mirror_repository function."""
|
||||
# Set up mocks
|
||||
mock_get_repo_config.return_value = {
|
||||
'mirror_metadata': True,
|
||||
'mirror_issues': True,
|
||||
'mirror_pull_requests': True,
|
||||
'mirror_labels': True,
|
||||
'mirror_milestones': True,
|
||||
'mirror_wiki': True,
|
||||
'mirror_releases': True
|
||||
}
|
||||
|
||||
mock_create_or_update_repo.return_value = True
|
||||
mock_trigger_mirror_sync.return_value = True
|
||||
|
||||
mock_release = MagicMock()
|
||||
mock_release.tag_name = "v1.0.0"
|
||||
mock_get_github_releases.return_value = [mock_release]
|
||||
|
||||
mock_mirror_github_metadata.return_value = {
|
||||
"overall_success": True,
|
||||
"has_errors": False,
|
||||
"components": {}
|
||||
}
|
||||
|
||||
# Call the function
|
||||
result = mirror_repository(
|
||||
'github_token',
|
||||
'gitea_token',
|
||||
'http://gitea.example.com',
|
||||
'owner/repo',
|
||||
'gitea_owner',
|
||||
'gitea_repo',
|
||||
force_recreate=False
|
||||
)
|
||||
|
||||
# Assertions
|
||||
assert result == True
|
||||
mock_create_or_update_repo.assert_called_once_with(
|
||||
'gitea_token',
|
||||
'http://gitea.example.com',
|
||||
'gitea_owner',
|
||||
'gitea_repo',
|
||||
'owner/repo',
|
||||
'github_token',
|
||||
force_recreate=False,
|
||||
mirror_options={
|
||||
'mirror_issues': True,
|
||||
'mirror_pull_requests': True,
|
||||
'mirror_labels': True,
|
||||
'mirror_milestones': True,
|
||||
'mirror_wiki': True,
|
||||
'mirror_releases': True
|
||||
}
|
||||
)
|
||||
mock_trigger_mirror_sync.assert_called_once()
|
||||
mock_get_github_releases.assert_called_once()
|
||||
mock_create_gitea_release.assert_called_once()
|
||||
mock_mirror_github_metadata.assert_called_once()
|
||||
|
||||
# Check that save_repo_config was called with updated config
|
||||
saved_config = mock_save_repo_config.call_args[0][3]
|
||||
assert "last_mirror_timestamp" in saved_config
|
||||
assert "last_mirror_date" in saved_config
|
||||
|
||||
@patch('gitmirror.mirror.create_or_update_repo')
|
||||
@patch('gitmirror.mirror.get_repo_config')
|
||||
def test_mirror_repository_failure(
|
||||
self,
|
||||
mock_get_repo_config,
|
||||
mock_create_or_update_repo
|
||||
):
|
||||
"""Test mirroring a repository with a failure."""
|
||||
# Set up mocks
|
||||
mock_get_repo_config.return_value = {
|
||||
'mirror_metadata': True,
|
||||
'mirror_issues': True,
|
||||
'mirror_pull_requests': True,
|
||||
'mirror_labels': True,
|
||||
'mirror_milestones': True,
|
||||
'mirror_wiki': True,
|
||||
'mirror_releases': True
|
||||
}
|
||||
|
||||
mock_create_or_update_repo.return_value = False
|
||||
|
||||
# Call the function
|
||||
result = mirror_repository(
|
||||
'github_token',
|
||||
'gitea_token',
|
||||
'http://gitea.example.com',
|
||||
'owner/repo',
|
||||
'gitea_owner',
|
||||
'gitea_repo',
|
||||
force_recreate=False
|
||||
)
|
||||
|
||||
# Assertions
|
||||
assert result == False
|
||||
mock_create_or_update_repo.assert_called_once_with(
|
||||
'gitea_token',
|
||||
'http://gitea.example.com',
|
||||
'gitea_owner',
|
||||
'gitea_repo',
|
||||
'owner/repo',
|
||||
'github_token',
|
||||
force_recreate=False,
|
||||
mirror_options={
|
||||
'mirror_issues': True,
|
||||
'mirror_pull_requests': True,
|
||||
'mirror_labels': True,
|
||||
'mirror_milestones': True,
|
||||
'mirror_wiki': True,
|
||||
'mirror_releases': True
|
||||
}
|
||||
)
|
||||
|
||||
@patch('gitmirror.utils.config.get_config_dir')
|
||||
@patch('os.path.exists')
|
||||
@patch('builtins.open', new_callable=mock_open, read_data='{"mirror_metadata": true}')
|
||||
def test_get_repo_config(self, mock_file, mock_exists, mock_get_config_dir):
|
||||
"""Test the get_repo_config function."""
|
||||
# Set up mocks
|
||||
mock_exists.return_value = True
|
||||
mock_get_config_dir.return_value = '/tmp/config'
|
||||
|
||||
# Call the function
|
||||
config = get_repo_config('owner/repo', 'gitea_owner', 'gitea_repo')
|
||||
|
||||
# Assertions
|
||||
assert config['mirror_metadata'] == True
|
||||
mock_file.assert_called_once()
|
||||
|
||||
@patch('gitmirror.utils.config.get_repo_config_path')
|
||||
@patch('builtins.open', new_callable=mock_open)
|
||||
def test_save_repo_config(self, mock_file, mock_get_repo_config_path):
|
||||
"""Test the save_repo_config function."""
|
||||
# Set up config
|
||||
config = {
|
||||
'mirror_metadata': True,
|
||||
'mirror_issues': True,
|
||||
'mirror_pull_requests': True,
|
||||
'mirror_labels': True,
|
||||
'mirror_milestones': True,
|
||||
'mirror_wiki': True,
|
||||
'mirror_releases': True
|
||||
}
|
||||
|
||||
# Set up mocks
|
||||
mock_get_repo_config_path.return_value = '/tmp/config/owner_repo_gitea_owner_gitea_repo.json'
|
||||
|
||||
# Call the function
|
||||
result = save_repo_config('owner/repo', 'gitea_owner', 'gitea_repo', config)
|
||||
|
||||
# Assertions
|
||||
assert result == True
|
||||
mock_file.assert_called_once_with('/tmp/config/owner_repo_gitea_owner_gitea_repo.json', 'w')
|
||||
mock_file().write.assert_called()
|
186
tests/unit/test_web.py
Normal file
186
tests/unit/test_web.py
Normal file
|
@ -0,0 +1,186 @@
|
|||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch, MagicMock
|
||||
import pytest
|
||||
from flask import Flask, request, jsonify
|
||||
|
||||
# Import the original app for reference but create a new one for testing
|
||||
from gitmirror.web import app as original_app
|
||||
|
||||
class TestWeb(unittest.TestCase):
|
||||
"""Test the web module."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up the app for testing."""
|
||||
# Create a test Flask app
|
||||
self.app = Flask(__name__)
|
||||
self.app.config['TESTING'] = True
|
||||
self.app.config['WTF_CSRF_ENABLED'] = False
|
||||
|
||||
# Create a test client
|
||||
self.client = self.app.test_client()
|
||||
|
||||
# Create temporary directories for testing
|
||||
self.temp_config_dir = tempfile.mkdtemp()
|
||||
self.temp_logs_dir = tempfile.mkdtemp()
|
||||
|
||||
# Set environment variables
|
||||
os.environ['GITMIRROR_CONFIG_DIR'] = self.temp_config_dir
|
||||
os.environ['GITMIRROR_LOGS_DIR'] = self.temp_logs_dir
|
||||
|
||||
# Create a test log file
|
||||
self.test_log_path = os.path.join(self.temp_logs_dir, 'test.log')
|
||||
with open(self.test_log_path, 'w') as f:
|
||||
f.write('Test log content')
|
||||
|
||||
# Set up basic routes for testing
|
||||
@self.app.route('/')
|
||||
def index():
|
||||
return '<h1>GitHub to Gitea Mirror</h1>'
|
||||
|
||||
@self.app.route('/logs')
|
||||
def logs():
|
||||
return f'<div>test.log</div>'
|
||||
|
||||
@self.app.route('/logs/test.log')
|
||||
def view_log():
|
||||
with open(self.test_log_path, 'r') as f:
|
||||
content = f.read()
|
||||
return content
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up after tests."""
|
||||
# Clean up
|
||||
os.remove(self.test_log_path)
|
||||
os.rmdir(self.temp_config_dir)
|
||||
os.rmdir(self.temp_logs_dir)
|
||||
|
||||
def test_index_route(self):
|
||||
"""Test the index route."""
|
||||
# Call the route
|
||||
response = self.client.get('/')
|
||||
|
||||
# Assertions
|
||||
assert response.status_code == 200
|
||||
assert b'GitHub to Gitea Mirror' in response.data
|
||||
|
||||
def test_health_route(self):
|
||||
"""Test the health route."""
|
||||
# Add a health route for testing
|
||||
@self.app.route('/health')
|
||||
def health_check():
|
||||
return jsonify({'status': 'healthy'})
|
||||
|
||||
# Call the route
|
||||
response = self.client.get('/health')
|
||||
|
||||
# Assertions
|
||||
assert response.status_code == 200
|
||||
assert b'healthy' in response.data
|
||||
|
||||
def test_api_repos_route(self):
|
||||
"""Test the API repos route."""
|
||||
# Mock data
|
||||
repos_data = [
|
||||
{
|
||||
'github_repo': 'test/repo1',
|
||||
'gitea_owner': 'test',
|
||||
'gitea_repo': 'repo1',
|
||||
'config': {
|
||||
'mirror_metadata': True
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
# Add a route for testing
|
||||
@self.app.route('/api/repos')
|
||||
def api_repos():
|
||||
return jsonify(repos_data)
|
||||
|
||||
# Call the route
|
||||
response = self.client.get('/api/repos')
|
||||
|
||||
# Assertions
|
||||
assert response.status_code == 200
|
||||
data = response.get_json()
|
||||
assert len(data) == 1
|
||||
assert data[0]['github_repo'] == 'test/repo1'
|
||||
assert 'config' in data[0]
|
||||
|
||||
def test_api_repo_config_route(self):
|
||||
"""Test the API repo config route."""
|
||||
# Mock data
|
||||
config_data = {
|
||||
'mirror_metadata': True,
|
||||
'mirror_issues': True,
|
||||
'mirror_pull_requests': True,
|
||||
'mirror_labels': True,
|
||||
'mirror_milestones': True,
|
||||
'mirror_wiki': True,
|
||||
'mirror_releases': True
|
||||
}
|
||||
|
||||
# Add a test route
|
||||
@self.app.route('/api/repos/test/repo/config', methods=['GET'])
|
||||
def get_repo_config():
|
||||
return jsonify(config_data)
|
||||
|
||||
# Call the route
|
||||
response = self.client.get('/api/repos/test/repo/config')
|
||||
|
||||
# Assertions
|
||||
assert response.status_code == 200
|
||||
data = response.get_json()
|
||||
assert data['mirror_metadata'] is True
|
||||
|
||||
def test_api_repo_config_update_route(self):
|
||||
"""Test the API repo config update route."""
|
||||
# Mock data
|
||||
config_data = {
|
||||
'mirror_metadata': True,
|
||||
'mirror_issues': True,
|
||||
'mirror_pull_requests': True,
|
||||
'mirror_labels': True,
|
||||
'mirror_milestones': True,
|
||||
'mirror_wiki': True,
|
||||
'mirror_releases': True
|
||||
}
|
||||
|
||||
# Add a test route
|
||||
@self.app.route('/api/repos/test/repo/config', methods=['POST'])
|
||||
def update_repo_config():
|
||||
updated_config = config_data.copy()
|
||||
updated_config.update(request.json)
|
||||
return jsonify(updated_config)
|
||||
|
||||
# Call the route with JSON data
|
||||
response = self.client.post('/api/repos/test/repo/config',
|
||||
json={
|
||||
'mirror_metadata': False,
|
||||
'mirror_issues': False
|
||||
})
|
||||
|
||||
# Assertions
|
||||
assert response.status_code == 200
|
||||
data = response.get_json()
|
||||
assert data['mirror_metadata'] is False
|
||||
assert data['mirror_issues'] is False
|
||||
|
||||
def test_logs_route(self):
|
||||
"""Test the logs route."""
|
||||
# Call the route
|
||||
response = self.client.get('/logs')
|
||||
|
||||
# Assertions
|
||||
assert response.status_code == 200
|
||||
assert b'test.log' in response.data
|
||||
|
||||
def test_log_file_route(self):
|
||||
"""Test the log file route."""
|
||||
# Call the route
|
||||
response = self.client.get('/logs/test.log')
|
||||
|
||||
# Assertions
|
||||
assert response.status_code == 200
|
||||
assert b'Test log content' in response.data
|
Loading…
Add table
Add a link
Reference in a new issue