JIRA MCP Tools
by NZenitram
Verified
- mcp-jira
- tests
#!/usr/bin/env python3
"""Test the JIRA issue transition tool with mocking."""
import unittest
from unittest.mock import patch, MagicMock
import logging
from src.tools.issues import transition_issue
# Set up logging
logging.basicConfig(level=logging.INFO, format='%(message)s')
logger = logging.getLogger(__name__)
class TestTransitionIssue(unittest.TestCase):
"""Test cases for transition_issue using mocks."""
def setUp(self):
"""Set up test fixtures before each test method."""
self.issue_key = "TEST-123"
self.target_status = "In Progress"
self.comment = "Transitioning to In Progress"
# Mock issue object and its fields
self.mock_issue = MagicMock()
self.mock_issue.key = self.issue_key
self.mock_fields = MagicMock()
self.mock_fields.status = MagicMock()
self.mock_fields.status.name = "Open" # Initial status
self.mock_issue.fields = self.mock_fields
# Mock JIRA client
self.mock_jira = MagicMock()
self.mock_jira._options = {'server': 'https://test-jira.atlassian.net'}
self.mock_jira.issue.return_value = self.mock_issue
# Mock available transitions
self.mock_transitions = [
{'id': '2', 'name': 'In Progress'},
{'id': '3', 'name': 'Done'},
{'id': '4', 'name': 'Blocked'}
]
self.mock_jira.transitions.return_value = self.mock_transitions
@patch('src.tools.issues.initialize_jira')
def test_transition_success(self, mock_init_jira):
"""Test successful issue transition."""
# Set up mock
mock_init_jira.return_value = self.mock_jira
# Update mock for status after transition
updated_issue = MagicMock()
updated_fields = MagicMock()
updated_fields.status = MagicMock()
updated_fields.status.name = self.target_status
updated_issue.fields = updated_fields
self.mock_jira.issue.side_effect = [self.mock_issue, updated_issue]
# Call the function
result = transition_issue(self.issue_key, self.target_status, self.comment)
# Verify JIRA client calls
mock_init_jira.assert_called_once()
self.mock_jira.transitions.assert_called_once_with(self.mock_issue)
self.mock_jira.transition_issue.assert_called_once()
# Verify transition data
transition_call = self.mock_jira.transition_issue.call_args
self.assertEqual(transition_call[0][0], self.mock_issue) # First arg is issue
self.assertEqual(transition_call[0][1], '2') # Second arg is transition ID
# Verify response structure
self.assertEqual(result['status'], 'success')
self.assertEqual(result['details']['issue_key'], self.issue_key)
self.assertEqual(result['details']['previous_status'], 'Open')
self.assertEqual(result['details']['new_status'], self.target_status)
self.assertEqual(result['details']['comment_added'], True)
self.assertEqual(
result['details']['url'],
f"https://test-jira.atlassian.net/browse/{self.issue_key}"
)
logger.info(f"Successfully transitioned issue {self.issue_key} from Open to {self.target_status}")
@patch('src.tools.issues.initialize_jira')
def test_transition_invalid_status(self, mock_init_jira):
"""Test transition with invalid target status."""
# Set up mock
mock_init_jira.return_value = self.mock_jira
invalid_status = "Invalid Status"
# Verify that attempting invalid transition raises ValueError
with self.assertRaises(ValueError) as context:
transition_issue(self.issue_key, invalid_status)
# Verify error message contains available transitions
error_msg = str(context.exception)
self.assertIn(invalid_status, error_msg)
self.assertIn("Available transitions", error_msg)
for transition in ['In Progress', 'Done', 'Blocked']:
self.assertIn(transition, error_msg)
logger.info("Successfully prevented transition to invalid status")
@patch('src.tools.issues.initialize_jira')
def test_transition_issue_not_found(self, mock_init_jira):
"""Test transition of non-existent issue."""
# Set up mock to return None for non-existent issue
self.mock_jira.issue.return_value = None
mock_init_jira.return_value = self.mock_jira
# Verify that attempting to transition non-existent issue raises ValueError
with self.assertRaises(ValueError) as context:
transition_issue(self.issue_key, self.target_status)
self.assertEqual(str(context.exception), f"Issue {self.issue_key} not found")
logger.info("Successfully prevented transition of non-existent issue")
if __name__ == '__main__':
unittest.main()