Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 9 additions & 20 deletions services/github/check_suites/test_get_failed_check_runs.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
from unittest.mock import Mock, patch

import requests
from services.github.check_suites.get_failed_check_runs import \
get_failed_check_runs_from_check_suite
from services.github.check_suites.get_failed_check_runs import (
get_failed_check_runs_from_check_suite,
)


@patch("services.github.check_suites.get_failed_check_runs.requests.get")
@patch("services.github.check_suites.get_failed_check_runs.create_headers")
def test_returns_failed_check_runs_when_mixed_outcomes(
mock_create_headers, mock_get
):
def test_returns_failed_check_runs_when_mixed_outcomes(mock_create_headers, mock_get):
"""Returns only failed check runs when suite includes failed and non-failed runs"""
mock_create_headers.return_value = {"Authorization": "Bearer test-token"}

Expand Down Expand Up @@ -85,9 +84,7 @@ def test_returns_empty_when_no_failures(mock_create_headers, mock_get):
@patch("services.github.check_suites.get_failed_check_runs.requests.get")
@patch("services.github.check_suites.get_failed_check_runs.create_headers")
@patch("builtins.print")
def test_returns_empty_when_api_error(
mock_print, mock_create_headers, mock_get
):
def test_returns_empty_when_api_error(mock_print, mock_create_headers, mock_get):
"""Returns empty list when API returns error status code"""
mock_create_headers.return_value = {"Authorization": "Bearer test-token"}

Expand Down Expand Up @@ -125,9 +122,7 @@ def test_returns_empty_when_not_found(mock_create_headers, mock_get):
@patch("services.github.check_suites.get_failed_check_runs.requests.get")
@patch("services.github.check_suites.get_failed_check_runs.create_headers")
@patch("builtins.print")
def test_returns_empty_when_unauthorized(
mock_print, mock_create_headers, mock_get
):
def test_returns_empty_when_unauthorized(mock_print, mock_create_headers, mock_get):
"""Returns empty list when authentication fails"""
mock_create_headers.return_value = {"Authorization": "Bearer test-token"}

