Additional tests for improved coverage (#439)
Signed-off-by: Glenn Jocher <[email protected]> Co-authored-by: UltralyticsAssistant <[email protected]>
This commit is contained in:
co-authored by
UltralyticsAssistant
parent
9a71915810
commit
7ba774a7b1
@@ -0,0 +1,146 @@
|
||||
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
||||
|
||||
from datetime import datetime
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from actions.dispatch_actions import (
|
||||
RUN_CI_KEYWORD,
|
||||
get_pr_branch,
|
||||
main,
|
||||
trigger_and_get_workflow_info,
|
||||
update_comment,
|
||||
)
|
||||
|
||||
|
||||
def test_get_pr_branch():
|
||||
"""Test getting PR branch name."""
|
||||
mock_event = MagicMock()
|
||||
mock_event.event_data = {"issue": {"number": 123}}
|
||||
mock_event.get_repo_data.return_value = {"head": {"ref": "feature-branch"}}
|
||||
|
||||
branch = get_pr_branch(mock_event)
|
||||
|
||||
assert branch == "feature-branch"
|
||||
mock_event.get_repo_data.assert_called_once_with("pulls/123")
|
||||
|
||||
|
||||
def test_trigger_and_get_workflow_info():
|
||||
"""Test triggering workflows and getting info."""
|
||||
mock_event = MagicMock()
|
||||
mock_event.repository = "test/repo"
|
||||
|
||||
# Mock the workflow and runs responses separately
|
||||
workflow_response = MagicMock()
|
||||
workflow_response.status_code = 200
|
||||
workflow_response.json.return_value = {"name": "CI Workflow"}
|
||||
|
||||
runs_response = MagicMock()
|
||||
runs_response.status_code = 200
|
||||
runs_response.json.return_value = {
|
||||
"workflow_runs": [{"html_url": "https://github.com/test/repo/actions/runs/123", "run_number": 42}]
|
||||
}
|
||||
|
||||
# Set up get method to return different responses for different URLs
|
||||
def get_side_effect(url):
|
||||
if "workflows/ci.yml" in url and "runs" not in url:
|
||||
return workflow_response
|
||||
elif "workflows/ci.yml/runs" in url:
|
||||
return runs_response
|
||||
# Return default response for unexpected URLs
|
||||
default = MagicMock()
|
||||
default.status_code = 404
|
||||
return default
|
||||
|
||||
mock_event.get.side_effect = get_side_effect
|
||||
|
||||
# Use patch to skip time.sleep and limit to one workflow
|
||||
with patch("time.sleep"):
|
||||
with patch("actions.dispatch_actions.WORKFLOW_FILES", ["ci.yml"]):
|
||||
results = trigger_and_get_workflow_info(mock_event, "feature-branch")
|
||||
|
||||
# Check results
|
||||
assert len(results) == 1
|
||||
assert results[0]["name"] == "CI Workflow"
|
||||
assert results[0]["run_number"] == 42
|
||||
|
||||
|
||||
def test_update_comment_function():
|
||||
"""Test updating comment with workflow info."""
|
||||
mock_event = MagicMock()
|
||||
mock_event.repository = "test/repo"
|
||||
mock_event.event_data = {"comment": {"id": 456}}
|
||||
|
||||
comment_body = f"Run tests please {RUN_CI_KEYWORD}"
|
||||
triggered_actions = [
|
||||
{
|
||||
"name": "CI Workflow",
|
||||
"file": "ci.yml",
|
||||
"url": "https://github.com/test/repo/actions/workflows/ci.yml",
|
||||
"run_number": 42,
|
||||
}
|
||||
]
|
||||
|
||||
# Mock datetime to have a consistent timestamp
|
||||
with patch("actions.dispatch_actions.datetime") as mock_datetime:
|
||||
mock_datetime.now.return_value = datetime(2023, 1, 1, 12, 0, 0)
|
||||
# Call without capturing return value
|
||||
update_comment(mock_event, comment_body, triggered_actions, "feature-branch")
|
||||
|
||||
# Check that patch was called with expected content
|
||||
mock_event.patch.assert_called_once()
|
||||
|
||||
# Verify key content in the comment body
|
||||
args, kwargs = mock_event.patch.call_args
|
||||
assert "https://api.github.com/repos/test/repo/issues/comments/456" in args[0]
|
||||
assert "Actions Trigger" in kwargs["json"]["body"]
|
||||
assert "CI Workflow" in kwargs["json"]["body"]
|
||||
assert "2023-01-01 12:00:00 UTC" in kwargs["json"]["body"]
|
||||
|
||||
|
||||
def test_main_triggers_workflows():
|
||||
"""Test main function when comment contains trigger keyword."""
|
||||
with patch("actions.dispatch_actions.Action") as MockAction:
|
||||
# Configure mock
|
||||
mock_event = MockAction.return_value
|
||||
mock_event.event_name = "issue_comment"
|
||||
mock_event.repository = "test/repo"
|
||||
mock_event.event_data = {
|
||||
"action": "created",
|
||||
"issue": {"pull_request": {}},
|
||||
"comment": {"body": f"Please run CI {RUN_CI_KEYWORD}", "user": {"login": "testuser"}, "id": 789},
|
||||
}
|
||||
mock_event.is_org_member.return_value = True
|
||||
|
||||
# Create minimal patches for the functions called by main
|
||||
with patch("actions.dispatch_actions.get_pr_branch") as mock_get_branch:
|
||||
with patch("actions.dispatch_actions.trigger_and_get_workflow_info") as mock_trigger:
|
||||
with patch("actions.dispatch_actions.update_comment"):
|
||||
# Set return values
|
||||
mock_get_branch.return_value = "feature-branch"
|
||||
mock_trigger.return_value = [{"name": "CI", "file": "ci.yml", "url": "url", "run_number": 1}]
|
||||
|
||||
# Call the function
|
||||
main()
|
||||
|
||||
# Verify main component calls were made
|
||||
mock_event.is_org_member.assert_called_once_with("testuser")
|
||||
mock_get_branch.assert_called_once()
|
||||
mock_trigger.assert_called_once()
|
||||
|
||||
|
||||
def test_main_skips_non_pr_comments():
|
||||
"""Test main function skips non-PR comments."""
|
||||
with patch("actions.dispatch_actions.Action") as MockAction:
|
||||
# Configure mock
|
||||
mock_event = MockAction.return_value
|
||||
mock_event.event_name = "issue_comment"
|
||||
mock_event.event_data = {
|
||||
"action": "created",
|
||||
"issue": {}, # No pull_request key
|
||||
"comment": {"body": f"Please run CI {RUN_CI_KEYWORD}", "user": {"login": "testuser"}},
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
# Verify toggle_eyes_reaction was not called
|
||||
mock_event.toggle_eyes_reaction.assert_not_called()
|
||||
@@ -0,0 +1,116 @@
|
||||
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from actions.first_interaction import (
|
||||
create_alert_label,
|
||||
get_event_content,
|
||||
get_first_interaction_response,
|
||||
get_relevant_labels,
|
||||
)
|
||||
|
||||
|
||||
def test_get_event_content_issue():
|
||||
"""Test extracting content from issue event."""
|
||||
# Create mock event
|
||||
mock_event = MagicMock()
|
||||
mock_event.event_name = "issues"
|
||||
mock_event.event_data = {
|
||||
"action": "opened",
|
||||
"issue": {
|
||||
"number": 123,
|
||||
"node_id": "node123",
|
||||
"title": "Test Issue",
|
||||
"body": "Issue description",
|
||||
"user": {"login": "testuser"},
|
||||
},
|
||||
}
|
||||
|
||||
number, node_id, title, body, username, issue_type, action = get_event_content(mock_event)
|
||||
|
||||
assert number == 123
|
||||
assert node_id == "node123"
|
||||
assert title == "Test Issue"
|
||||
assert body == "Issue description"
|
||||
assert username == "testuser"
|
||||
assert issue_type == "issue"
|
||||
assert action == "opened"
|
||||
|
||||
|
||||
def test_get_event_content_pr():
|
||||
"""Test extracting content from PR event."""
|
||||
# Create mock event
|
||||
mock_event = MagicMock()
|
||||
mock_event.event_name = "pull_request"
|
||||
mock_event.event_data = {"action": "opened", "pull_request": {"number": 456}}
|
||||
|
||||
# Mock PR data returned from API
|
||||
mock_event.get_repo_data.return_value = {
|
||||
"number": 456,
|
||||
"node_id": "node456",
|
||||
"title": "Test PR",
|
||||
"body": "PR description",
|
||||
"user": {"login": "testuser"},
|
||||
}
|
||||
|
||||
number, node_id, title, body, username, issue_type, action = get_event_content(mock_event)
|
||||
|
||||
assert number == 456
|
||||
assert node_id == "node456"
|
||||
assert title == "Test PR"
|
||||
assert body == "PR description"
|
||||
assert username == "testuser"
|
||||
assert issue_type == "pull request"
|
||||
assert action == "opened"
|
||||
|
||||
|
||||
@patch("actions.first_interaction.get_completion")
|
||||
def test_get_relevant_labels(mock_get_completion):
|
||||
"""Test getting relevant labels for an issue."""
|
||||
mock_get_completion.return_value = "bug, enhancement"
|
||||
|
||||
available_labels = {
|
||||
"bug": "A bug in the software",
|
||||
"enhancement": "New feature or request",
|
||||
"documentation": "Improvements to documentation",
|
||||
}
|
||||
|
||||
labels = get_relevant_labels(
|
||||
issue_type="issue",
|
||||
title="Bug: App crashes on startup",
|
||||
body="The application crashes when started",
|
||||
available_labels=available_labels,
|
||||
current_labels=[],
|
||||
)
|
||||
|
||||
assert labels == ["bug", "enhancement"]
|
||||
mock_get_completion.assert_called_once()
|
||||
|
||||
|
||||
@patch("actions.first_interaction.get_completion")
|
||||
def test_get_first_interaction_response(mock_get_completion):
|
||||
"""Test generating first interaction response."""
|
||||
mock_get_completion.return_value = "Thank you for your issue"
|
||||
|
||||
mock_event = MagicMock()
|
||||
mock_event.repository = "test/repo"
|
||||
|
||||
response = get_first_interaction_response(
|
||||
event=mock_event, issue_type="issue", title="Test Issue", body="Issue description", username="testuser"
|
||||
)
|
||||
|
||||
assert response == "Thank you for your issue"
|
||||
mock_get_completion.assert_called_once()
|
||||
|
||||
|
||||
def test_create_alert_label():
|
||||
"""Test creating Alert label."""
|
||||
mock_event = MagicMock()
|
||||
|
||||
create_alert_label(mock_event)
|
||||
|
||||
mock_event.post.assert_called_once()
|
||||
args, kwargs = mock_event.post.call_args
|
||||
assert "labels" in args[0]
|
||||
assert kwargs["json"]["name"] == "Alert"
|
||||
assert kwargs["json"]["color"] == "FF0000"
|
||||
@@ -0,0 +1,73 @@
|
||||
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from actions.summarize_pr import (
|
||||
generate_issue_comment,
|
||||
generate_merge_message,
|
||||
generate_pr_summary,
|
||||
update_pr_description,
|
||||
)
|
||||
|
||||
|
||||
@patch("actions.summarize_pr.get_completion")
|
||||
def test_generate_pr_summary(mock_get_completion):
|
||||
"""Test generating PR summary with expected formatting."""
|
||||
mock_get_completion.return_value = "Test PR summary content"
|
||||
summary = generate_pr_summary("test/repo", "diff content")
|
||||
|
||||
assert summary.startswith("## 🛠️ PR Summary")
|
||||
assert "Test PR summary content" in summary
|
||||
mock_get_completion.assert_called_once()
|
||||
|
||||
|
||||
@patch("actions.summarize_pr.get_completion")
|
||||
def test_generate_merge_message(mock_get_completion):
|
||||
"""Test generating merge thank you messages."""
|
||||
mock_get_completion.return_value = "Thank you for your contribution!"
|
||||
|
||||
message = generate_merge_message(
|
||||
pr_summary="Feature implementation", pr_credit="@testuser", pr_url="https://github.com/test/repo/pull/1"
|
||||
)
|
||||
|
||||
assert message == "Thank you for your contribution!"
|
||||
mock_get_completion.assert_called_once()
|
||||
|
||||
|
||||
@patch("actions.summarize_pr.get_completion")
|
||||
def test_generate_issue_comment(mock_get_completion):
|
||||
"""Test generating issue comments about PR fixes."""
|
||||
mock_get_completion.return_value = "This issue is fixed in PR #123"
|
||||
|
||||
comment = generate_issue_comment(
|
||||
pr_url="https://api.github.com/repos/owner/repo/pulls/123",
|
||||
pr_summary="Fixed bug",
|
||||
pr_credit="@testuser",
|
||||
pr_title="Bug fix PR",
|
||||
)
|
||||
|
||||
assert comment == "This issue is fixed in PR #123"
|
||||
mock_get_completion.assert_called_once()
|
||||
|
||||
|
||||
def test_update_pr_description():
|
||||
"""Test updating PR description with summary."""
|
||||
# Mock Action class
|
||||
mock_event = MagicMock()
|
||||
mock_event.repository = "test/repo"
|
||||
mock_event.pr = {"number": 123}
|
||||
|
||||
# Mock response for get request
|
||||
mock_response = MagicMock()
|
||||
mock_response.json.return_value = {"body": "Original description"}
|
||||
mock_event.get.return_value = mock_response
|
||||
|
||||
# Test updating description
|
||||
update_pr_description(mock_event, "## 🛠️ PR Summary\nNew summary")
|
||||
|
||||
# Verify patch was called with correct parameters
|
||||
mock_event.patch.assert_called_once()
|
||||
args, kwargs = mock_event.patch.call_args
|
||||
assert args[0] == "https://api.github.com/repos/test/repo/pulls/123"
|
||||
assert "Original description" in kwargs["json"]["body"]
|
||||
assert "## 🛠️ PR Summary\nNew summary" in kwargs["json"]["body"]
|
||||
@@ -0,0 +1,127 @@
|
||||
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from actions.summarize_release import (
|
||||
create_github_release,
|
||||
generate_release_summary,
|
||||
get_prs_between_tags,
|
||||
get_release_diff,
|
||||
)
|
||||
|
||||
|
||||
def test_get_release_diff():
|
||||
"""Test retrieving diff between tags."""
|
||||
mock_event = MagicMock()
|
||||
mock_event.repository = "test/repo"
|
||||
mock_event.headers_diff = {"Accept": "application/vnd.github.v3.diff"}
|
||||
|
||||
# Mock response
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.text = "diff content"
|
||||
mock_event.get.return_value = mock_response
|
||||
|
||||
diff = get_release_diff(mock_event, "v1.0.0", "v1.1.0")
|
||||
|
||||
assert diff == "diff content"
|
||||
mock_event.get.assert_called_once_with(
|
||||
"https://api.github.com/repos/test/repo/compare/v1.0.0...v1.1.0", headers=mock_event.headers_diff
|
||||
)
|
||||
|
||||
|
||||
def test_get_prs_between_tags():
|
||||
"""Test retrieving PRs between tags."""
|
||||
mock_event = MagicMock()
|
||||
mock_event.repository = "test/repo"
|
||||
|
||||
# Mock compare response
|
||||
mock_compare_response = MagicMock()
|
||||
mock_compare_response.json.return_value = {
|
||||
"commits": [{"commit": {"message": "Fix bug #123"}}, {"commit": {"message": "Add feature #456"}}]
|
||||
}
|
||||
|
||||
# Mock PR responses
|
||||
mock_pr1_response = MagicMock()
|
||||
mock_pr1_response.status_code = 200
|
||||
mock_pr1_response.json.return_value = {
|
||||
"number": 123,
|
||||
"title": "Fix bug",
|
||||
"body": "Fixes a bug",
|
||||
"user": {"login": "user1"},
|
||||
"html_url": "https://github.com/test/repo/pull/123",
|
||||
"merged_at": "2023-01-01T12:00:00Z",
|
||||
}
|
||||
|
||||
mock_pr2_response = MagicMock()
|
||||
mock_pr2_response.status_code = 200
|
||||
mock_pr2_response.json.return_value = {
|
||||
"number": 456,
|
||||
"title": "Add feature",
|
||||
"body": "Adds a new feature",
|
||||
"user": {"login": "user2"},
|
||||
"html_url": "https://github.com/test/repo/pull/456",
|
||||
"merged_at": "2023-01-02T12:00:00Z",
|
||||
}
|
||||
|
||||
# Set up get method to return different responses
|
||||
mock_event.get.side_effect = [mock_compare_response, mock_pr1_response, mock_pr2_response]
|
||||
|
||||
# Use patch to skip the sleep
|
||||
with patch("time.sleep"):
|
||||
prs = get_prs_between_tags(mock_event, "v1.0.0", "v1.1.0")
|
||||
|
||||
assert len(prs) == 2
|
||||
assert prs[0]["number"] == 123
|
||||
assert prs[1]["number"] == 456
|
||||
|
||||
|
||||
@patch("actions.summarize_release.get_completion")
|
||||
def test_generate_release_summary(mock_get_completion):
|
||||
"""Test generating release summary."""
|
||||
mock_get_completion.return_value = "Release summary content"
|
||||
|
||||
mock_event = MagicMock()
|
||||
mock_event.repository = "test/repo"
|
||||
|
||||
# Create test data with matching author for new contributor
|
||||
test_prs = [
|
||||
{
|
||||
"number": 123,
|
||||
"title": "Fix bug",
|
||||
"body": "Fixes a bug",
|
||||
"author": "newuser", # Match the contributor name
|
||||
"html_url": "https://github.com/test/repo/pull/123",
|
||||
"merged_at": "2023-01-01T12:00:00Z",
|
||||
}
|
||||
]
|
||||
|
||||
# Mock new contributors function
|
||||
with patch("actions.summarize_release.get_new_contributors", return_value=["newuser"]):
|
||||
summary = generate_release_summary(
|
||||
event=mock_event, diff="diff content", prs=test_prs, latest_tag="v1.1.0", previous_tag="v1.0.0"
|
||||
)
|
||||
|
||||
assert "Release summary content" in summary
|
||||
assert "What's Changed" in summary
|
||||
assert "https://github.com/test/repo/compare/v1.0.0...v1.1.0" in summary
|
||||
mock_get_completion.assert_called_once()
|
||||
|
||||
|
||||
def test_create_github_release():
|
||||
"""Test creating GitHub release."""
|
||||
mock_event = MagicMock()
|
||||
mock_event.repository = "test/repo"
|
||||
|
||||
create_github_release(event=mock_event, tag_name="v1.1.0", name="Version 1.1.0", body="Release notes")
|
||||
|
||||
mock_event.post.assert_called_once_with(
|
||||
"https://api.github.com/repos/test/repo/releases",
|
||||
json={
|
||||
"tag_name": "v1.1.0",
|
||||
"name": "Version 1.1.0",
|
||||
"body": "Release notes",
|
||||
"draft": False,
|
||||
"prerelease": False,
|
||||
},
|
||||
)
|
||||
Reference in New Issue
Block a user