diff --git a/src/robusta/integrations/msteams/msteams_msg.py b/src/robusta/integrations/msteams/msteams_msg.py index 06b8c3076..86770a4cc 100644 --- a/src/robusta/integrations/msteams/msteams_msg.py +++ b/src/robusta/integrations/msteams/msteams_msg.py @@ -184,7 +184,9 @@ def send(self): self._put_text_files_data_up_to_max_limit(complete_card_map) response = requests.post(self.webhook_url, json=complete_card_map) - if response.status_code not in [200, 201]: + # Power Automate workflow webhooks accept the payload asynchronously and return 202, + # while legacy Office 365 connectors return 200. Both indicate success. + if response.status_code not in [200, 201, 202]: logging.error(f"Error sending to ms teams json: {complete_card_map} error: {response.reason}") if response.text and "error" in response.text.lower(): # teams error indication is in the text only :( diff --git a/tests/test_ms_teams_send.py b/tests/test_ms_teams_send.py new file mode 100644 index 000000000..4c7b11955 --- /dev/null +++ b/tests/test_ms_teams_send.py @@ -0,0 +1,40 @@ +from unittest.mock import MagicMock, patch + +import pytest + +from robusta.integrations.msteams.msteams_msg import MsTeamsMsg + + +def _mock_response(status_code: int, reason: str, text: str = ""): + response = MagicMock() + response.status_code = status_code + response.reason = reason + response.text = text + return response + + +@pytest.mark.parametrize( + "status_code, reason, should_log_error", + [ + (200, "OK", False), + (201, "Created", False), + # Power Automate workflow webhooks accept the payload asynchronously and + # return 202 on success. It must not be logged as an error. + (202, "Accepted", False), + (400, "Bad Request", True), + (500, "Internal Server Error", True), + ], +) +def test_ms_teams_send_status_code_logging(status_code, reason, should_log_error): + msg = MsTeamsMsg(webhook_url="http://example.com/webhook", prefer_redirect_to_platform=False) + response = _mock_response(status_code, reason, text="") + + with patch("robusta.integrations.msteams.msteams_msg.requests.post", return_value=response), patch( + "robusta.integrations.msteams.msteams_msg.logging" + ) as mock_logging: + msg.send() + + if should_log_error: + assert mock_logging.error.called, f"expected an error log for status {status_code}" + else: + mock_logging.error.assert_not_called()