Spaces:
Sleeping
Sleeping
Fix dark mode input font color and improve UI accessibility - Fixed dark mode input textbox font color for better visibility - Increased chatbot response font size - Enhanced Spanish language support for search intent detection - Improved email request detection and transit/school context handling - Integrated violation checker into search flow - Added comprehensive test suites for regex and LLM fallback validation
67e153c | #!/usr/bin/env python3 | |
| """ | |
| Integration tests for handoff detection system. | |
| Tests interaction with other tools and ensures appropriate handoff decisions. | |
| """ | |
| import pytest | |
| from escalation.handoff_detector import HandoffDetector, final_answer | |
| from escalation.contact_directory import get_contact_info | |
| class TestHandoffIntegration: | |
| """Test suite for handoff detection integration.""" | |
| def detector(self): | |
| """Create a HandoffDetector instance for testing.""" | |
| return HandoffDetector() | |
| def context(self): | |
| """Create a sample context for testing.""" | |
| return { | |
| "voucher_type": "CityFHEPS", | |
| "borough": "Brooklyn" | |
| } | |
| def test_search_vs_handoff(self, detector, context): | |
| """Test that search-related queries don't trigger handoff.""" | |
| search_queries = [ | |
| # Basic searches | |
| "Find apartments in Brooklyn", | |
| "Show me places that accept Section 8", | |
| "Search for 2 bedroom units", | |
| "List CityFHEPS apartments", | |
| # Complex searches | |
| "Find 2 bedroom apartments in Manhattan under $2500 that accept Section 8", | |
| "Show me pet-friendly units in Brooklyn with CityFHEPS", | |
| "Looking for accessible apartments near trains that take HASA", | |
| "Search for available units with laundry and elevator", | |
| # Search with help terms | |
| "Help me find apartments", | |
| "I need help searching for places", | |
| "Can you help locate units?", | |
| "Assist me in finding housing", | |
| # Questions about search | |
| "How do I search for apartments?", | |
| "What should I look for in listings?", | |
| "Where can I find more listings?", | |
| "What areas should I search in?", | |
| # Search refinements | |
| "Can you narrow down the search?", | |
| "Show me different options", | |
| "Filter by price range", | |
| "Sort by location" | |
| ] | |
| for query in search_queries: | |
| needs_handoff, reason, contact_info = detector.detect_handoff(query, context) | |
| assert needs_handoff is False, f"Search query incorrectly triggered handoff: {query}" | |
| assert reason is None | |
| assert contact_info is None | |
| def test_mixed_intent_handling(self, detector, context): | |
| """Test handling of messages with both search and handoff intent.""" | |
| mixed_queries = [ | |
| # Should trigger handoff | |
| ("I've been searching but need to talk to someone about discrimination", True), | |
| ("Can't find anything, can I speak with a caseworker?", True), | |
| ("Looking at listings but landlords won't take my voucher", True), | |
| ("Tried searching but need help understanding my rights", True), | |
| ("Been looking all day but need to report discrimination", True), | |
| # Should not trigger handoff | |
| ("Help me search for better apartments", False), | |
| ("Need help finding more listings", False), | |
| ("Can you help me look in different areas?", False), | |
| ("Assist me with my apartment search", False), | |
| ("Help me understand the search results", False) | |
| ] | |
| for query, should_handoff in mixed_queries: | |
| needs_handoff, reason, contact_info = detector.detect_handoff(query, context) | |
| assert needs_handoff == should_handoff, f"Wrong handoff decision for: {query}" | |
| if should_handoff: | |
| assert reason in ["user_request", "discrimination_case"] | |
| assert contact_info is not None | |
| else: | |
| assert reason is None | |
| assert contact_info is None | |
| def test_discrimination_with_borough(self, detector): | |
| """Test discrimination cases with borough-specific routing.""" | |
| test_cases = [ | |
| # Manhattan cases | |
| { | |
| "message": "Landlord in Manhattan won't take my voucher", | |
| "context": {"voucher_type": "Section 8", "borough": "manhattan"}, | |
| "expected_office": "Manhattan NYCHA Section 8 Office" | |
| }, | |
| # Brooklyn cases | |
| { | |
| "message": "Broker in Brooklyn is discriminating", | |
| "context": {"voucher_type": "CityFHEPS", "borough": "brooklyn"}, | |
| "expected_office": "Brooklyn CityFHEPS Office" | |
| }, | |
| # Bronx cases | |
| { | |
| "message": "Agent in the Bronx keeps making excuses", | |
| "context": {"voucher_type": "HASA", "borough": "bronx"}, | |
| "expected_office": "HIV/AIDS Services Administration" # HASA doesn't have borough offices | |
| } | |
| ] | |
| for case in test_cases: | |
| needs_handoff, reason, contact_info = detector.detect_handoff(case["message"], case["context"]) | |
| assert needs_handoff is True | |
| assert reason == "discrimination_case" | |
| assert contact_info is not None | |
| if "Office" in case["expected_office"]: | |
| assert contact_info["name"] == case["expected_office"] | |
| def test_handoff_message_formatting(self, detector, context): | |
| """Test that handoff messages are properly formatted.""" | |
| test_cases = [ | |
| # User request | |
| { | |
| "message": "Can I speak with someone?", | |
| "expected_content": ["speak with a human caseworker", "phone", "email", "address"] | |
| }, | |
| # Discrimination case | |
| { | |
| "message": "Landlord won't take my voucher", | |
| "expected_content": ["housing discrimination", "illegal in nyc", "commission on human rights"] | |
| } | |
| ] | |
| for case in test_cases: | |
| needs_handoff, reason, contact_info = detector.detect_handoff(case["message"], context) | |
| assert needs_handoff is True | |
| # Format the message | |
| formatted_msg = detector.format_handoff_message(reason, contact_info) | |
| # Check required content | |
| for content in case["expected_content"]: | |
| assert content in formatted_msg.lower() | |
| # Check contact info inclusion | |
| assert contact_info["phone"] in formatted_msg | |
| assert contact_info["email"] in formatted_msg | |
| assert contact_info["address"] in formatted_msg | |
| def test_non_interference_with_tools(self, detector, context): | |
| """Test that handoff detection doesn't interfere with other tool operations.""" | |
| tool_specific_queries = [ | |
| # Search tool queries | |
| "Search for apartments in Brooklyn", | |
| "Find Section 8 units", | |
| "Look for 2 bedrooms", | |
| # Filter tool queries | |
| "Filter by price under $2000", | |
| "Show only pet-friendly units", | |
| "Filter to elevator buildings", | |
| # Sort tool queries | |
| "Sort by price", | |
| "Order by distance", | |
| "Sort newest first", | |
| # Map tool queries | |
| "Show on map", | |
| "Display locations", | |
| "View on map", | |
| # Save/favorite tool queries | |
| "Save this listing", | |
| "Add to favorites", | |
| "Bookmark this one" | |
| ] | |
| for query in tool_specific_queries: | |
| needs_handoff, reason, contact_info = detector.detect_handoff(query, context) | |
| assert needs_handoff is False, f"Tool query incorrectly triggered handoff: {query}" | |
| assert reason is None | |
| assert contact_info is None | |
| def test_contact_info_accuracy(self): | |
| """Test that contact information is accurate and complete.""" | |
| test_cases = [ | |
| # CityFHEPS | |
| { | |
| "voucher_type": "CityFHEPS", | |
| "borough": "brooklyn", | |
| "is_discrimination": False, | |
| "expected_name": "Brooklyn CityFHEPS Office" | |
| }, | |
| # Section 8 | |
| { | |
| "voucher_type": "Section 8", | |
| "borough": "manhattan", | |
| "is_discrimination": True, | |
| "expected_name": "NYC Commission on Human Rights" | |
| }, | |
| # HASA | |
| { | |
| "voucher_type": "HASA", | |
| "borough": None, | |
| "is_discrimination": True, | |
| "expected_name": "Housing Works Legal Team" | |
| } | |
| ] | |
| for case in test_cases: | |
| contact_info = get_contact_info( | |
| voucher_type=case["voucher_type"], | |
| borough=case["borough"], | |
| is_discrimination=case["is_discrimination"] | |
| ) | |
| assert contact_info["name"] == case["expected_name"] | |
| assert all(key in contact_info for key in ["phone", "email", "address", "hours"]) | |
| assert all(contact_info[key] for key in ["phone", "email", "address", "hours"]) |