bmc_hub/tests/test_email_reply_automation.py

68 lines
3.7 KiB
Python
Raw Normal View History

import asyncio
from unittest.mock import AsyncMock
import pytest
from app.services import email_workflow_service as module
@pytest.mark.parametrize('classification', ['spam', 'newsletter', 'invoice', 'general'])
def test_known_reply_routes_without_identity_approval(monkeypatch, classification):
service = module.EmailWorkflowService()
service.enabled = True
monkeypatch.setattr(service, '_find_sag_id_from_thread_headers', lambda data: 42)
monkeypatch.setattr(service, '_find_sag_id_from_thread_key', lambda key: 42)
route = AsyncMock(return_value={'status': 'completed', 'sag_id': 42})
monkeypatch.setattr(service, '_handle_helpdesk_sag_routing', route)
monkeypatch.setattr(service, '_find_matching_workflows', AsyncMock(return_value=[]))
result = asyncio.run(service.execute_workflows({
'id': 7, 'classification': classification, 'confidence_score': 0,
'sender_email': 'new-cc@example.dk', 'in_reply_to': '<known@example.dk>'}))
assert result['workflows_succeeded'] == 1
route.assert_awaited_once()
def test_unknown_newsletter_reply_does_not_override_skip(monkeypatch):
service = module.EmailWorkflowService()
service.enabled = True
monkeypatch.setattr(service, '_find_sag_id_from_thread_headers', lambda data: None)
monkeypatch.setattr(service, '_find_sag_id_from_thread_key', lambda key: None)
route = AsyncMock()
monkeypatch.setattr(service, '_handle_helpdesk_sag_routing', route)
monkeypatch.setattr(service, '_find_matching_workflows', AsyncMock(return_value=[]))
asyncio.run(service.execute_workflows({'id': 8, 'classification': 'newsletter', 'in_reply_to': '<unknown>'}))
route.assert_not_awaited()
@pytest.mark.parametrize('known_reply', [True, False])
def test_processor_bypasses_manual_gate_only_for_verified_route(monkeypatch, known_reply):
from app.services import email_processor_service as processor
service = processor.EmailProcessorService.__new__(processor.EmailProcessorService)
service.rules_enabled = False
monkeypatch.setattr(processor, 'execute_query', lambda *args: [])
monkeypatch.setattr(processor, 'execute_update', lambda *args: None)
monkeypatch.setattr(processor.settings, 'WHISPER_ENABLED', False)
monkeypatch.setattr(processor.settings, 'EMAIL_AUTO_CLASSIFY', False)
monkeypatch.setattr(processor.settings, 'EMAIL_REQUIRE_MANUAL_APPROVAL', True)
monkeypatch.setattr(processor.settings, 'EMAIL_WORKFLOWS_ENABLED', True)
monkeypatch.setattr(processor.email_workflow_service, 'has_verified_automatic_route', lambda data: known_reply)
execute = AsyncMock(return_value={'workflows_executed': 1, 'workflows_succeeded': 1})
monkeypatch.setattr(processor.email_workflow_service, 'execute_workflows', execute)
park = AsyncMock()
monkeypatch.setattr(service, '_set_awaiting_user_action', park)
result = asyncio.run(service.process_single_email({'id': 9, 'classification': 'general', 'confidence_score': 0}))
if known_reply:
execute.assert_awaited_once()
park.assert_not_awaited()
assert not result['awaiting_user_action']
else:
execute.assert_not_awaited()
park.assert_awaited_once()
assert result['awaiting_user_action']
def test_unknown_reply_header_is_not_a_verified_automatic_route(monkeypatch):
service = module.EmailWorkflowService()
monkeypatch.setattr(service, '_find_sag_id_from_thread_headers', lambda data: None)
monkeypatch.setattr(service, '_find_sag_id_from_thread_key', lambda key: None)
assert service.has_helpdesk_routing_hint({'in_reply_to': '<unknown@example>'}) is True
assert service.has_verified_automatic_route({'in_reply_to': '<unknown@example>'}) is False