diff --git a/tests/test_issue_creator.py b/tests/test_issue_creator.py index 13a6efbf..548871c3 100644 --- a/tests/test_issue_creator.py +++ b/tests/test_issue_creator.py @@ -174,20 +174,40 @@ class TestIssueCreator: with pytest.raises(IssueError, match="Failed to create issue.*parse.*response"): creator.create_issue("Test Issue", "Test description") - @patch('subprocess.run') + @patch('gitea.http_client.subprocess.run') def test_create_issue_with_optional_fields(self, mock_run): """Test issue creation with optional fields.""" config = self._get_test_config() creator = IssueCreator(config=config, auth_token="test-token") - mock_response = self._get_complete_mock_response(124) - mock_run.return_value = MagicMock( - returncode=0, - stdout=json.dumps(mock_response), - stderr="" - ) + # Mock labels API response for label resolution + labels_response = [ + {"id": 1, "name": "bug", "color": "red"}, + {"id": 2, "name": "high", "color": "orange"} + ] - creator.create_issue( + # Mock issue creation response + issue_response = self._get_complete_mock_response(124) + + # Configure mock to return different responses based on URL + def side_effect(*args, **kwargs): + cmd = args[0] + url = cmd[-1] # URL is the last argument + + result_mock = MagicMock() + result_mock.returncode = 0 + result_mock.stderr = "" + + if 'labels' in url: + result_mock.stdout = json.dumps(labels_response) + else: + result_mock.stdout = json.dumps(issue_response) + + return result_mock + + mock_run.side_effect = side_effect + + result = creator.create_issue( "Test Issue", "Test description", assignees=["user1"], @@ -195,27 +215,63 @@ class TestIssueCreator: labels=["bug", "high"] ) - # Check that JSON data includes optional fields - call_args = mock_run.call_args[0][0] - json_data_index = call_args.index('-d') + 1 - json_data = json.loads(call_args[json_data_index]) + # Verify issue was created successfully + assert result['number'] == 124 + assert result['title'] == "Test Issue" - assert json_data['assignees'] == ["user1"] - assert json_data['milestone'] == 1 - assert json_data['labels'] == ["bug", "high"] + # Verify the API was called correctly + # Find the issue creation call (not the labels call) + create_call = None + for call in mock_run.call_args_list: + cmd = call[0][0] + url = cmd[-1] + if 'issues' in url and '/labels' not in url: + create_call = call + break - @patch('subprocess.run') + assert create_call is not None + cmd = create_call[0][0] + + # Find the -d argument (data payload) + data_index = cmd.index('-d') + 1 + payload = json.loads(cmd[data_index]) + + assert payload['assignees'] == ["user1"] + assert payload['milestone'] == 1 + assert payload['labels'] == [1, 2] # Should be IDs now + + @patch('gitea.http_client.subprocess.run') def test_create_enhancement_issue(self, mock_run): """Test creating enhancement issue with structured format.""" config = self._get_test_config() creator = IssueCreator(config=config, auth_token="test-token") - mock_response = self._get_complete_mock_response(125) - mock_run.return_value = MagicMock( - returncode=0, - stdout=json.dumps(mock_response), - stderr="" - ) + # Mock labels API response for label resolution + labels_response = [ + {"id": 1, "name": "enhancement", "color": "blue"}, + {"id": 2, "name": "high", "color": "orange"} + ] + + # Mock issue creation response + issue_response = self._get_complete_mock_response(125) + + # Configure mock to return different responses based on URL + def side_effect(*args, **kwargs): + cmd = args[0] + url = cmd[-1] # URL is the last argument + + result_mock = MagicMock() + result_mock.returncode = 0 + result_mock.stderr = "" + + if 'labels' in url: + result_mock.stdout = json.dumps(labels_response) + else: + result_mock.stdout = json.dumps(issue_response) + + return result_mock + + mock_run.side_effect = side_effect result = creator.create_enhancement_issue( title="Add CLI Support", @@ -227,30 +283,60 @@ class TestIssueCreator: ) # Verify structure of created issue - call_args = mock_run.call_args[0][0] - json_data_index = call_args.index('-d') + 1 - json_data = json.loads(call_args[json_data_index]) + create_call = None + for call in mock_run.call_args_list: + cmd = call[0][0] + url = cmd[-1] + if 'issues' in url and '/labels' not in url: + create_call = call + break - assert "UseCase: User needs command-line interface" in json_data['body'] - assert "Technical Requirements:" in json_data['body'] - assert "- [ ] CLI entry point works" in json_data['body'] - assert "- [ ] Commands have help text" in json_data['body'] - assert "Dependencies:" in json_data['body'] - assert "- Issue #1 - Database" in json_data['body'] - assert json_data['labels'] == ["high", "enhancement"] + assert create_call is not None + cmd = create_call[0][0] - @patch('subprocess.run') + # Find the -d argument (data payload) + data_index = cmd.index('-d') + 1 + payload = json.loads(cmd[data_index]) + + assert "UseCase: User needs command-line interface" in payload['body'] + assert "Technical Requirements:" in payload['body'] + assert "- [ ] CLI entry point works" in payload['body'] + assert "- [ ] Commands have help text" in payload['body'] + assert "Dependencies:" in payload['body'] + assert "- Issue #1 - Database" in payload['body'] + assert payload['labels'] == [2, 1] # Should be IDs: [high, enhancement] + + @patch('gitea.http_client.subprocess.run') def test_create_bug_issue(self, mock_run): """Test creating bug issue with structured format.""" config = self._get_test_config() creator = IssueCreator(config=config, auth_token="test-token") - mock_response = self._get_complete_mock_response(126) - mock_run.return_value = MagicMock( - returncode=0, - stdout=json.dumps(mock_response), - stderr="" - ) + # Mock labels API response for label resolution + labels_response = [ + {"id": 1, "name": "bug", "color": "red"} + ] + + # Mock issue creation response + issue_response = self._get_complete_mock_response(126) + + # Configure mock to return different responses based on URL + def side_effect(*args, **kwargs): + cmd = args[0] + url = cmd[-1] # URL is the last argument + + result_mock = MagicMock() + result_mock.returncode = 0 + result_mock.stderr = "" + + if 'labels' in url: + result_mock.stdout = json.dumps(labels_response) + else: + result_mock.stdout = json.dumps(issue_response) + + return result_mock + + mock_run.side_effect = side_effect result = creator.create_bug_issue( title="CLI crashes on empty input", @@ -262,18 +348,29 @@ class TestIssueCreator: ) # Verify structure of created bug issue - call_args = mock_run.call_args[0][0] - json_data_index = call_args.index('-d') + 1 - json_data = json.loads(call_args[json_data_index]) + create_call = None + for call in mock_run.call_args_list: + cmd = call[0][0] + url = cmd[-1] + if 'issues' in url and '/labels' not in url: + create_call = call + break - assert "The CLI tool crashes when given empty input" in json_data['body'] - assert "Steps to Reproduce:" in json_data['body'] - assert "1. Run CLI command" in json_data['body'] - assert "2. Provide empty input" in json_data['body'] - assert "Expected Behavior: Should show help message" in json_data['body'] - assert "Actual Behavior: Application crashes" in json_data['body'] - assert "Environment: Python 3.8, Linux" in json_data['body'] - assert json_data['labels'] == ["bug"] + assert create_call is not None + cmd = create_call[0][0] + + # Find the -d argument (data payload) + data_index = cmd.index('-d') + 1 + payload = json.loads(cmd[data_index]) + + assert "The CLI tool crashes when given empty input" in payload['body'] + assert "Steps to Reproduce:" in payload['body'] + assert "1. Run CLI command" in payload['body'] + assert "2. Provide empty input" in payload['body'] + assert "Expected Behavior: Should show help message" in payload['body'] + assert "Actual Behavior: Application crashes" in payload['body'] + assert "Environment: Python 3.8, Linux" in payload['body'] + assert payload['labels'] == [1] # Should be ID: [bug] @patch('subprocess.run') @patch('builtins.open', new_callable=mock_open, read_data="Title: Template Issue\nTemplate body content with {variable}")