Skip to main content
Glama
test_issue_helper.py10.4 kB
"""Test module for the issue helper script.""" import sys import json import pytest import subprocess from unittest.mock import patch, MagicMock # Add the scripts directory to the path so we can import the module directly sys.path.append('scripts') import issue_helper as ih @pytest.mark.script_test class TestIssueHelper: """Test class for the IssueHelper script.""" @patch('subprocess.run') def test_run_command(self, mock_subprocess_run): """Test running a command and getting output.""" # Mock the subprocess response mock_process = MagicMock() mock_process.returncode = 0 mock_process.stdout = "Command output" mock_process.stderr = "" mock_subprocess_run.return_value = mock_process # Call the function exit_code, stdout, stderr = ih.run_command(['gh', 'version']) # Verify the result assert exit_code == 0 assert stdout == "Command output" assert stderr == "" mock_subprocess_run.assert_called_once_with( ['gh', 'version'], check=True, capture_output=True, text=True ) @patch('subprocess.run') def test_run_command_error(self, mock_subprocess_run): """Test handling of command errors.""" # Mock a command that fails mock_subprocess_run.side_effect = subprocess.CalledProcessError( returncode=1, cmd=['gh', 'invalid'], output=b'', stderr=b'Error: unknown command' ) # Call the function with check=False to prevent sys.exit with patch('sys.exit') as mock_exit: exit_code, stdout, stderr = ih.run_command(['gh', 'invalid'], check=False) # Verify results assert exit_code == 1 mock_exit.assert_not_called() @patch('json.loads') @patch('issue_helper.run_command') def test_update_issue_status(self, mock_run_command, mock_json_loads): """Test updating an issue's status.""" # Mock first command (get current labels) mock_run_command.return_value = (0, '{"labels": [{"name": "status:prioritized"}, {"name": "priority:1"}]}', '') mock_json_loads.return_value = {"labels": [{"name": "status:prioritized"}, {"name": "priority:1"}]} # Call the function ih.update_issue_status(123, 'in-progress') # Verify that run_command was called correctly assert mock_run_command.call_count == 3 # First call should get current labels args1, _ = mock_run_command.call_args_list[0] assert args1[0][0:3] == ['gh', 'issue', 'view'] assert args1[0][3] == '123' # Second call should remove old status args2, _ = mock_run_command.call_args_list[1] assert args2[0][0:3] == ['gh', 'issue', 'edit'] assert args2[0][3] == '123' assert '--remove-label' in args2[0] assert 'status:prioritized' in args2[0] # Third call should add new status args3, _ = mock_run_command.call_args_list[2] assert args3[0][0:3] == ['gh', 'issue', 'edit'] assert args3[0][3] == '123' assert '--add-label' in args3[0] assert 'status:in-progress' in args3[0] @patch('json.loads') @patch('issue_helper.run_command') def test_get_issue_status(self, mock_run_command, mock_json_loads): """Test getting an issue's status.""" # Mock command response mock_run_command.return_value = (0, '{"labels": [{"name": "status:in-progress"}, {"name": "priority:1"}]}', '') mock_json_loads.return_value = {"labels": [{"name": "status:in-progress"}, {"name": "priority:1"}]} # Call the function status = ih.get_issue_status(123) # Verify the result assert status == 'in-progress' mock_run_command.assert_called_once() args, _ = mock_run_command.call_args assert args[0][0:3] == ['gh', 'issue', 'view'] assert args[0][3] == '123' @patch('json.loads') @patch('issue_helper.run_command') def test_get_issue_status_no_status(self, mock_run_command, mock_json_loads): """Test getting an issue's status when no status label is present.""" # Mock command response mock_run_command.return_value = (0, '{"labels": [{"name": "priority:1"}, {"name": "type:bug"}]}', '') mock_json_loads.return_value = {"labels": [{"name": "priority:1"}, {"name": "type:bug"}]} # Call the function status = ih.get_issue_status(123) # Verify the result assert status == "" @patch('builtins.print') @patch('issue_helper.get_issue_status') @patch('issue_helper.run_command') def test_check_issue_status(self, mock_run_command, mock_get_status, mock_print): """Test checking and displaying an issue's status.""" # Setup mocks mock_get_status.return_value = "in-progress" # Mock the responses for each run_command call mock_run_command.side_effect = [ # First call - issue view with title,url,labels (0, json.dumps({ "title": "Test Issue", "url": "https://github.com/user/repo/issues/123", "labels": [ {"name": "status:in-progress"}, {"name": "priority:1"} ] }), ''), # Second call - git log (commits) (0, "abcd123 Implement feature\n", ''), # Third call - PR list (0, json.dumps([ { "number": 45, "title": "Fix Issue #123", "state": "open" } ]), '') ] # Call the function ih.check_issue_status(123) # Verify expectations assert mock_run_command.call_count == 3 assert mock_print.call_count > 0 assert mock_get_status.called is False # We should use the status from the labels in the response @patch('builtins.print') @patch('builtins.input', return_value='y') @patch('os.path.exists', return_value=True) # Mock README.md exists @patch('builtins.open', new_callable=MagicMock) # Mock file open @patch('issue_helper.update_issue_status') @patch('issue_helper.get_issue_status') @patch('issue_helper.run_command') def test_start_work_on_issue(self, mock_run_command, mock_get_status, mock_update_status, mock_open, mock_path_exists, mock_input, mock_print): """Test starting work on an issue.""" # Mock status check mock_get_status.return_value = 'prioritized' # Mock the issue title lookup and git commands mock_run_command.side_effect = [ # First call - Get issue title (0, json.dumps({"title": "Test issue title"}), ''), # Second call - Check if branch exists (0, '', ''), # Empty result means branch doesn't exist # Third call - Create branch (0, '', ''), # Fourth call - Add README (0, '', ''), # Fifth call - Commit (0, '', ''), # Sixth call - Push (0, '', '') ] # Set up file mock file_mock = MagicMock() mock_open.return_value.__enter__.return_value = file_mock # Call the function ih.start_work_on_issue(123) # Verify status update was called mock_update_status.assert_called_once_with(123, 'in-progress') # Verify git commands were called assert mock_run_command.call_count >= 3 # Verify README was modified mock_open.assert_called_once() file_mock.write.assert_called_once_with('\n') @patch('builtins.print') @patch('builtins.input', return_value='y') @patch('issue_helper.get_issue_status') def test_complete_issue(self, mock_get_status, mock_input, mock_print): """Test completing an issue by creating a PR.""" # Mock status check mock_get_status.return_value = 'in-progress' # We need to mock both run_command and subprocess.run with patch('issue_helper.run_command') as mock_run_command: # Mock the issue title lookup mock_run_command.return_value = (0, json.dumps({"title": "Test Issue"}), '') # Mock subprocess.run for git commands with patch('subprocess.run') as mock_subprocess_run: # Setup mock process for git commands mock_process = MagicMock() mock_process.returncode = 0 # Return a branch name for git branch command mock_process.stdout = "feature/issue-123-test-branch" # For git status command mock_process.stderr = "" mock_subprocess_run.return_value = mock_process # Call the function ih.complete_issue(123) # Verify that correct commands were called mock_get_status.assert_called_once_with(123) assert mock_print.call_count > 0 assert mock_input.call_count > 0 @patch('issue_helper.update_issue_status') @patch('issue_helper.run_command') def test_force_update_issue_for_testing(self, mock_run_command, mock_update_status): """Test force-updating an issue's status for testing.""" # Mock so we don't actually call the GitHub CLI mock_run_command.return_value = (0, "", "") # Call the function ih.force_update_issue_for_testing(123, 'completed') # Verify update_issue_status was called with correct args mock_update_status.assert_called_once_with(123, 'completed') # Verify comment was added via run_command comment_call_found = False for call_args in mock_run_command.call_args_list: args = call_args[0][0] if 'comment' in args: comment_call_found = True break assert comment_call_found, "Expected call to add comment not found"

Latest Blog Posts

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/non-dirty/imap-mcp'

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