mirror of
https://github.com/myronblair/epic-download
synced 2026-06-30 17:51:00 -05:00
291 lines
12 KiB
Python
291 lines
12 KiB
Python
#!/usr/bin/env python3
|
|
import requests
|
|
import sys
|
|
import json
|
|
from datetime import datetime
|
|
|
|
class EpicTravelAPITester:
|
|
def __init__(self, base_url="https://world-explorer-139.preview.emergentagent.com"):
|
|
self.base_url = base_url
|
|
self.api_url = f"{base_url}/api"
|
|
self.token = None
|
|
self.tests_run = 0
|
|
self.tests_passed = 0
|
|
self.test_results = []
|
|
|
|
def log_test(self, name, success, message="", response_data=None):
|
|
"""Log test results"""
|
|
self.tests_run += 1
|
|
if success:
|
|
self.tests_passed += 1
|
|
print(f"✅ {name}: PASSED - {message}")
|
|
else:
|
|
print(f"❌ {name}: FAILED - {message}")
|
|
|
|
self.test_results.append({
|
|
"test": name,
|
|
"status": "PASSED" if success else "FAILED",
|
|
"message": message,
|
|
"response_data": response_data
|
|
})
|
|
return success
|
|
|
|
def run_test(self, name, method, endpoint, expected_status, data=None, headers=None):
|
|
"""Run a single API test"""
|
|
url = f"{self.api_url}/{endpoint}"
|
|
test_headers = {'Content-Type': 'application/json'}
|
|
|
|
if self.token:
|
|
test_headers['Authorization'] = f'Bearer {self.token}'
|
|
|
|
if headers:
|
|
test_headers.update(headers)
|
|
|
|
try:
|
|
if method == 'GET':
|
|
response = requests.get(url, headers=test_headers)
|
|
elif method == 'POST':
|
|
response = requests.post(url, json=data, headers=test_headers)
|
|
elif method == 'PUT':
|
|
response = requests.put(url, json=data, headers=test_headers)
|
|
elif method == 'DELETE':
|
|
response = requests.delete(url, headers=test_headers)
|
|
|
|
success = response.status_code == expected_status
|
|
|
|
if success:
|
|
try:
|
|
response_data = response.json() if response.content else {}
|
|
return self.log_test(name, True, f"Status: {response.status_code}", response_data), response_data
|
|
except:
|
|
return self.log_test(name, True, f"Status: {response.status_code}", {}), {}
|
|
else:
|
|
try:
|
|
error_data = response.json() if response.content else {}
|
|
return self.log_test(name, False, f"Expected {expected_status}, got {response.status_code} - {error_data}"), {}
|
|
except:
|
|
return self.log_test(name, False, f"Expected {expected_status}, got {response.status_code}"), {}
|
|
|
|
except Exception as e:
|
|
return self.log_test(name, False, f"Error: {str(e)}"), {}
|
|
|
|
def test_health_check(self):
|
|
"""Test API health check"""
|
|
success, data = self.run_test("API Health Check", "GET", "", 200)
|
|
return success
|
|
|
|
def test_admin_login(self):
|
|
"""Test admin login"""
|
|
login_data = {
|
|
"email": "admin@epictravel.com",
|
|
"password": "admin123"
|
|
}
|
|
success, response = self.run_test("Admin Login", "POST", "auth/login", 200, login_data)
|
|
|
|
if success and 'access_token' in response:
|
|
self.token = response['access_token']
|
|
self.log_test("Token Extraction", True, "JWT token successfully extracted")
|
|
return True
|
|
else:
|
|
self.log_test("Token Extraction", False, "Failed to extract JWT token")
|
|
return False
|
|
|
|
def test_get_destinations(self):
|
|
"""Test getting all destinations"""
|
|
success, data = self.run_test("Get All Destinations", "GET", "destinations", 200)
|
|
if success and isinstance(data, list) and len(data) > 0:
|
|
self.log_test("Destinations Data Validation", True, f"Found {len(data)} destinations")
|
|
return data
|
|
else:
|
|
self.log_test("Destinations Data Validation", False, "No destinations returned or invalid data")
|
|
return []
|
|
|
|
def test_get_specials(self):
|
|
"""Test getting all specials"""
|
|
success, data = self.run_test("Get All Specials", "GET", "specials", 200)
|
|
if success and isinstance(data, list):
|
|
self.log_test("Specials Data Validation", True, f"Found {len(data)} specials")
|
|
return data
|
|
else:
|
|
self.log_test("Specials Data Validation", False, "Failed to get specials or invalid data")
|
|
return []
|
|
|
|
def test_search_destinations(self):
|
|
"""Test destination search functionality"""
|
|
# Test search by name
|
|
success, data = self.run_test("Search Destinations by Name", "GET", "destinations?search=Paris", 200)
|
|
if success:
|
|
found_paris = any(dest.get('name', '').lower() == 'paris' for dest in data)
|
|
if found_paris:
|
|
self.log_test("Search Results Validation", True, "Paris found in search results")
|
|
else:
|
|
self.log_test("Search Results Validation", False, "Paris not found in search results")
|
|
|
|
# Test filter by category
|
|
success, data = self.run_test("Filter Destinations by Category", "GET", "destinations?category=City", 200)
|
|
if success:
|
|
all_city = all(dest.get('category') == 'City' for dest in data)
|
|
if all_city:
|
|
self.log_test("Filter Results Validation", True, "All returned destinations are City type")
|
|
else:
|
|
self.log_test("Filter Results Validation", False, "Filter not working correctly")
|
|
|
|
def test_contact_form(self):
|
|
"""Test contact form submission"""
|
|
contact_data = {
|
|
"name": "Test User",
|
|
"email": "test@example.com",
|
|
"message": "This is a test contact message"
|
|
}
|
|
success, data = self.run_test("Contact Form Submission", "POST", "contact", 200, contact_data)
|
|
return success
|
|
|
|
def test_newsletter_subscription(self):
|
|
"""Test newsletter subscription"""
|
|
newsletter_data = {
|
|
"email": "newsletter@test.com"
|
|
}
|
|
success, data = self.run_test("Newsletter Subscription", "POST", "newsletter/subscribe", 200, newsletter_data)
|
|
return success
|
|
|
|
def test_admin_crud_operations(self):
|
|
"""Test full CRUD operations for destinations (requires authentication)"""
|
|
if not self.token:
|
|
self.log_test("CRUD Operations", False, "No authentication token available")
|
|
return False
|
|
|
|
# Test creating a new destination
|
|
new_destination = {
|
|
"name": "Test Destination",
|
|
"location": "Test Country",
|
|
"description": "A test destination for API testing",
|
|
"image": "https://via.placeholder.com/800x600",
|
|
"category": "City",
|
|
"rating": 4.5,
|
|
"price": 999,
|
|
"currency": "USD"
|
|
}
|
|
|
|
success, created_dest = self.run_test("Create New Destination", "POST", "destinations", 200, new_destination)
|
|
|
|
if not success:
|
|
return False
|
|
|
|
dest_id = created_dest.get('id')
|
|
if not dest_id:
|
|
self.log_test("Destination ID Extraction", False, "Failed to get destination ID from creation response")
|
|
return False
|
|
|
|
# Test updating the destination
|
|
update_data = {
|
|
"name": "Updated Test Destination",
|
|
"price": 1299
|
|
}
|
|
success, updated_dest = self.run_test("Update Destination", "PUT", f"destinations/{dest_id}", 200, update_data)
|
|
|
|
if success and updated_dest.get('name') == "Updated Test Destination":
|
|
self.log_test("Update Validation", True, "Destination updated successfully")
|
|
else:
|
|
self.log_test("Update Validation", False, "Destination update failed or data not persisted")
|
|
|
|
# Test getting single destination
|
|
success, single_dest = self.run_test("Get Single Destination", "GET", f"destinations/{dest_id}", 200)
|
|
|
|
# Test adding destination to specials
|
|
special_data = {
|
|
"destination_id": dest_id,
|
|
"discount": 25,
|
|
"end_date": "2025-12-31",
|
|
"highlights": ["Test special", "Limited time", "API test"]
|
|
}
|
|
success, created_special = self.run_test("Add Destination to Specials", "POST", "specials", 200, special_data)
|
|
|
|
special_id = created_special.get('id') if success else None
|
|
|
|
if special_id:
|
|
# Test updating special
|
|
special_update = {
|
|
"discount": 30,
|
|
"end_date": "2025-11-30"
|
|
}
|
|
success, updated_special = self.run_test("Update Special", "PUT", f"specials/{special_id}", 200, special_update)
|
|
|
|
# Test removing destination from specials
|
|
success, _ = self.run_test("Remove from Specials", "DELETE", f"specials/destination/{dest_id}", 200)
|
|
|
|
# Test deleting the destination (cleanup)
|
|
success, _ = self.run_test("Delete Test Destination", "DELETE", f"destinations/{dest_id}", 200)
|
|
|
|
return True
|
|
|
|
def run_all_tests(self):
|
|
"""Run all tests in sequence"""
|
|
print("🚀 Starting Epic Travel API Testing...")
|
|
print("=" * 50)
|
|
|
|
# Test 1: Health Check
|
|
print("\n📋 Testing Basic API Access...")
|
|
if not self.test_health_check():
|
|
print("❌ Health check failed, stopping tests")
|
|
return self.generate_summary()
|
|
|
|
# Test 2: Authentication
|
|
print("\n🔐 Testing Authentication...")
|
|
if not self.test_admin_login():
|
|
print("❌ Authentication failed, continuing with public endpoints only")
|
|
|
|
# Test 3: Public Endpoints
|
|
print("\n🌍 Testing Public Endpoints...")
|
|
destinations = self.test_get_destinations()
|
|
specials = self.test_get_specials()
|
|
self.test_search_destinations()
|
|
|
|
# Test 4: Forms
|
|
print("\n📝 Testing Form Submissions...")
|
|
self.test_contact_form()
|
|
self.test_newsletter_subscription()
|
|
|
|
# Test 5: Admin Operations
|
|
if self.token:
|
|
print("\n⚙️ Testing Admin CRUD Operations...")
|
|
self.test_admin_crud_operations()
|
|
else:
|
|
print("\n⚠️ Skipping Admin CRUD tests - No authentication token")
|
|
|
|
return self.generate_summary()
|
|
|
|
def generate_summary(self):
|
|
"""Generate test summary"""
|
|
print("\n" + "=" * 50)
|
|
print("📊 TEST SUMMARY")
|
|
print("=" * 50)
|
|
print(f"Tests Run: {self.tests_run}")
|
|
print(f"Tests Passed: {self.tests_passed}")
|
|
print(f"Tests Failed: {self.tests_run - self.tests_passed}")
|
|
print(f"Success Rate: {(self.tests_passed / self.tests_run * 100):.1f}%" if self.tests_run > 0 else "0%")
|
|
|
|
failed_tests = [test for test in self.test_results if test['status'] == 'FAILED']
|
|
if failed_tests:
|
|
print("\n❌ FAILED TESTS:")
|
|
for test in failed_tests:
|
|
print(f" - {test['test']}: {test['message']}")
|
|
|
|
print("\n" + "=" * 50)
|
|
|
|
return {
|
|
"total_tests": self.tests_run,
|
|
"passed_tests": self.tests_passed,
|
|
"failed_tests": self.tests_run - self.tests_passed,
|
|
"success_rate": (self.tests_passed / self.tests_run * 100) if self.tests_run > 0 else 0,
|
|
"detailed_results": self.test_results
|
|
}
|
|
|
|
def main():
|
|
tester = EpicTravelAPITester()
|
|
results = tester.run_all_tests()
|
|
|
|
# Return appropriate exit code
|
|
return 0 if results['failed_tests'] == 0 else 1
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |