mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 07:51:09 -05:00
- Added comprehensive documentation for hybrid filtering implementation, including architecture, API endpoints, performance characteristics, and usage examples. - Developed a hybrid pagination and client-side filtering recommendation, detailing server-side responsibilities and client-side logic. - Created a test script for hybrid filtering endpoints, covering various test cases including basic filtering, search functionality, pagination, and edge cases.
409 lines
17 KiB
Bash
Executable File
409 lines
17 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# ThrillWiki Hybrid Filtering Endpoints Test Script
|
|
# Tests the newly synchronized Parks and Rides hybrid filtering endpoints
|
|
#
|
|
# Usage: ./test_hybrid_endpoints.sh [BASE_URL]
|
|
# Default BASE_URL: http://localhost:8000
|
|
|
|
set -e
|
|
|
|
# Configuration
|
|
BASE_URL="${1:-http://localhost:8000}"
|
|
VERBOSE=true
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
BLUE='\033[0;34m'
|
|
YELLOW='\033[1;33m'
|
|
PURPLE='\033[0;35m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Helper functions
|
|
print_header() {
|
|
local title="$1"
|
|
local level="${2:-1}"
|
|
|
|
case $level in
|
|
1) echo -e "\n${BLUE}================================================================================${NC}"
|
|
echo -e "${BLUE}$title${NC}"
|
|
echo -e "${BLUE}================================================================================${NC}" ;;
|
|
2) echo -e "\n${CYAN}--------------------------------------------------------------------------------${NC}"
|
|
echo -e "${CYAN}$title${NC}"
|
|
echo -e "${CYAN}--------------------------------------------------------------------------------${NC}" ;;
|
|
3) echo -e "\n${YELLOW}$title${NC}"
|
|
echo -e "${YELLOW}$(echo "$title" | sed 's/./~/g')${NC}" ;;
|
|
esac
|
|
}
|
|
|
|
print_endpoint() {
|
|
local method="$1"
|
|
local url="$2"
|
|
echo -e "\n${PURPLE}🔗 ENDPOINT:${NC} ${GREEN}$method${NC} $url"
|
|
}
|
|
|
|
print_description() {
|
|
local desc="$1"
|
|
echo -e "${CYAN}📋 DESCRIPTION:${NC} $desc"
|
|
}
|
|
|
|
make_request() {
|
|
local method="$1"
|
|
local url="$2"
|
|
local description="$3"
|
|
|
|
print_endpoint "$method" "$url"
|
|
print_description "$description"
|
|
|
|
echo -e "\n${YELLOW}📤 REQUEST:${NC}"
|
|
echo "curl -X $method \\"
|
|
echo " -H 'Accept: application/json' \\"
|
|
echo " -H 'Content-Type: application/json' \\"
|
|
echo " '$url'"
|
|
|
|
echo -e "\n${YELLOW}📥 RESPONSE:${NC}"
|
|
|
|
# Make the actual request
|
|
response=$(curl -s -w "\n%{http_code}" -X "$method" \
|
|
-H "Accept: application/json" \
|
|
-H "Content-Type: application/json" \
|
|
"$url")
|
|
|
|
# Extract status code and body
|
|
status_code=$(echo "$response" | tail -n1)
|
|
body=$(echo "$response" | sed '$d')
|
|
|
|
# Print status
|
|
if [[ "$status_code" -ge 200 && "$status_code" -lt 300 ]]; then
|
|
echo -e "${GREEN}✅ SUCCESS: HTTP $status_code${NC}"
|
|
else
|
|
echo -e "${RED}❌ ERROR: HTTP $status_code${NC}"
|
|
fi
|
|
|
|
# Pretty print JSON response
|
|
if command -v jq >/dev/null 2>&1; then
|
|
echo "$body" | jq '.'
|
|
else
|
|
echo "$body"
|
|
fi
|
|
|
|
# Extract and display key metrics
|
|
if command -v jq >/dev/null 2>&1 && [[ "$status_code" -ge 200 && "$status_code" -lt 300 ]]; then
|
|
echo -e "\n${CYAN}📊 RESPONSE SUMMARY:${NC}"
|
|
|
|
# Total count
|
|
total_count=$(echo "$body" | jq -r '.total_count // empty')
|
|
if [[ -n "$total_count" ]]; then
|
|
echo -e " • Total Count: ${GREEN}$total_count${NC}"
|
|
fi
|
|
|
|
# Strategy
|
|
strategy=$(echo "$body" | jq -r '.strategy // empty')
|
|
if [[ -n "$strategy" ]]; then
|
|
if [[ "$strategy" == "client_side" ]]; then
|
|
echo -e " • Strategy: ${GREEN}🖥️ $strategy${NC}"
|
|
else
|
|
echo -e " • Strategy: ${BLUE}🌐 $strategy${NC}"
|
|
fi
|
|
fi
|
|
|
|
# Has more
|
|
has_more=$(echo "$body" | jq -r '.has_more // empty')
|
|
if [[ -n "$has_more" ]]; then
|
|
if [[ "$has_more" == "true" ]]; then
|
|
echo -e " • Has More: ${YELLOW}➡️ $has_more${NC}"
|
|
else
|
|
echo -e " • Has More: ${GREEN}🏁 $has_more${NC}"
|
|
fi
|
|
fi
|
|
|
|
# Next offset
|
|
next_offset=$(echo "$body" | jq -r '.next_offset // empty')
|
|
if [[ -n "$next_offset" && "$next_offset" != "null" ]]; then
|
|
echo -e " • Next Offset: ${CYAN}$next_offset${NC}"
|
|
fi
|
|
|
|
# Data counts
|
|
parks_count=$(echo "$body" | jq -r '.parks | length // empty' 2>/dev/null)
|
|
if [[ -n "$parks_count" ]]; then
|
|
echo -e " • Parks Returned: ${GREEN}$parks_count${NC}"
|
|
fi
|
|
|
|
rides_count=$(echo "$body" | jq -r '.rides | length // empty' 2>/dev/null)
|
|
if [[ -n "$rides_count" ]]; then
|
|
echo -e " • Rides Returned: ${GREEN}$rides_count${NC}"
|
|
fi
|
|
|
|
# Filter metadata summary
|
|
if echo "$body" | jq -e '.filter_metadata' >/dev/null 2>&1; then
|
|
echo -e " • Filter Metadata: ${GREEN}✅ Available${NC}"
|
|
|
|
# Count categorical options
|
|
countries=$(echo "$body" | jq -r '.filter_metadata.categorical.countries | length // 0' 2>/dev/null)
|
|
states=$(echo "$body" | jq -r '.filter_metadata.categorical.states | length // 0' 2>/dev/null)
|
|
categories=$(echo "$body" | jq -r '.filter_metadata.categorical.categories | length // 0' 2>/dev/null)
|
|
|
|
if [[ "$countries" -gt 0 ]]; then
|
|
echo -e " - Countries: ${CYAN}$countries${NC}"
|
|
fi
|
|
if [[ "$states" -gt 0 ]]; then
|
|
echo -e " - States: ${CYAN}$states${NC}"
|
|
fi
|
|
if [[ "$categories" -gt 0 ]]; then
|
|
echo -e " - Categories: ${CYAN}$categories${NC}"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
echo -e "\n${PURPLE}$(printf '%.0s-' {1..80})${NC}"
|
|
}
|
|
|
|
# Main test execution
|
|
main() {
|
|
print_header "THRILLWIKI HYBRID FILTERING ENDPOINTS TEST SUITE" 1
|
|
echo -e "Testing endpoints at: ${GREEN}$BASE_URL${NC}"
|
|
echo -e "Timestamp: ${CYAN}$(date)${NC}"
|
|
|
|
# Check if server is running
|
|
echo -e "\n${YELLOW}🔍 Checking server availability...${NC}"
|
|
if ! curl -s --connect-timeout 5 "$BASE_URL" >/dev/null; then
|
|
echo -e "${RED}❌ Server not available at $BASE_URL${NC}"
|
|
echo -e "${YELLOW}💡 Make sure to start the Django server first:${NC}"
|
|
echo -e " cd backend && uv run manage.py runserver_plus"
|
|
exit 1
|
|
fi
|
|
echo -e "${GREEN}✅ Server is running${NC}"
|
|
|
|
# ========================================================================
|
|
# PARKS HYBRID FILTERING TESTS
|
|
# ========================================================================
|
|
|
|
print_header "PARKS HYBRID FILTERING TESTS" 1
|
|
|
|
# Test 1: Basic Parks Hybrid Filtering
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/" \
|
|
"Basic hybrid filtering with no parameters - demonstrates automatic strategy selection"
|
|
|
|
# Test 2: Parks with Search Filter
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/?search=disney" \
|
|
"Search for parks containing 'disney' - tests full-text search functionality"
|
|
|
|
# Test 3: Parks with Status Filter
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/?status=OPERATING,CLOSED_TEMP" \
|
|
"Filter parks by multiple statuses - tests comma-separated list parameters"
|
|
|
|
# Test 4: Parks with Geographic Filters
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/?country=United%20States&state=Florida,California" \
|
|
"Filter parks by country and multiple states - tests geographic filtering"
|
|
|
|
# Test 5: Parks with Numeric Range Filters
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/?opening_year_min=1990&opening_year_max=2020&rating_min=4.0" \
|
|
"Filter parks by opening year range and minimum rating - tests numeric range filtering"
|
|
|
|
# Test 6: Parks with Size and Ride Count Filters
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/?size_min=100&ride_count_min=10&coaster_count_min=5" \
|
|
"Filter parks by minimum size, ride count, and coaster count - tests park statistics filtering"
|
|
|
|
# Test 7: Parks with Operator Filter
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/?operator=disney,universal" \
|
|
"Filter parks by operator slugs - tests company relationship filtering"
|
|
|
|
# Test 8: Parks Progressive Loading (with offset)
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/?offset=50" \
|
|
"Progressive loading starting at offset 50 - tests server-side pagination"
|
|
|
|
# Test 9: Parks Filter Metadata
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/filter-metadata/" \
|
|
"Get comprehensive filter metadata for parks - provides all available filter options and ranges"
|
|
|
|
# Test 10: Parks Scoped Filter Metadata
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/filter-metadata/?scoped=true&country=United%20States" \
|
|
"Get filter metadata scoped to US parks - demonstrates dynamic metadata based on current filters"
|
|
|
|
# ========================================================================
|
|
# RIDES HYBRID FILTERING TESTS
|
|
# ========================================================================
|
|
|
|
print_header "RIDES HYBRID FILTERING TESTS" 1
|
|
|
|
# Test 1: Basic Rides Hybrid Filtering
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/" \
|
|
"Basic hybrid filtering with no parameters - demonstrates automatic strategy selection for rides"
|
|
|
|
# Test 2: Rides with Search Filter
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/?search=coaster" \
|
|
"Search for rides containing 'coaster' - tests full-text search across ride names and descriptions"
|
|
|
|
# Test 3: Rides with Category Filter
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/?category=RC,DR" \
|
|
"Filter rides by categories (Roller Coaster, Dark Ride) - tests ride category filtering"
|
|
|
|
# Test 4: Rides with Status and Park Filters
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/?status=OPERATING&park_slug=cedar-point" \
|
|
"Filter operating rides at Cedar Point - tests status and park-specific filtering"
|
|
|
|
# Test 5: Rides with Manufacturer and Designer Filters
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/?manufacturer=bolliger-mabillard&designer=bolliger-mabillard" \
|
|
"Filter rides by B&M as manufacturer and designer - tests company relationship filtering"
|
|
|
|
# Test 6: Rides with Roller Coaster Specific Filters
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/?roller_coaster_type=INVERTED,FLYING&track_material=STEEL&has_inversions=true" \
|
|
"Filter inverted/flying steel coasters with inversions - tests roller coaster specific attributes"
|
|
|
|
# Test 7: Rides with Height and Speed Filters
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/?height_ft_min=200&speed_mph_min=70&inversions_min=4" \
|
|
"Filter tall, fast coasters with multiple inversions - tests numeric performance filtering"
|
|
|
|
# Test 8: Rides with Rating and Capacity Filters
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/?rating_min=4.5&capacity_min=1000&opening_year_min=2000" \
|
|
"Filter highly-rated, high-capacity modern rides - tests quality and operational metrics"
|
|
|
|
# Test 9: Rides with Height Requirement Filters
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/?height_requirement_min=48&height_requirement_max=54" \
|
|
"Filter rides by height requirements (48-54 inches) - tests accessibility filtering"
|
|
|
|
# Test 10: Rides Progressive Loading
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/?offset=25&category=RC" \
|
|
"Progressive loading of roller coasters starting at offset 25 - tests server-side pagination with filters"
|
|
|
|
# Test 11: Rides Filter Metadata
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/filter-metadata/" \
|
|
"Get comprehensive filter metadata for rides - provides all available filter options and ranges"
|
|
|
|
# Test 12: Rides Scoped Filter Metadata
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/filter-metadata/?scoped=true&category=RC" \
|
|
"Get filter metadata scoped to roller coasters - demonstrates dynamic metadata for specific categories"
|
|
|
|
# ========================================================================
|
|
# COMPLEX COMBINATION TESTS
|
|
# ========================================================================
|
|
|
|
print_header "COMPLEX COMBINATION TESTS" 1
|
|
|
|
# Test 1: Parks with All Filter Types
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/?search=theme&status=OPERATING&country=United%20States&opening_year_min=1980&rating_min=4.0&size_min=50&ride_count_min=20" \
|
|
"Complex parks query combining search, status, geographic, temporal, rating, and size filters"
|
|
|
|
# Test 2: Rides with All Filter Types
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/?search=steel&category=RC&status=OPERATING&roller_coaster_type=SITDOWN&track_material=STEEL&height_ft_min=100&speed_mph_min=50&rating_min=4.0&has_inversions=false" \
|
|
"Complex rides query combining search, category, status, coaster type, materials, performance, and rating filters"
|
|
|
|
# ========================================================================
|
|
# EDGE CASE TESTS
|
|
# ========================================================================
|
|
|
|
print_header "EDGE CASE TESTS" 1
|
|
|
|
# Test 1: Empty Results
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/?search=nonexistentpark12345" \
|
|
"Search for non-existent park - tests empty result handling"
|
|
|
|
# Test 2: Invalid Parameters
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/rides/hybrid/?height_ft_min=invalid&rating_min=15" \
|
|
"Invalid numeric parameters - tests parameter validation and error handling"
|
|
|
|
# Test 3: Large Offset
|
|
make_request "GET" \
|
|
"$BASE_URL/api/v1/parks/hybrid/?offset=99999" \
|
|
"Very large offset value - tests pagination boundary handling"
|
|
|
|
# ========================================================================
|
|
# PERFORMANCE COMPARISON TESTS
|
|
# ========================================================================
|
|
|
|
print_header "PERFORMANCE COMPARISON TESTS" 1
|
|
|
|
echo -e "\n${CYAN}📊 Testing response times for different strategies...${NC}"
|
|
|
|
# Time the requests
|
|
echo -e "\n${YELLOW}⏱️ Timing Parks Hybrid Endpoint:${NC}"
|
|
time curl -s -o /dev/null "$BASE_URL/api/v1/parks/hybrid/"
|
|
|
|
echo -e "\n${YELLOW}⏱️ Timing Rides Hybrid Endpoint:${NC}"
|
|
time curl -s -o /dev/null "$BASE_URL/api/v1/rides/hybrid/"
|
|
|
|
echo -e "\n${YELLOW}⏱️ Timing Parks Filter Metadata:${NC}"
|
|
time curl -s -o /dev/null "$BASE_URL/api/v1/parks/hybrid/filter-metadata/"
|
|
|
|
echo -e "\n${YELLOW}⏱️ Timing Rides Filter Metadata:${NC}"
|
|
time curl -s -o /dev/null "$BASE_URL/api/v1/rides/hybrid/filter-metadata/"
|
|
|
|
# ========================================================================
|
|
# SUMMARY
|
|
# ========================================================================
|
|
|
|
print_header "TEST SUITE SUMMARY" 1
|
|
|
|
echo -e "${GREEN}✅ Test suite completed successfully!${NC}"
|
|
echo -e "\n${CYAN}📋 ENDPOINTS TESTED:${NC}"
|
|
echo -e " • Parks Hybrid Filtering: ${GREEN}/api/v1/parks/hybrid/${NC}"
|
|
echo -e " • Parks Filter Metadata: ${GREEN}/api/v1/parks/hybrid/filter-metadata/${NC}"
|
|
echo -e " • Rides Hybrid Filtering: ${GREEN}/api/v1/rides/hybrid/${NC}"
|
|
echo -e " • Rides Filter Metadata: ${GREEN}/api/v1/rides/hybrid/filter-metadata/${NC}"
|
|
|
|
echo -e "\n${CYAN}🔍 KEY FEATURES DEMONSTRATED:${NC}"
|
|
echo -e " • Automatic strategy selection (client-side vs server-side)"
|
|
echo -e " • Progressive loading for large datasets"
|
|
echo -e " • Comprehensive filter options (17+ parameters per domain)"
|
|
echo -e " • Dynamic filter metadata generation"
|
|
echo -e " • Consistent response formats across domains"
|
|
echo -e " • Full-text search capabilities"
|
|
echo -e " • Numeric range filtering"
|
|
echo -e " • Multi-value parameter support"
|
|
echo -e " • Geographic and temporal filtering"
|
|
echo -e " • Roller coaster specific filtering"
|
|
echo -e " • Error handling and validation"
|
|
|
|
echo -e "\n${YELLOW}💡 NEXT STEPS:${NC}"
|
|
echo -e " • Integrate these endpoints into your frontend application"
|
|
echo -e " • Use filter metadata to build dynamic filter interfaces"
|
|
echo -e " • Implement progressive loading for better user experience"
|
|
echo -e " • Monitor performance and adjust thresholds as needed"
|
|
|
|
echo -e "\n${PURPLE}🎉 Happy filtering! 🎢${NC}"
|
|
}
|
|
|
|
# Check dependencies
|
|
check_dependencies() {
|
|
if ! command -v curl >/dev/null 2>&1; then
|
|
echo -e "${RED}❌ curl is required but not installed${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v jq >/dev/null 2>&1; then
|
|
echo -e "${YELLOW}⚠️ jq not found - JSON responses will not be pretty-printed${NC}"
|
|
fi
|
|
}
|
|
|
|
# Script execution
|
|
check_dependencies
|
|
main "$@"
|