|
1 | 1 | import logging |
2 | 2 | from typing import Any |
3 | | -from unittest.mock import AsyncMock, patch |
| 3 | +from unittest.mock import AsyncMock, Mock, patch |
4 | 4 |
|
| 5 | +import pytest |
5 | 6 | from lightman_ai.article.models import SelectedArticle, SelectedArticlesList |
6 | | -from lightman_ai.main import lightman |
| 7 | +from lightman_ai.main import _create_service_desk_issues, lightman |
7 | 8 | from tests.utils import patch_agent |
8 | 9 |
|
9 | 10 |
|
@@ -70,3 +71,106 @@ def test_lightman_no_publish_if_dry_run(self, caplog: Any, test_prompt: str, thn |
70 | 71 | # Check ServiceDesk integration is NOT called in dry_run mode |
71 | 72 | mock_service_desk_env.assert_not_called() |
72 | 73 | assert mock_service_desk.create_request_of_type.call_count == 0 |
| 74 | + |
| 75 | + |
| 76 | +class TestCreateServiceDeskIssues: |
| 77 | + """Tests for the _create_service_desk_issues function.""" |
| 78 | + |
| 79 | + def test_create_service_desk_issues_success( |
| 80 | + self, selected_articles: list[SelectedArticle], mock_service_desk: Mock, caplog: pytest.LogCaptureFixture |
| 81 | + ) -> None: |
| 82 | + """Test successful creation of service desk issues for all articles.""" |
| 83 | + with caplog.at_level(logging.INFO): |
| 84 | + _create_service_desk_issues( |
| 85 | + selected_articles=selected_articles, |
| 86 | + service_desk_client=mock_service_desk, |
| 87 | + project_key="TEST", |
| 88 | + request_id_type="10001", |
| 89 | + ) |
| 90 | + |
| 91 | + # Verify service desk client was called for each article |
| 92 | + assert mock_service_desk.create_request_of_type.call_count == 2 |
| 93 | + |
| 94 | + # Check the calls were made with correct parameters |
| 95 | + calls = mock_service_desk.create_request_of_type.call_args_list |
| 96 | + |
| 97 | + # First article call |
| 98 | + first_call = calls[0] |
| 99 | + assert first_call.kwargs["project_key"] == "TEST" |
| 100 | + assert first_call.kwargs["summary"] == "Critical Security Vulnerability in Popular Library" |
| 101 | + assert first_call.kwargs["request_id_type"] == "10001" |
| 102 | + expected_desc_1 = "*Why is relevant:*\nThis affects our production systems\n\n*Source:* https://example.com/article1\n\n*Score:* 9/10" |
| 103 | + assert first_call.kwargs["description"] == expected_desc_1 |
| 104 | + |
| 105 | + # Second article call |
| 106 | + second_call = calls[1] |
| 107 | + assert second_call.kwargs["project_key"] == "TEST" |
| 108 | + assert second_call.kwargs["summary"] == "New Attack Vector Discovered" |
| 109 | + assert second_call.kwargs["request_id_type"] == "10001" |
| 110 | + expected_desc_2 = "*Why is relevant:*\nCould impact our infrastructure\n\n*Source:* https://example.com/article2\n\n*Score:* 8/10" |
| 111 | + assert second_call.kwargs["description"] == expected_desc_2 |
| 112 | + |
| 113 | + # Check success log messages |
| 114 | + assert "Created issue for article https://example.com/article1" in caplog.text |
| 115 | + assert "Created issue for article https://example.com/article2" in caplog.text |
| 116 | + |
| 117 | + def test_create_service_desk_issues_single_failure( |
| 118 | + self, selected_articles: list[SelectedArticle], mock_service_desk: Mock, caplog: pytest.LogCaptureFixture |
| 119 | + ) -> None: |
| 120 | + """Test handling when one article fails to create service desk issue.""" |
| 121 | + # Make the first call succeed, second call fail |
| 122 | + mock_service_desk.create_request_of_type.side_effect = [ |
| 123 | + "PROJ-123", # Success for first article |
| 124 | + Exception("Service desk unavailable"), # Failure for second article |
| 125 | + ] |
| 126 | + |
| 127 | + with caplog.at_level(logging.INFO), pytest.raises(ExceptionGroup) as exc_info: |
| 128 | + _create_service_desk_issues( |
| 129 | + selected_articles=selected_articles, |
| 130 | + service_desk_client=mock_service_desk, |
| 131 | + project_key="TEST", |
| 132 | + request_id_type="10001", |
| 133 | + ) |
| 134 | + |
| 135 | + # Verify both calls were attempted |
| 136 | + assert mock_service_desk.create_request_of_type.call_count == 2 |
| 137 | + |
| 138 | + # Check that ExceptionGroup contains the failure |
| 139 | + assert "Could not create all ServiceDesk issues" in str(exc_info.value) |
| 140 | + assert len(exc_info.value.exceptions) == 1 |
| 141 | + assert "Service desk unavailable" in str(exc_info.value.exceptions[0]) |
| 142 | + |
| 143 | + # Check that success was logged for the first article |
| 144 | + assert "Created issue for article https://example.com/article1" in caplog.text |
| 145 | + |
| 146 | + def test_create_service_desk_issues_all_failures( |
| 147 | + self, selected_articles: list[SelectedArticle], mock_service_desk: Mock, caplog: pytest.LogCaptureFixture |
| 148 | + ) -> None: |
| 149 | + """Test handling when all articles fail to create service desk issues.""" |
| 150 | + # Make all calls fail |
| 151 | + mock_service_desk.create_request_of_type.side_effect = Exception("Service desk down") |
| 152 | + |
| 153 | + with caplog.at_level(logging.ERROR), pytest.raises(ExceptionGroup) as exc_info: |
| 154 | + _create_service_desk_issues( |
| 155 | + selected_articles=selected_articles, |
| 156 | + service_desk_client=mock_service_desk, |
| 157 | + project_key="TEST", |
| 158 | + request_id_type="10001", |
| 159 | + ) |
| 160 | + |
| 161 | + # Verify both calls were attempted |
| 162 | + assert mock_service_desk.create_request_of_type.call_count == 2 |
| 163 | + |
| 164 | + # Check that ExceptionGroup contains all failures |
| 165 | + assert "Could not create all ServiceDesk issues" in str(exc_info.value) |
| 166 | + assert len(exc_info.value.exceptions) == 2 |
| 167 | + |
| 168 | + # Check error logging |
| 169 | + assert ( |
| 170 | + "Could not create ServiceDesk issue: Critical Security Vulnerability in Popular Library, https://example.com/article1" |
| 171 | + in caplog.text |
| 172 | + ) |
| 173 | + assert ( |
| 174 | + "Could not create ServiceDesk issue: New Attack Vector Discovered, https://example.com/article2" |
| 175 | + in caplog.text |
| 176 | + ) |
0 commit comments