#!/bin/bash # ============================================================================== # WellDrySense API Test Suite (Bash Version) # Functionality: Exercises Job APIs including Create, List, Edit, Details, Weather, # Sensor Data, and performs Database Cleanup. # ============================================================================== # --- Configuration --- # Load .env file if it exists if [ -f .env ]; then export $(cat .env | xargs) fi # Defaults (can be overridden by env vars) PORT="${PORT:-8002}" BASE_URL="http://localhost:$PORT/api/well_api" #API_USER="${API_USER:-jpeters}" #API_PASSWORD="${API_PASSWORD:-WellJson}" API_USER="${API_USER:-brankol}" API_PASSWORD="${API_PASSWORD:-branko_2025!}" DB_NAME="${DB_NAME:-wellnuo}" DB_USER="${DB_USER:-postgres}" DB_HOST="${DB_HOST:-localhost}" DB_PORT="${DB_PORT:-5432}" # DB_PASSWORD should be set in .env or exported # Colors GREEN='\033[0;32m' RED='\033[0;31m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Global Variables TOKEN="" USER_ID="" JOB_ID="" # Check for jq if ! command -v jq &> /dev/null; then echo -e "${RED}Error: 'jq' is not installed. Please install it to run this script.${NC}" exit 1 fi echo -e "${BLUE}=== Setting up WellDrySense Test Suite on Port $PORT ===${NC}" # ============================================================================== # Helper Functions # ============================================================================== # Function to print section headers print_header() { echo -e "\n${BLUE}----------------------------------------------------------------${NC}" echo -e "${BLUE}[Test] $1${NC}" } # Function to perform a POST request # Usage: perform_test "Test Name" "JSON_PAYLOAD_STRING" perform_test() { local test_name="$1" local json_payload="$2" print_header "$test_name" # 1. Print Request echo "# Request:" echo "$json_payload" | jq '.' # 2. Convert JSON to Form Data for curl (flattening simple objects) # Note: This simple conversion handles top-level keys. # Complex nested JSON strings (like 'devices') need to be passed as strings in the input JSON. local form_data="" # Extract keys and values and build form string while IFS="=" read -r key value; do if [ -n "$key" ]; then # URL encode the value encoded_value=$(printf '%s' "$value" | jq -sRr @uri) if [ -z "$form_data" ]; then form_data="${key}=${encoded_value}" else form_data="${form_data}&${key}=${encoded_value}" fi fi done < <(echo "$json_payload" | jq -r "to_entries|map(\"\(.key)=\(.value)\")|.[]") # 3. Execute Request response=$(curl -s -X POST "$BASE_URL" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "$form_data") # 4. Print Response echo -e "\n# Response:" if [ -z "$response" ]; then echo "(Empty Response)" echo -e "${RED}FAIL${NC}" return 1 else echo "$response" | jq '.' 2>/dev/null || echo "$response" fi # 5. Evaluate Pass/Fail based on "ok": 1 ok_val=$(echo "$response" | jq -r '.ok // .status // 0') # Handle different response structures (some return {status: 200}, some {ok: 1}) if [ "$ok_val" == "1" ] || [ "$ok_val" == "200" ] || [ "$ok_val" == "success" ]; then echo -e "${GREEN}PASS${NC}" # Extract Job ID if this was the create step if [ "$test_name" == "job_create" ]; then JOB_ID=$(echo "$response" | jq -r '.job_id') echo "-> Captured Job ID: $JOB_ID" fi return 0 else error_msg=$(echo "$response" | jq -r '.error // .message // "Unknown error"') echo -e "${RED}FAIL: $error_msg${NC}" return 1 fi } # ============================================================================== # Test Execution # ============================================================================== # 1. Login / Credentials # ---------------------- login_payload=$(jq -n \ --arg fn "credentials" \ --arg un "$API_USER" \ --arg ps "$API_PASSWORD" \ --arg cid "bash-suite" \ --arg nonce "test-nonce" \ '{function: $fn, user_name: $un, ps: $ps, clientId: $cid, nonce: $nonce}') print_header "Login" echo "# Request:" echo "$login_payload" | jq '.' # Special handling for login to capture token response=$(curl -s -X POST "$BASE_URL" -d "function=credentials&user_name=$API_USER&ps=$API_PASSWORD&clientId=bash-suite&nonce=test-nonce") echo -e "\n# Response:" echo "$response" | jq '.' TOKEN=$(echo "$response" | jq -r '.access_token // .data.access_token') USER_ID=$(echo "$response" | jq -r '.user_id // .data.user_id') if [ -n "$TOKEN" ] && [ "$TOKEN" != "null" ]; then echo -e "${GREEN}PASS${NC} (User ID: $USER_ID)" else echo -e "${RED}FATAL: Login failed. Check credentials.${NC}" exit 1 fi # # 2. Create Job # # ---------------------- # # Note: We pass JSON strings for complex fields like 'devices' and 'alerts_config' # devices_json='[{"mac": "TEST_MAC_VIRTUAL", "location": "Lab"}]' # alerts_json='{"temp_high": 30}' # create_payload=$(jq -n \ # --arg fn "job_create" \ # --arg un "$API_USER" \ # --arg tk "$TOKEN" \ # --arg cn "TEST_SUITE_CUSTOMER_BASH" \ # --arg as "123 Bash Script Ln" \ # --arg ac "Shellville" \ # --arg dev "$devices_json" \ # --arg lat "34.05" \ # --arg lng "-118.25" \ # '{function: $fn, user_name: $un, token: $tk, customer_name: $cn, address_street: $as, address_city: $ac, devices: $dev, lat: $lat, lng: $lng}') # perform_test "job_create" "$create_payload" || exit 1 # # 3. Job List # # ---------------------- # list_payload=$(jq -n \ # --arg fn "job_list" \ # --arg un "$API_USER" \ # --arg tk "$TOKEN" \ # '{function: $fn, user_name: $un, token: $tk}') # perform_test "job_list" "$list_payload" # # 3. Job List 2 (with added search) # # ---------------------- # list_payload=$(jq -n \ # --arg fn "job_list2" \ # --arg un "$API_USER" \ # --arg tk "$TOKEN" \ # --arg sch "" \ # '{function: $fn, user_name: $un, token: $tk, search: $sch}') # perform_test "job_list2" "$list_payload" # # 4. Job Details # # ---------------------- # details_payload=$(jq -n \ # --arg fn "job_details" \ # --arg un "$API_USER" \ # --arg tk "$TOKEN" \ # --arg jid "$JOB_ID" \ # '{function: $fn, user_name: $un, token: $tk, job_id: $jid}') # perform_test "job_details" "$details_payload" # # 5. Job Edit (Stop Job) # # ---------------------- # edit_payload=$(jq -n \ # --arg fn "job_edit" \ # --arg un "$API_USER" \ # --arg tk "$TOKEN" \ # --arg jid "$JOB_ID" \ # --arg st "Stopped" \ # --arg dt "2025-12-31T23:59:59" \ # '{function: $fn, user_name: $un, token: $tk, job_id: $jid, job_status: $st, date_to: $dt}') # perform_test "job_edit" "$edit_payload" # # 6. Available Devices (two versions, with direct SQL and via GetProximityList) # # ---------------------- # avail_payload=$(jq -n \ # --arg fn "job_available_devices" \ # --arg un "$API_USER" \ # --arg tk "$TOKEN" \ # '{function: $fn, user_name: $un, token: $tk}') # perform_test "job_available_devices" "$avail_payload" # # 6. Available Devices (Alternative Test using job_available_devices2, which is using GetProximityList) # avail_payload=$(jq -n \ # --arg fn "job_available_devices2" \ # --arg un "$API_USER" \ # --arg tk "$TOKEN" \ # '{function: $fn, user_name: $un, token: $tk}') # perform_test "job_available_devices2" "$avail_payload" # # 6. Available Devices(made reusing job_user_all_devices2, adding filter and search) # avail_payload=$(jq -n \ # --arg fn "job_devices" \ # --arg un "$API_USER" \ # --arg tk "$TOKEN" \ # --arg fl "all" \ # --arg sch "" \ # '{function: $fn, user_name: $un, token: $tk, filter: $fl, search: $sch}') # perform_test "job_devices" "$avail_payload" # # 7. Job Weather # # ---------------------- # weather_payload=$(jq -n \ # --arg fn "job_weather" \ # --arg un "$API_USER" \ # --arg tk "$TOKEN" \ # --arg jid "$JOB_ID" \ # '{function: $fn, user_name: $un, token: $tk, job_id: $jid}') # perform_test "job_weather" "$weather_payload" # # 8. Job Sensor Bucketed Data (New Test) # # ---------------------- # # Using dynamic dates for the test # DATE_FROM=$(date +%Y-%m-%d) # DATE_TO=$(date +%Y-%m-%d) # sensor_payload=$(jq -n \ # --arg fn "get_job_sensor_bucketed_data" \ # --arg un "$API_USER" \ # --arg tk "$TOKEN" \ # --arg jid "$JOB_ID" \ # --arg sens "temperature" \ # --arg dt "$DATE_FROM" \ # --arg dtt "$DATE_TO" \ # --arg bs "15m" \ # '{function: $fn, user_name: $un, token: $tk, job_id: $jid, sensor: $sens, date: $dt, to_date: $dtt, bucket_size: $bs}') # perform_test "get_job_sensor_bucketed_data" "$sensor_payload" # 9. device_list (New Test) # based on name=devices_list # &token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InJvYnN0ZXIiLCJleHAiOjE3NjQ3OTYwNzh9.t9rKVDRpSYOZGJMm2G0HYKSOOeaLypKwRGIJHehJBFE # &user_id=32 # &user_name=robster # &first=0 # &last=1000 # &privileges=-1 # # robster test device_list_payload=$(jq -n \ --arg fn "devices_list" \ --arg fid "0" \ --arg lid "1000" \ --arg priv "-1" \ --arg uid "32" \ --arg un "robster" \ --arg tk "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InJvYnN0ZXIiLCJleHAiOjE3NjQ3OTYwNzh9.t9rKVDRpSYOZGJMm2G0HYKSOOeaLypKwRGIJHehJBFE" \ '{function: $fn, name: $fn, user_id: $uid, user_name: $un, token: $tk, first: $fid, last: $lid, privileges: $priv}') perform_test "devices_list" "$device_list_payload" # brankol test device_list_payload=$(jq -n \ --arg fn "devices_list" \ --arg fid "0" \ --arg lid "1000" \ --arg priv "-1" \ --arg un "$API_USER" \ --arg tk "$TOKEN" \ '{function: $fn, name: $fn, user_name: $un, token: $tk, first: $fid, last: $lid, privileges: $priv}') # --arg uid "32" \ # --arg un "robster" \ # --arg tk "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InJvYnN0ZXIiLCJleHAiOjE3NjQ3OTYwNzh9.t9rKVDRpSYOZGJMm2G0HYKSOOeaLypKwRGIJHehJBFE" \ #'{name: $fn, user_id: $uid, user_name: $un, token: $tk, first: $fid, last: $lid, privileges: $priv}') perform_test "devices_list" "$device_list_payload" # device_list_payload=$(jq -n \ # --arg fn "devices_list" \ # --arg un "$API_USER" \ # --arg tk "$TOKEN" \ # --arg fid "0" \ # --arg lid "1000" \ # --arg priv "-1" \ # '{function: $fn, user_name: $un, token: $tk, first: $fid, last: $lid, privileges: $priv}') # perform_test "devices_list" "$device_list_payload" # # ============================================================================== # # Cleanup # # ============================================================================== # print_header "Cleanup" # if [ -n "$JOB_ID" ]; then # echo "-> Deleting Job ID: $JOB_ID from database..." # # Use PGPASSWORD for non-interactive auth if set # export PGPASSWORD="${DB_PASSWORD}" # psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "DELETE FROM public.jobs WHERE job_id = $JOB_ID;" > /dev/null 2>&1 # if [ $? -eq 0 ]; then # echo -e "${GREEN}Cleanup successful. Database restored.${NC}" # else # echo -e "${RED}Cleanup failed. Please manually delete job_id $JOB_ID from public.jobs.${NC}" # echo "Command attempted: psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c \"DELETE FROM public.jobs WHERE job_id = $JOB_ID;\"" # fi # else # echo "No Job ID created, skipping cleanup." # fi echo -e "\n${BLUE}=== Test Suite Finished ===${NC}" # ============================================================================== # well-api.py modifications to support WellDrySense API on port 1998 # ==============================================================================