""" Test script for the RoadTripService implementation. This script tests all functionality of the OSM Road Trip Service including: - Geocoding addresses - Route calculation - Park discovery along routes - Multi-park trip planning - Integration with existing Park models """ import os import sys import django # Setup Django os***REMOVED***iron.setdefault('DJANGO_SETTINGS_MODULE', 'thrillwiki.settings') django.setup() from parks.services import RoadTripService from parks.services.roadtrip import Coordinates from parks.models import Park from django.core.cache import cache def test_geocoding(): """Test geocoding functionality.""" print("\n=== Testing Geocoding ===") service = RoadTripService() # Test various address formats test_addresses = [ "Cedar Point, Sandusky, Ohio", "Magic Kingdom, Orlando, Florida", "Disneyland, Anaheim, California", "Six Flags Great Adventure, Jackson, New Jersey", "Invalid Address That Should Not Work 123456789" ] for address in test_addresses: print(f"\nGeocoding: {address}") coords = service.geocode_address(address) if coords: print(f" ✅ Success: {coords.latitude:.6f}, {coords.longitude:.6f}") else: print(f" ❌ Failed") # Test cache functionality print(f"\nTesting cache...") coords1 = service.geocode_address("Cedar Point, Sandusky, Ohio") coords2 = service.geocode_address("Cedar Point, Sandusky, Ohio") if coords1 and coords2: print(f" ✅ Cache working: {coords1.latitude == coords2.latitude}") def test_route_calculation(): """Test route calculation between coordinates.""" print("\n=== Testing Route Calculation ===") service = RoadTripService() # Cedar Point to Magic Kingdom (long distance) cedar_point = Coordinates(41.4793, -82.6833) magic_kingdom = Coordinates(28.4177, -81.5812) print(f"Calculating route from Cedar Point to Magic Kingdom...") route = service.calculate_route(cedar_point, magic_kingdom) if route: print(f" ✅ Success:") print(f" Distance: {route.formatted_distance}") print(f" Duration: {route.formatted_duration}") print(f" Geometry: {'Yes' if route.geometry else 'No'}") else: print(f" ❌ Failed") # Test short distance (should use OSRM) disneyland = Coordinates(33.8121, -117.9190) knotts = Coordinates(33.8442, -118.0000) print(f"\nCalculating route from Disneyland to Knott's Berry Farm...") route = service.calculate_route(disneyland, knotts) if route: print(f" ✅ Success:") print(f" Distance: {route.formatted_distance}") print(f" Duration: {route.formatted_duration}") else: print(f" ❌ Failed") def test_park_integration(): """Test integration with Park models.""" print("\n=== Testing Park Integration ===") service = RoadTripService() # Get some parks from the database parks = Park.objects.select_related('location').all()[:5] if not parks: print(" ⚠️ No parks found in database") return print(f"Found {len(parks)} parks to test with:") for park in parks: print(f" - {park.name}") if hasattr(park, 'location') and park.location: coords = park.coordinates if coords: print(f" 📍 {coords[0]:.4f}, {coords[1]:.4f}") else: print(f" 📍 No coordinates, will try to geocode...") success = service.geocode_park_if_needed(park) if success: coords = park.coordinates print(f" ✅ Geocoded to: {coords[0]:.4f}, {coords[1]:.4f}") else: print(f" ❌ Geocoding failed") else: print(f" ❌ No location data") def test_nearby_parks(): """Test finding nearby parks.""" print("\n=== Testing Nearby Park Discovery ===") service = RoadTripService() # Get a park with location data parks_with_location = Park.objects.filter( location__point__isnull=False ).select_related('location')[:1] if not parks_with_location: print(" ⚠️ No parks with location data found") return center_park = parks_with_location[0] print(f"Finding parks within 200km of {center_park.name}...") nearby_parks = service.get_park_distances(center_park, radius_km=200) if nearby_parks: print(f" ✅ Found {len(nearby_parks)} nearby parks:") for result in nearby_parks[:5]: # Show first 5 park = result['park'] print(f" {park.name}: {result['formatted_distance']}, {result['formatted_duration']}") else: print(f" ❌ No nearby parks found") def test_route_park_discovery(): """Test finding parks along a route.""" print("\n=== Testing Parks Along Route ===") service = RoadTripService() # Get two parks with location data parks_with_location = Park.objects.filter( location__point__isnull=False ).select_related('location')[:2] if len(parks_with_location) < 2: print(" ⚠️ Need at least 2 parks with location data") return start_park = parks_with_location[0] end_park = parks_with_location[1] print(f"Finding parks along route from {start_park.name} to {end_park.name}...") parks_along_route = service.find_parks_along_route( start_park, end_park, max_detour_km=100 ) if parks_along_route: print(f" ✅ Found {len(parks_along_route)} parks along route:") for park in parks_along_route[:3]: # Show first 3 print(f" - {park.name}") else: print(f" ❌ No parks found along route") def test_multi_park_trip(): """Test multi-park trip planning.""" print("\n=== Testing Multi-Park Trip Planning ===") service = RoadTripService() # Get parks with location data parks_with_location = Park.objects.filter( location__point__isnull=False ).select_related('location')[:4] if len(parks_with_location) < 3: print(" ⚠️ Need at least 3 parks with location data") return parks_list = list(parks_with_location) print(f"Planning trip for {len(parks_list)} parks:") for park in parks_list: print(f" - {park.name}") trip = service.create_multi_park_trip(parks_list) if trip: print(f" ✅ Trip planned successfully:") print(f" Total Distance: {trip.formatted_total_distance}") print(f" Total Duration: {trip.formatted_total_duration}") print(f" Route:") for i, leg in enumerate(trip.legs, 1): print(f" {i}. {leg.from_park.name} → {leg.to_park.name}") print(f" {leg.route.formatted_distance}, {leg.route.formatted_duration}") else: print(f" ❌ Trip planning failed") def test_error_handling(): """Test error handling and edge cases.""" print("\n=== Testing Error Handling ===") service = RoadTripService() # Test with invalid coordinates print("Testing invalid coordinates...") invalid_coords = Coordinates(999, 999) valid_coords = Coordinates(40.0, -80.0) route = service.calculate_route(invalid_coords, valid_coords) if route: print(f" ⚠️ Got route with invalid coords: {route.formatted_distance}") else: print(f" ✅ Correctly handled invalid coordinates") # Test with empty address print("Testing empty address geocoding...") coords = service.geocode_address("") if coords: print(f" ⚠️ Got coordinates for empty address") else: print(f" ✅ Correctly handled empty address") # Test with None values print("Testing None coordinates...") route = service.calculate_route(None, valid_coords) if route: print(f" ⚠️ Got route with None coordinates") else: print(f" ✅ Correctly handled None coordinates") def test_rate_limiting(): """Test rate limiting functionality.""" print("\n=== Testing Rate Limiting ===") service = RoadTripService() print("Making multiple rapid requests to test rate limiting...") import time start_time = time.time() # Make 3 rapid geocoding requests addresses = [ "Disney World, Orlando, FL", "Universal Studios, Orlando, FL", "SeaWorld, Orlando, FL" ] for address in addresses: coords = service.geocode_address(address) if coords: print(f" ✅ {address}: {coords.latitude:.4f}, {coords.longitude:.4f}") elapsed = time.time() - start_time print(f" Total time for 3 requests: {elapsed:.2f} seconds") if elapsed >= 2.0: # Should take at least 2 seconds with 1 req/sec limit print(f" ✅ Rate limiting appears to be working") else: print(f" ⚠️ Requests may have been cached or rate limiting not working") def main(): """Run all tests.""" print("🚗 ThrillWiki Road Trip Service Test Suite") print("=" * 50) # Clear cache to ensure fresh tests cache.clear() try: test_geocoding() test_route_calculation() test_park_integration() test_nearby_parks() test_route_park_discovery() test_multi_park_trip() test_error_handling() test_rate_limiting() print("\n" + "=" * 50) print("🎉 Test suite completed!") print("\nNote: Some tests may show failures if:") print("- No park data exists in the database") print("- Network connectivity issues") print("- OSM API rate limits exceeded") print("- Parks don't have location data") except Exception as e: print(f"\n❌ Test suite failed with error: {e}") import traceback traceback.print_exc() if __name__ == "__main__": main()