Files
rfcp/scripts/rfcp-integration-test.sh
2026-01-31 01:43:29 +02:00

275 lines
12 KiB
Bash

#!/bin/bash
# RFCP Frontend-Backend Integration Test
# Tests API endpoints that frontend uses
# Usage: ./rfcp-integration-test.sh [base_url]
BASE_URL="${1:-https://api.rfcp.eliah.one}"
PASSED=0
FAILED=0
# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " RFCP Integration Test (Frontend ↔ Backend)"
echo " Target: $BASE_URL"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
test_endpoint() {
local name="$1"
local method="$2"
local endpoint="$3"
local expected="$4"
local data="$5"
if [ "$method" == "GET" ]; then
response=$(curl -s -w "\n%{http_code}" "$BASE_URL$endpoint")
else
response=$(curl -s -w "\n%{http_code}" -X "$method" "$BASE_URL$endpoint" \
-H "Content-Type: application/json" \
-d "$data")
fi
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" == "200" ] && echo "$body" | grep -q "$expected"; then
echo -e "${GREEN}${NC} $name"
((PASSED++))
return 0
else
echo -e "${RED}${NC} $name (HTTP $http_code)"
echo " Expected: $expected"
echo " Got: ${body:0:100}..."
((FAILED++))
return 1
fi
}
# ═══════════════════════════════════════════════════
# Core API Tests
# ═══════════════════════════════════════════════════
echo -e "${CYAN}Core API${NC}"
echo "─────────────────────────────────────────────────"
test_endpoint "Health check" "GET" "/api/health/" '"status":"ok"'
test_endpoint "Database connection" "GET" "/api/health/db" '"database":"connected"'
test_endpoint "API version" "GET" "/" '"version"'
echo ""
# ═══════════════════════════════════════════════════
# Project API (state persistence)
# ═══════════════════════════════════════════════════
echo -e "${CYAN}Project API${NC}"
echo "─────────────────────────────────────────────────"
test_endpoint "Get project" "GET" "/api/projects/current" '"name":"global"'
test_endpoint "Get settings" "GET" "/api/projects/current/settings" '"radius"'
# Save test site
test_endpoint "Save sites" "PUT" "/api/projects/current/sites" '"updated"' \
'[{"id":"integration-test","name":"Integration Test Site","lat":48.46,"lon":35.05,"height":30,"power":43}]'
# Verify saved
test_endpoint "Verify sites" "GET" "/api/projects/current/sites" "Integration Test Site"
echo ""
# ═══════════════════════════════════════════════════
# Coverage API (main functionality)
# ═══════════════════════════════════════════════════
echo -e "${CYAN}Coverage API${NC}"
echo "─────────────────────────────────────────────────"
# Presets
test_endpoint "Get presets" "GET" "/api/coverage/presets" '"fast"'
# Coverage calculation
echo -n "Coverage calculation (fast)... "
start=$(date +%s)
calc_response=$(curl -s -X POST "$BASE_URL/api/coverage/calculate" \
-H "Content-Type: application/json" \
-d '{
"sites": [{"lat": 48.46, "lon": 35.05, "height": 30, "power": 43, "gain": 15, "frequency": 1800}],
"settings": {"radius": 1000, "resolution": 100, "preset": "fast"}
}')
end=$(date +%s)
# Validate response structure
has_points=$(echo "$calc_response" | jq 'has("points")')
has_stats=$(echo "$calc_response" | jq 'has("stats")')
has_time=$(echo "$calc_response" | jq 'has("computation_time")')
has_models=$(echo "$calc_response" | jq 'has("models_used")')
point_count=$(echo "$calc_response" | jq '.count')
if [ "$has_points" == "true" ] && [ "$has_stats" == "true" ] && [ "$has_time" == "true" ] && [ "$has_models" == "true" ] && [ "$point_count" -gt 0 ]; then
echo -e "${GREEN}${NC} Coverage calculation ($point_count points, $((end-start))s)"
((PASSED++))
else
echo -e "${RED}${NC} Coverage calculation - missing fields or no points"
((FAILED++))
fi
# Response structure check
echo -n "Response structure... "
min_rsrp=$(echo "$calc_response" | jq '.stats.min_rsrp')
max_rsrp=$(echo "$calc_response" | jq '.stats.max_rsrp')
models=$(echo "$calc_response" | jq -r '.models_used[]' | head -1)
if [ "$min_rsrp" != "null" ] && [ "$max_rsrp" != "null" ] && [ -n "$models" ]; then
echo -e "${GREEN}${NC} Response structure valid"
echo " RSRP: $min_rsrp to $max_rsrp dBm"
echo " Models: $(echo "$calc_response" | jq -r '.models_used | join(", ")')"
((PASSED++))
else
echo -e "${RED}${NC} Invalid response structure"
((FAILED++))
fi
# Buildings endpoint
test_endpoint "Get buildings" "GET" "/api/coverage/buildings?min_lat=48.455&min_lon=35.045&max_lat=48.465&max_lon=35.055" '"count"'
echo ""
# ═══════════════════════════════════════════════════
# Terrain API
# ═══════════════════════════════════════════════════
echo -e "${CYAN}Terrain API${NC}"
echo "─────────────────────────────────────────────────"
test_endpoint "Get elevation" "GET" "/api/terrain/elevation?lat=48.46&lon=35.05" '"elevation"'
# Elevation profile
echo -n "Elevation profile... "
profile_response=$(curl -s "$BASE_URL/api/terrain/profile?lat1=48.46&lon1=35.05&lat2=48.47&lon2=35.06&points=10")
profile_count=$(echo "$profile_response" | jq '.profile | length')
if [ "$profile_count" -eq 10 ]; then
echo -e "${GREEN}${NC} Elevation profile ($profile_count points)"
((PASSED++))
else
echo -e "${RED}${NC} Elevation profile (expected 10, got $profile_count)"
((FAILED++))
fi
# LoS check
test_endpoint "Line of Sight" "GET" "/api/terrain/los?tx_lat=48.46&tx_lon=35.05&tx_height=30&rx_lat=48.47&rx_lon=35.06" '"has_los"'
# Fresnel check
test_endpoint "Fresnel clearance" "GET" "/api/terrain/fresnel?tx_lat=48.46&tx_lon=35.05&tx_height=30&rx_lat=48.47&rx_lon=35.06&rx_height=1.5&frequency=1800" '"clearance_percent"'
echo ""
# ═══════════════════════════════════════════════════
# Error Handling
# ═══════════════════════════════════════════════════
echo -e "${CYAN}Error Handling${NC}"
echo "─────────────────────────────────────────────────"
# Invalid coordinates
echo -n "Invalid coordinates... "
error_response=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/api/terrain/elevation?lat=999&lon=999")
if [ "$error_response" == "422" ] || [ "$error_response" == "400" ]; then
echo -e "${GREEN}${NC} Returns error for invalid coords (HTTP $error_response)"
((PASSED++))
else
echo -e "${YELLOW}${NC} Unexpected response: HTTP $error_response"
fi
# Empty sites
echo -n "Empty sites array... "
empty_response=$(curl -s -X POST "$BASE_URL/api/coverage/calculate" \
-H "Content-Type: application/json" \
-d '{"sites": [], "settings": {"radius": 1000, "resolution": 100}}')
empty_code=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$BASE_URL/api/coverage/calculate" \
-H "Content-Type: application/json" \
-d '{"sites": [], "settings": {"radius": 1000, "resolution": 100}}')
if [ "$empty_code" == "400" ]; then
echo -e "${GREEN}${NC} Rejects empty sites (HTTP 400)"
((PASSED++))
else
echo -e "${YELLOW}${NC} Should reject empty sites (got HTTP $empty_code)"
fi
# Too large radius
echo -n "Radius limit... "
large_response=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$BASE_URL/api/coverage/calculate" \
-H "Content-Type: application/json" \
-d '{"sites": [{"lat": 48.46, "lon": 35.05, "height": 30, "power": 43, "gain": 15, "frequency": 1800}], "settings": {"radius": 100000, "resolution": 100}}')
if [ "$large_response" == "400" ]; then
echo -e "${GREEN}${NC} Rejects >50km radius (HTTP 400)"
((PASSED++))
else
echo -e "${YELLOW}${NC} Should limit radius (got HTTP $large_response)"
fi
echo ""
# ═══════════════════════════════════════════════════
# Performance Check
# ═══════════════════════════════════════════════════
echo -e "${CYAN}Performance${NC}"
echo "─────────────────────────────────────────────────"
echo -n "Fast preset timing... "
start=$(date +%s.%N)
curl -s -X POST "$BASE_URL/api/coverage/calculate" \
-H "Content-Type: application/json" \
-d '{"sites": [{"lat": 48.46, "lon": 35.05, "height": 30, "power": 43, "gain": 15, "frequency": 1800}], "settings": {"radius": 2000, "resolution": 100, "preset": "fast"}}' > /dev/null
end=$(date +%s.%N)
duration=$(echo "$end - $start" | bc)
if (( $(echo "$duration < 5" | bc -l) )); then
echo -e "${GREEN}${NC} Fast preset: ${duration}s (< 5s)"
((PASSED++))
else
echo -e "${YELLOW}${NC} Fast preset slow: ${duration}s (expected < 5s)"
fi
echo ""
# ═══════════════════════════════════════════════════
# Swagger/Docs
# ═══════════════════════════════════════════════════
echo -e "${CYAN}Documentation${NC}"
echo "─────────────────────────────────────────────────"
swagger_code=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/docs")
if [ "$swagger_code" == "200" ]; then
echo -e "${GREEN}${NC} Swagger UI accessible"
((PASSED++))
else
echo -e "${RED}${NC} Swagger UI (HTTP $swagger_code)"
((FAILED++))
fi
test_endpoint "OpenAPI schema" "GET" "/openapi.json" '"openapi"'
echo ""
# ═══════════════════════════════════════════════════
# Summary
# ═══════════════════════════════════════════════════
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
TOTAL=$((PASSED + FAILED))
if [ $FAILED -eq 0 ]; then
echo -e " ${GREEN}All tests passed!${NC} ($PASSED/$TOTAL)"
echo ""
echo " Frontend can safely integrate with this backend."
else
echo -e " ${YELLOW}Results:${NC} ${GREEN}$PASSED passed${NC}, ${RED}$FAILED failed${NC}"
echo ""
echo " Fix failing tests before frontend integration."
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
exit $FAILED