fix: resolve issue-facade ID mapping bugs and enhance functionality

- Fix Sentinel bug in list command where Click set search params to Sentinel.UNSET
- Fix version command by adding explicit version and package_name parameters
- Fix test isolation by correcting mock patch targets and datetime objects
- Fix critical ID mapping bug: use issue.number consistently instead of mixing with issue.backend_id
- Update all comment operations to use issue numbers instead of internal IDs
- Ensure issue-facade uses upstream issue numbers directly without local ID confusion
- Add comprehensive test coverage with 20 passing tests
- Verify core functionality: list, show, close, version, backend management all working
- Successfully close issue #166 with proper comment handling

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-10 10:48:31 +01:00
parent 00b9834d2f
commit 34a8bc7d4c
19 changed files with 469 additions and 13 deletions

195
tests/test_gitea_backend.py Normal file
View File

@@ -0,0 +1,195 @@
"""
Test suite for Gitea backend functionality.
These tests ensure the Gitea backend works correctly with the API.
"""
import pytest
import json
from unittest.mock import Mock, patch, MagicMock
from issue_tracker.backends.gitea.backend import GiteaBackend, GiteaAPIError
class TestGiteaBackend:
"""Test Gitea backend implementation."""
def setup_method(self):
"""Set up test environment."""
self.backend = GiteaBackend()
self.test_config = {
'type': 'gitea',
'base_url': 'https://git.example.com',
'owner': 'testorg',
'repo': 'testrepo',
'token': 'test-token'
}
def test_backend_initialization(self):
"""Test backend initializes correctly."""
assert self.backend.base_url is None
assert self.backend.token is None
assert self.backend.owner is None
assert self.backend.repo is None
assert self.backend.session is not None
@patch('issue_tracker.backends.gitea.backend.requests.Session')
def test_connect_success(self, mock_session_class):
"""Test successful connection to Gitea API."""
mock_session = MagicMock()
mock_session_class.return_value = mock_session
# Mock successful API response
mock_response = Mock()
mock_response.status_code = 200
mock_session.request.return_value = mock_response
backend = GiteaBackend()
backend.session = mock_session
backend.connect(self.test_config)
# Verify configuration is set
assert backend.base_url == 'https://git.example.com'
assert backend.token == 'test-token'
assert backend.owner == 'testorg'
assert backend.repo == 'testrepo'
# Verify headers are set
mock_session.headers.update.assert_called_once_with({
'Authorization': 'token test-token',
'Content-Type': 'application/json',
'Accept': 'application/json'
})
@patch('issue_tracker.backends.gitea.backend.requests.Session')
def test_connect_failure(self, mock_session_class):
"""Test failed connection raises appropriate error."""
mock_session = MagicMock()
mock_session_class.return_value = mock_session
# Mock failed API response
mock_response = Mock()
mock_response.status_code = 404
mock_session.request.return_value = mock_response
backend = GiteaBackend()
backend.session = mock_session
with pytest.raises(GiteaAPIError, match="Failed to connect to Gitea API"):
backend.connect(self.test_config)
def test_url_construction_fix(self):
"""Test that URL construction properly handles urljoin edge cases."""
backend = GiteaBackend()
backend.base_url = 'https://git.example.com'
# Test the fixed _api_request URL construction
with patch.object(backend.session, 'request') as mock_request:
mock_response = Mock()
mock_response.status_code = 200
mock_request.return_value = mock_response
backend._api_request('GET', '/repos/owner/repo')
# Verify the correct URL was called
mock_request.assert_called_once()
called_url = mock_request.call_args[1]['url'] if 'url' in mock_request.call_args[1] else mock_request.call_args[0][1]
assert called_url == 'https://git.example.com/api/v1/repos/owner/repo'
@patch('issue_tracker.backends.gitea.backend.requests.Session')
def test_test_connection_success(self, mock_session_class):
"""Test test_connection method works correctly."""
mock_session = MagicMock()
mock_session_class.return_value = mock_session
# Mock successful API response
mock_response = Mock()
mock_response.status_code = 200
mock_session.request.return_value = mock_response
backend = GiteaBackend()
backend.session = mock_session
backend.base_url = 'https://git.example.com'
backend.owner = 'testorg'
backend.repo = 'testrepo'
backend.token = 'test-token'
result = backend.test_connection()
assert result is True
@patch('issue_tracker.backends.gitea.backend.requests.Session')
def test_test_connection_failure(self, mock_session_class):
"""Test test_connection handles failures gracefully."""
mock_session = MagicMock()
mock_session_class.return_value = mock_session
# Mock failed API response
mock_response = Mock()
mock_response.status_code = 404
mock_response.raise_for_status.side_effect = Exception("404 Not Found")
mock_session.request.return_value = mock_response
backend = GiteaBackend()
backend.session = mock_session
backend.base_url = 'https://git.example.com'
backend.owner = 'testorg'
backend.repo = 'testrepo'
backend.token = 'test-token'
result = backend.test_connection()
assert result is False
@patch('issue_tracker.backends.gitea.backend.requests.Session')
def test_get_issue_success(self, mock_session_class):
"""Test successful issue retrieval."""
mock_session = MagicMock()
mock_session_class.return_value = mock_session
# Mock Gitea issue response
gitea_issue = {
"id": 123,
"number": 42,
"title": "Test Issue",
"body": "Test description",
"state": "open",
"user": {"login": "testuser", "email": "test@example.com"},
"created_at": "2023-01-01T12:00:00Z",
"updated_at": "2023-01-01T12:00:00Z",
"labels": [],
"assignees": [],
"milestone": None,
"comments": 0
}
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = gitea_issue
mock_session.request.return_value = mock_response
backend = GiteaBackend()
backend.session = mock_session
backend.base_url = 'https://git.example.com'
backend.owner = 'testorg'
backend.repo = 'testrepo'
backend.token = 'test-token'
issue = backend.get_issue(42)
assert issue.number == 42
assert issue.title == "Test Issue"
assert issue.description == "Test description"
assert issue.state.value == "open"
def test_disconnect(self):
"""Test disconnect method cleans up properly."""
self.backend.base_url = 'https://git.example.com'
self.backend.token = 'test-token'
self.backend.owner = 'testorg'
self.backend.repo = 'testrepo'
self.backend.disconnect()
assert self.backend.base_url is None
assert self.backend.token is None
assert self.backend.owner is None
assert self.backend.repo is None