#!/usr/bin/env python3 """ Unit tests for UI Error Handler. Tests error handling and recovery mechanisms for UI components. Requirements: 9.1, 9.2, 9.3, 9.4 """ import pytest from unittest.mock import Mock, patch from datetime import datetime from src.core.ui_error_handler import ( UIErrorHandler, UIError, ValidationResult, ErrorCategory, ErrorSeverity ) from src.core.provider_summary_generator import ProviderSummary from src.core.improved_classification_prompt_manager import ClassificationResult class TestUIErrorHandler: """Test cases for UIErrorHandler.""" def setup_method(self): """Set up test fixtures.""" self.error_handler = UIErrorHandler() def test_initialization(self): """Test error handler initialization.""" assert self.error_handler is not None assert hasattr(self.error_handler, 'fallback_templates') assert hasattr(self.error_handler, 'validation_rules') def test_validate_provider_summary_structure_valid(self): """Test validation of valid provider summary.""" # Create valid summary summary = ProviderSummary( patient_name="John Doe", patient_phone="555-123-4567", classification="RED", confidence=0.8, reasoning="Patient expressing significant spiritual distress", indicators=["Loss of meaning", "Spiritual questioning"], severity_level="HIGH", urgency_level="URGENT", situation_description="Patient experiencing spiritual crisis requiring immediate attention", recommended_actions=["Contact within 24 hours", "Assess support needs"] ) result = self.error_handler.validate_provider_summary_structure(summary) assert isinstance(result, ValidationResult) assert result.is_valid assert len(result.errors) == 0 def test_validate_provider_summary_structure_missing_contact(self): """Test validation with missing contact information.""" # Create summary with missing contact info summary = ProviderSummary( patient_name="[Patient Name]", patient_phone="[Phone Number]", classification="RED", confidence=0.8, reasoning="Patient expressing significant spiritual distress", indicators=["Loss of meaning"], severity_level="HIGH", urgency_level="URGENT" ) result = self.error_handler.validate_provider_summary_structure(summary) assert not result.is_valid assert len(result.errors) >= 2 # Name and phone errors # Check for specific errors error_messages = [error.message for error in result.errors] assert any("Patient name is missing" in msg for msg in error_messages) assert any("Patient phone is missing" in msg for msg in error_messages) def test_validate_provider_summary_structure_invalid_confidence(self): """Test validation with invalid confidence value.""" summary = ProviderSummary( patient_name="John Doe", patient_phone="555-123-4567", classification="RED", confidence=1.5, # Invalid - out of range reasoning="Test reasoning", indicators=["Test indicator"] ) result = self.error_handler.validate_provider_summary_structure(summary) assert not result.is_valid confidence_errors = [e for e in result.errors if e.field == "confidence"] assert len(confidence_errors) > 0 assert "out of valid range" in confidence_errors[0].message def test_validate_provider_summary_structure_missing_reasoning(self): """Test validation with missing reasoning.""" summary = ProviderSummary( patient_name="John Doe", patient_phone="555-123-4567", classification="RED", confidence=0.8, reasoning="", # Empty reasoning indicators=["Test indicator"] ) result = self.error_handler.validate_provider_summary_structure(summary) assert not result.is_valid reasoning_errors = [e for e in result.errors if e.field == "reasoning"] assert len(reasoning_errors) > 0 assert "missing or insufficient" in reasoning_errors[0].message def test_apply_fallback_template_missing_contact(self): """Test applying fallback template for missing contact information.""" summary = ProviderSummary( patient_name="[Patient Name]", patient_phone="[Phone Number]", classification="RED", confidence=0.8, reasoning="Test reasoning", indicators=["Test indicator"] ) fixed_summary = self.error_handler.apply_fallback_template(summary, "missing_contact") assert fixed_summary.patient_name != "[Patient Name]" assert fixed_summary.patient_phone != "[Phone Number]" assert "Patient (Name Not Provided)" in fixed_summary.patient_name assert "not available" in fixed_summary.patient_phone.lower() def test_apply_fallback_template_missing_reasoning(self): """Test applying fallback template for missing reasoning.""" summary = ProviderSummary( patient_name="John Doe", patient_phone="555-123-4567", classification="RED", confidence=0.8, reasoning="", # Empty reasoning indicators=["Loss of meaning", "Spiritual distress"] ) fixed_summary = self.error_handler.apply_fallback_template(summary, "missing_reasoning") assert len(fixed_summary.reasoning) > 10 assert "RED flag classification" in fixed_summary.reasoning assert "Loss of meaning" in fixed_summary.reasoning def test_apply_fallback_template_invalid_levels(self): """Test applying fallback template for invalid severity/urgency levels.""" summary = ProviderSummary( patient_name="John Doe", patient_phone="555-123-4567", classification="RED", confidence=0.8, reasoning="Test reasoning", indicators=["Test indicator"], severity_level="INVALID", urgency_level="INVALID" ) fixed_summary = self.error_handler.apply_fallback_template(summary, "invalid_levels") assert fixed_summary.severity_level in ["CRITICAL", "HIGH", "MODERATE"] assert fixed_summary.urgency_level in ["IMMEDIATE", "URGENT", "STANDARD"] def test_apply_fallback_template_missing_actions(self): """Test applying fallback template for missing recommended actions.""" summary = ProviderSummary( patient_name="John Doe", patient_phone="555-123-4567", classification="RED", confidence=0.8, reasoning="Test reasoning", indicators=["Test indicator"], urgency_level="URGENT", recommended_actions=[] # Empty actions ) fixed_summary = self.error_handler.apply_fallback_template(summary, "missing_actions") assert len(fixed_summary.recommended_actions) > 0 assert any("Contact patient" in action for action in fixed_summary.recommended_actions) def test_create_degraded_display(self): """Test creating degraded display for errors.""" error_context = "Test error occurred" original_content = "