test_integration.py•7.21 kB
"""
Integration tests for Mac Messages MCP server
Tests all MCP tools to ensure they don't crash and handle edge cases properly
"""
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from mac_messages_mcp.messages import (
    _check_imessage_availability,
    _send_message_sms,
    check_addressbook_access,
    check_messages_db_access,
    find_contact_by_name,
    fuzzy_search_messages,
    get_recent_messages,
)
def test_import_fixes():
    """Test that the critical import fixes work"""
    print("Testing import fixes...")
    
    # Test that thefuzz import works
    try:
        from thefuzz import fuzz
        print("✅ thefuzz import works")
        return True
    except ImportError as e:
        print(f"❌ thefuzz import failed: {e}")
        return False
def test_input_validation():
    """Test input validation prevents crashes"""
    print("Testing input validation...")
    
    # Test negative hours
    result = get_recent_messages(hours=-1)
    assert "Error: Hours cannot be negative" in result
    print("✅ Negative hours validation works")
    
    # Test overflow hours
    result = get_recent_messages(hours=999999999)
    assert "Error: Hours value too large" in result
    print("✅ Overflow hours validation works")
    
    # Test empty search term
    result = fuzzy_search_messages("")
    assert "Error: Search term cannot be empty" in result
    print("✅ Empty search term validation works")
    
    # Test invalid threshold
    result = fuzzy_search_messages("test", threshold=-0.1)
    assert "Error: Threshold must be between 0.0 and 1.0" in result
    print("✅ Invalid threshold validation works")
    
    return True
def test_contact_selection_validation():
    """Test contact selection validation"""
    print("Testing contact selection validation...")
    
    # Test invalid contact formats
    test_cases = [
        ("contact:", "Error: Invalid contact selection format"),
        ("contact:abc", "Error: Contact selection must be a number"),
        ("contact:-1", "Error: Contact selection must be a positive number"),
        ("contact:0", "Error: Contact selection must be a positive number"),
    ]
    
    for contact, expected_error in test_cases:
        result = get_recent_messages(contact=contact)
        assert expected_error in result, f"Expected '{expected_error}' in result for '{contact}'"
    
    print("✅ Contact selection validation works")
    return True
def test_no_crashes():
    """Test that basic functionality doesn't crash"""
    print("Testing basic functionality doesn't crash...")
    
    # Test basic message retrieval
    try:
        result = get_recent_messages(hours=1)
        assert isinstance(result, str)
        assert "NameError" not in result
        assert "name 'fuzz' is not defined" not in result
        print("✅ get_recent_messages doesn't crash")
    except Exception as e:
        print(f"❌ get_recent_messages crashed: {e}")
        return False
    
    # Test fuzzy search
    try:
        result = fuzzy_search_messages("test", hours=1)
        assert isinstance(result, str)
        assert "NameError" not in result
        assert "name 'fuzz' is not defined" not in result
        print("✅ fuzzy_search_messages doesn't crash")
    except Exception as e:
        print(f"❌ fuzzy_search_messages crashed: {e}")
        return False
    
    # Test database access checks
    try:
        result = check_messages_db_access()
        assert isinstance(result, str)
        print("✅ check_messages_db_access doesn't crash")
    except Exception as e:
        print(f"❌ check_messages_db_access crashed: {e}")
        return False
    
    try:
        result = check_addressbook_access()
        assert isinstance(result, str)
        print("✅ check_addressbook_access doesn't crash")
    except Exception as e:
        print(f"❌ check_addressbook_access crashed: {e}")
        return False
    
    return True
def test_time_ranges():
    """Test various time ranges that previously failed"""
    print("Testing various time ranges...")
    
    time_ranges = [1, 24, 168, 720, 2160, 4320, 8760]  # 1h to 1 year
    
    for hours in time_ranges:
        try:
            result = get_recent_messages(hours=hours)
            assert isinstance(result, str)
            assert "Python int too large" not in result
            assert "NameError" not in result
        except Exception as e:
            print(f"❌ Time range {hours} hours failed: {e}")
            return False
    
    print("✅ All time ranges work without crashing")
    return True
def test_sms_fallback_functionality():
    """Test SMS/RCS fallback functions don't crash with import errors"""
    print("Testing SMS/RCS fallback functionality...")
    
    # Test iMessage availability check
    try:
        result = _check_imessage_availability("+15551234567")
        assert isinstance(result, bool), "iMessage availability check should return boolean"
        print("✅ iMessage availability check works")
    except Exception as e:
        # AppleScript errors are expected in test environment, but not import errors
        if "NameError" in str(e) or "ImportError" in str(e):
            print(f"❌ Import error in iMessage check: {e}")
            return False
        print(f"✅ iMessage availability check handles exceptions properly: {type(e).__name__}")
    
    # Test SMS sending function
    try:
        result = _send_message_sms("+15551234567", "test message")
        assert isinstance(result, str), "SMS send should return string result"
        print("✅ SMS sending function works")
    except Exception as e:
        # AppleScript errors are expected in test environment, but not import errors
        if "NameError" in str(e) or "ImportError" in str(e):
            print(f"❌ Import error in SMS send: {e}")
            return False
        print(f"✅ SMS sending function handles exceptions properly: {type(e).__name__}")
    
    return True
def run_all_tests():
    """Run all tests and report results"""
    print("🚀 Running Mac Messages MCP Integration Tests")
    print("=" * 50)
    
    tests = [
        test_import_fixes,
        test_input_validation,
        test_contact_selection_validation,
        test_no_crashes,
        test_time_ranges,
        test_sms_fallback_functionality,
    ]
    
    passed = 0
    failed = 0
    
    for test in tests:
        try:
            if test():
                passed += 1
                print(f"✅ {test.__name__} PASSED")
            else:
                failed += 1
                print(f"❌ {test.__name__} FAILED")
        except Exception as e:
            failed += 1
            print(f"❌ {test.__name__} CRASHED: {e}")
        print()
    
    print("=" * 50)
    print(f"🎯 Test Results: {passed} passed, {failed} failed")
    
    if failed == 0:
        print("🎉 ALL TESTS PASSED! The fixes are working correctly.")
        return True
    else:
        print("💥 SOME TESTS FAILED! There are still issues to fix.")
        return False
if __name__ == "__main__":
    success = run_all_tests()
    sys.exit(0 if success else 1)