Expand Down Expand Up @@ -167,9 +162,7 @@ def test_returns_empty_when_response_has_no_check_runs_key(
@patch("services.github.check_suites.get_failed_check_runs.requests.get")
@patch("services.github.check_suites.get_failed_check_runs.create_headers")
@patch("builtins.print")
def test_returns_empty_when_forbidden(
mock_print, mock_create_headers, mock_get
):
def test_returns_empty_when_forbidden(mock_print, mock_create_headers, mock_get):
"""Returns empty list when access is forbidden"""
mock_create_headers.return_value = {"Authorization": "Bearer test-token"}

Expand All @@ -188,9 +181,7 @@ def test_returns_empty_when_forbidden(

@patch("services.github.check_suites.get_failed_check_runs.requests.get")
@patch("services.github.check_suites.get_failed_check_runs.create_headers")
def test_returns_empty_when_check_runs_array_is_empty(
mock_create_headers, mock_get
):
def test_returns_empty_when_check_runs_array_is_empty(mock_create_headers, mock_get):
"""Returns empty list when check_runs array is empty"""
mock_create_headers.return_value = {"Authorization": "Bearer test-token"}

Expand Down Expand Up @@ -422,9 +413,7 @@ def test_returns_empty_when_json_parsing_fails(mock_create_headers, mock_get):

@patch("services.github.check_suites.get_failed_check_runs.requests.get")
@patch("services.github.check_suites.get_failed_check_runs.create_headers")
def test_skips_check_runs_with_empty_string_conclusion(
mock_create_headers, mock_get
):
def test_skips_check_runs_with_empty_string_conclusion(mock_create_headers, mock_get):
"""Skips check runs with empty string as conclusion"""
mock_create_headers.return_value = {"Authorization": "Bearer test-token"}

Expand Down
14 changes: 8 additions & 6 deletions services/github/pulls/create_pull_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from utils.error.handle_exceptions import handle_exceptions


@handle_exceptions(default_return_value=None, raise_on_error=False)
def create_pull_request(body: str, title: str, base_args: BaseArgs) -> str | None:
@handle_exceptions(raise_on_error=True)
def create_pull_request(body: str, title: str, base_args: BaseArgs):
"""https://docs.github.com/en/rest/pulls/pulls#create-a-pull-request"""
owner, repo, base, head, token = (
base_args["owner"],
Expand All @@ -24,13 +24,15 @@ def create_pull_request(body: str, title: str, base_args: BaseArgs) -> str | Non
)
if response.status_code == 422:
msg = f"{create_pull_request.__name__} encountered an HTTPError: 422 Client Error: Unprocessable Entity for url: {response.url}, which is because no commits between the base branch and the working branch."
print(msg)
return None
raise requests.exceptions.HTTPError(msg)

response.raise_for_status()
pr_data = response.json()
pr_url: str = pr_data["html_url"]
pr_number: int = pr_data["number"]

# Add reviewers to the pull request
base_args["pr_number"] = pr_data["number"]
base_args["pr_number"] = pr_number
add_reviewers(base_args=base_args)

return pr_data["html_url"]
return pr_url, pr_number
59 changes: 24 additions & 35 deletions services/github/pulls/test_create_pull_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def test_create_pull_request_success(

result = create_pull_request("Test body", "Test title", base_args)

assert result == "https://github.com/owner/repo/pull/123"
assert result == ("https://github.com/owner/repo/pull/123", 123)
mock_post.assert_called_once_with(
url="https://api.github.com/repos/gitautoai/gitauto/pulls",
headers={"Authorization": "Bearer token"},
Expand All @@ -89,9 +89,7 @@ def test_create_pull_request_success(
@patch("services.github.pulls.create_pull_request.add_reviewers")
@patch("services.github.pulls.create_pull_request.create_headers")
@patch("services.github.pulls.create_pull_request.requests.post")
@patch("builtins.print")
def test_create_pull_request_422_error(
mock_print,
mock_post,
mock_create_headers,
mock_add_reviewers,
Expand All @@ -101,9 +99,14 @@ def test_create_pull_request_422_error(
mock_post.return_value = mock_422_response
mock_create_headers.return_value = {"Authorization": "Bearer token"}

result = create_pull_request("Test body", "Test title", base_args)
with pytest.raises(requests.exceptions.HTTPError) as exc_info:
create_pull_request("Test body", "Test title", base_args)

assert "422 Client Error: Unprocessable Entity" in str(exc_info.value)
assert "no commits between the base branch and the working branch" in str(
exc_info.value
)

assert result is None
mock_post.assert_called_once_with(
url="https://api.github.com/repos/gitautoai/gitauto/pulls",
headers={"Authorization": "Bearer token"},
Expand All @@ -120,9 +123,6 @@ def test_create_pull_request_422_error(
mock_422_response.json.assert_not_called()
mock_add_reviewers.assert_not_called()

expected_msg = "create_pull_request encountered an HTTPError: 422 Client Error: Unprocessable Entity for url: https://api.github.com/repos/owner/repo/pulls, which is because no commits between the base branch and the working branch."
mock_print.assert_called_once_with(expected_msg)


@patch("services.github.pulls.create_pull_request.add_reviewers")
@patch("services.github.pulls.create_pull_request.create_headers")
Expand All @@ -137,9 +137,9 @@ def test_create_pull_request_http_error(
mock_post.return_value = mock_error_response
mock_create_headers.return_value = {"Authorization": "Bearer token"}

result = create_pull_request("Test body", "Test title", base_args)
with pytest.raises(requests.HTTPError):
create_pull_request("Test body", "Test title", base_args)

assert result is None
mock_post.assert_called_once_with(
url="https://api.github.com/repos/gitautoai/gitauto/pulls",
headers={"Authorization": "Bearer token"},
Expand Down Expand Up @@ -171,9 +171,9 @@ def test_create_pull_request_json_error(
mock_create_headers.return_value = {"Authorization": "Bearer token"}
mock_response.json.side_effect = ValueError("Invalid JSON")

result = create_pull_request("Test body", "Test title", base_args)
with pytest.raises(ValueError):
create_pull_request("Test body", "Test title", base_args)

assert result is None
mock_post.assert_called_once()
mock_create_headers.assert_called_once_with(token="test-token-mock")
mock_response.raise_for_status.assert_called_once()
Expand All @@ -195,9 +195,11 @@ def test_create_pull_request_add_reviewers_error(
mock_create_headers.return_value = {"Authorization": "Bearer token"}
mock_add_reviewers.side_effect = Exception("Reviewer error")

result = create_pull_request("Test body", "Test title", base_args)
with pytest.raises(Exception) as exc_info:
create_pull_request("Test body", "Test title", base_args)

assert "Reviewer error" in str(exc_info.value)

assert result is None
mock_post.assert_called_once()
mock_create_headers.assert_called_once_with(token="test-token-mock")
mock_response.raise_for_status.assert_called_once()
Expand All @@ -219,7 +221,7 @@ def test_create_pull_request_empty_strings(

result = create_pull_request("", "", base_args)

assert result == "https://github.com/owner/repo/pull/123"
assert result == ("https://github.com/owner/repo/pull/123", 123)
mock_post.assert_called_once_with(
url="https://api.github.com/repos/gitautoai/gitauto/pulls",
headers={"Authorization": "Bearer token"},
Expand All @@ -245,7 +247,7 @@ def test_create_pull_request_different_branches(

result = create_pull_request("Feature body", "Feature title", base_args)

assert result == "https://github.com/owner/repo/pull/123"
assert result == ("https://github.com/owner/repo/pull/123", 123)
mock_post.assert_called_once_with(
url="https://api.github.com/repos/gitautoai/gitauto/pulls",
headers={"Authorization": "Bearer token"},
Expand All @@ -268,9 +270,9 @@ def test_create_pull_request_requests_exception(
mock_post.side_effect = requests.RequestException("Network error")
mock_create_headers.return_value = {"Authorization": "Bearer token"}

result = create_pull_request("Test body", "Test title", base_args)
with pytest.raises(requests.RequestException):
create_pull_request("Test body", "Test title", base_args)

assert result is None
mock_post.assert_called_once()
mock_create_headers.assert_called_once_with(token="test-token-mock")
mock_add_reviewers.assert_not_called()
Expand All @@ -284,26 +286,13 @@ def test_create_pull_request_create_headers_exception(
):
mock_create_headers.side_effect = Exception("Header creation error")

result = create_pull_request("Test body", "Test title", base_args)
with pytest.raises(Exception) as exc_info:
create_pull_request("Test body", "Test title", base_args)

assert "Header creation error" in str(exc_info.value)

assert result is None
mock_create_headers.assert_called_once_with(token="test-token-mock")
mock_post.assert_not_called()
mock_add_reviewers.assert_not_called()


@patch("services.github.pulls.create_pull_request.add_reviewers")
@patch("services.github.pulls.create_pull_request.create_headers")
@patch("services.github.pulls.create_pull_request.requests.post")
def test_create_pull_request_key_error_in_base_args(
mock_post, mock_create_headers, mock_add_reviewers, test_owner, test_repo
):
mock_create_headers.return_value = {"Authorization": "Bearer token"}
incomplete_base_args = {"owner": test_owner, "repo": test_repo}

result = create_pull_request("Test body", "Test title", incomplete_base_args)

assert result is None
mock_create_headers.assert_not_called()
mock_post.assert_not_called()
mock_add_reviewers.assert_not_called()
Loading