Files
OpenHands/enterprise/tests/unit/test_github_view.py
Rohit Malhotra 9686ee02f3 V1 GitHub resolver fixes (#12199)
Co-authored-by: openhands <openhands@all-hands.dev>
2026-01-06 19:33:54 +00:00

218 lines
8.0 KiB
Python

from unittest import TestCase, mock
from unittest.mock import MagicMock, patch
import pytest
from integrations.github.github_view import GithubFactory, GithubIssue, get_oh_labels
from integrations.models import Message, SourceType
from integrations.types import UserData
class TestGithubLabels(TestCase):
def test_labels_with_staging(self):
oh_label, inline_oh_label = get_oh_labels('staging.all-hands.dev')
self.assertEqual(oh_label, 'openhands-exp')
self.assertEqual(inline_oh_label, '@openhands-exp')
def test_labels_with_staging_v2(self):
oh_label, inline_oh_label = get_oh_labels('main.staging.all-hands.dev')
self.assertEqual(oh_label, 'openhands-exp')
self.assertEqual(inline_oh_label, '@openhands-exp')
def test_labels_with_local(self):
oh_label, inline_oh_label = get_oh_labels('localhost:3000')
self.assertEqual(oh_label, 'openhands-exp')
self.assertEqual(inline_oh_label, '@openhands-exp')
def test_labels_with_prod(self):
oh_label, inline_oh_label = get_oh_labels('app.all-hands.dev')
self.assertEqual(oh_label, 'openhands')
self.assertEqual(inline_oh_label, '@openhands')
def test_labels_with_spaces(self):
"""Test that spaces are properly stripped"""
oh_label, inline_oh_label = get_oh_labels(' local ')
self.assertEqual(oh_label, 'openhands-exp')
self.assertEqual(inline_oh_label, '@openhands-exp')
class TestGithubCommentCaseInsensitivity(TestCase):
@mock.patch('integrations.github.github_view.INLINE_OH_LABEL', '@openhands')
def test_issue_comment_case_insensitivity(self):
# Test with lowercase mention
message_lower = Message(
source=SourceType.GITHUB,
message={
'payload': {
'action': 'created',
'comment': {'body': 'hello @openhands please help'},
'issue': {'number': 1},
}
},
)
# Test with uppercase mention
message_upper = Message(
source=SourceType.GITHUB,
message={
'payload': {
'action': 'created',
'comment': {'body': 'hello @OPENHANDS please help'},
'issue': {'number': 1},
}
},
)
# Test with mixed case mention
message_mixed = Message(
source=SourceType.GITHUB,
message={
'payload': {
'action': 'created',
'comment': {'body': 'hello @OpenHands please help'},
'issue': {'number': 1},
}
},
)
# All should be detected as issue comments with mentions
self.assertTrue(GithubFactory.is_issue_comment(message_lower))
self.assertTrue(GithubFactory.is_issue_comment(message_upper))
self.assertTrue(GithubFactory.is_issue_comment(message_mixed))
class TestGithubV1ConversationRouting(TestCase):
"""Test V1 conversation routing logic in GitHub integration."""
def setUp(self):
"""Set up test fixtures."""
# Create a proper UserData instance instead of MagicMock
self.user_data = UserData(
user_id=123, username='testuser', keycloak_user_id='test-keycloak-id'
)
# Create a mock raw_payload
self.raw_payload = Message(
source=SourceType.GITHUB,
message={
'payload': {
'action': 'opened',
'issue': {'number': 123},
}
},
)
def _create_github_issue(self):
"""Create a GithubIssue instance for testing."""
return GithubIssue(
user_info=self.user_data,
full_repo_name='test/repo',
issue_number=123,
installation_id=456,
conversation_id='test-conversation-id',
should_extract=True,
send_summary_instruction=False,
is_public_repo=True,
raw_payload=self.raw_payload,
uuid='test-uuid',
title='Test Issue',
description='Test issue description',
previous_comments=[],
v1_enabled=False,
)
@pytest.mark.asyncio
@patch('integrations.github.github_view.initialize_conversation')
@patch('integrations.github.github_view.get_user_v1_enabled_setting')
async def test_initialize_sets_v1_enabled_from_setting_when_false(
self, mock_get_v1_setting, mock_initialize_conversation
):
"""Test that initialize_new_conversation sets v1_enabled from get_user_v1_enabled_setting."""
mock_get_v1_setting.return_value = False
mock_initialize_conversation.return_value = MagicMock(
conversation_id='new-conversation-id'
)
github_issue = self._create_github_issue()
await github_issue.initialize_new_conversation()
# Verify get_user_v1_enabled_setting was called with correct user ID
mock_get_v1_setting.assert_called_once_with('test-keycloak-id')
# Verify v1_enabled was set to False
self.assertFalse(github_issue.v1_enabled)
@pytest.mark.asyncio
@patch('integrations.github.github_view.get_user_v1_enabled_setting')
async def test_initialize_sets_v1_enabled_from_setting_when_true(
self, mock_get_v1_setting
):
"""Test that initialize_new_conversation sets v1_enabled to True when setting returns True."""
mock_get_v1_setting.return_value = True
github_issue = self._create_github_issue()
await github_issue.initialize_new_conversation()
# Verify get_user_v1_enabled_setting was called with correct user ID
mock_get_v1_setting.assert_called_once_with('test-keycloak-id')
# Verify v1_enabled was set to True
self.assertTrue(github_issue.v1_enabled)
@pytest.mark.asyncio
@patch.object(GithubIssue, '_create_v0_conversation')
@patch.object(GithubIssue, '_create_v1_conversation')
async def test_create_new_conversation_routes_to_v0_when_disabled(
self, mock_create_v1, mock_create_v0
):
"""Test that conversation creation routes to V0 when v1_enabled is False."""
mock_create_v0.return_value = None
mock_create_v1.return_value = None
github_issue = self._create_github_issue()
github_issue.v1_enabled = False
# Mock parameters
jinja_env = MagicMock()
git_provider_tokens = MagicMock()
conversation_metadata = MagicMock()
saas_user_auth = MagicMock()
# Call the method
await github_issue.create_new_conversation(
jinja_env, git_provider_tokens, conversation_metadata, saas_user_auth
)
# Verify V0 was called and V1 was not
mock_create_v0.assert_called_once_with(
jinja_env, git_provider_tokens, conversation_metadata
)
mock_create_v1.assert_not_called()
@pytest.mark.asyncio
@patch.object(GithubIssue, '_create_v0_conversation')
@patch.object(GithubIssue, '_create_v1_conversation')
async def test_create_new_conversation_routes_to_v1_when_enabled(
self, mock_create_v1, mock_create_v0
):
"""Test that conversation creation routes to V1 when v1_enabled is True."""
mock_create_v0.return_value = None
mock_create_v1.return_value = None
github_issue = self._create_github_issue()
github_issue.v1_enabled = True
# Mock parameters
jinja_env = MagicMock()
git_provider_tokens = MagicMock()
conversation_metadata = MagicMock()
saas_user_auth = MagicMock()
# Call the method
await github_issue.create_new_conversation(
jinja_env, git_provider_tokens, conversation_metadata, saas_user_auth
)
# Verify V1 was called and V0 was not
mock_create_v1.assert_called_once_with(
jinja_env, saas_user_auth, conversation_metadata
)
mock_create_v0.assert_not_called()