#!/usr/bin/env python3 """ Test script to verify frontend-backend integration for tickets #141 and #143. Sends the exact payloads from frontend components and checks API responses. """ import requests import json import sys BASE_URL = "http://sf_api:8000/api/v1" LOGIN_URL = f"{BASE_URL}/auth/login" def get_auth_token(): """Login with admin credentials and return JWT token.""" payload = { "username": "admin@servicefinder.hu", "password": "Admin123!" } try: resp = requests.post(LOGIN_URL, json=payload, timeout=10) resp.raise_for_status() data = resp.json() token = data.get("access_token") if not token: print("ERROR: No access_token in login response") print(f"Response: {data}") sys.exit(1) print(f"SUCCESS: Obtained token (first 20 chars): {token[:20]}...") return token except requests.exceptions.RequestException as e: print(f"ERROR: Login failed: {e}") if hasattr(e, 'response') and e.response is not None: print(f"Response status: {e.response.status_code}") print(f"Response body: {e.response.text}") sys.exit(1) def test_vehicle_creation(token): """Test POST /api/v1/assets/vehicles with frontend payload.""" url = f"{BASE_URL}/assets/vehicles" headers = {"Authorization": f"Bearer {token}"} # Payload from AddVehicle.vue saveVehicle() payload = { "vin": None, "license_plate": "N/A", "catalog_id": None, "organization_id": 1 } print("\n--- Testing Vehicle Creation ---") print(f"URL: {url}") print(f"Payload: {json.dumps(payload, indent=2)}") try: resp = requests.post(url, json=payload, headers=headers, timeout=10) print(f"Response status: {resp.status_code}") print(f"Response body: {resp.text}") resp.raise_for_status() print("✅ Vehicle creation successful") return resp.json() except requests.exceptions.RequestException as e: print(f"❌ Vehicle creation failed: {e}") if hasattr(e, 'response') and e.response is not None: print(f"Response details: {e.response.text}") return None def test_expense_creation(token, asset_id=None): """Test POST /api/v1/expenses/ with frontend payload.""" url = f"{BASE_URL}/expenses/" headers = {"Authorization": f"Bearer {token}"} # Payload from AddExpense.vue handleSubmit() # Note: frontend does NOT include organization_id, which is required by schema. # We'll try both with and without. payload = { "cost_type": "fuel", "amount_local": 15000, "currency_local": "HUF", "mileage_at_cost": 120000, "date": "2026-03-26T09:00:00Z", "asset_id": asset_id or "00000000-0000-0000-0000-000000000000", # dummy UUID "description": None, "data": {} # organization_id is missing } print("\n--- Testing Expense Creation (without organization_id) ---") print(f"URL: {url}") print(f"Payload: {json.dumps(payload, indent=2)}") try: resp = requests.post(url, json=payload, headers=headers, timeout=10) print(f"Response status: {resp.status_code}") print(f"Response body: {resp.text}") resp.raise_for_status() print("✅ Expense creation successful") return resp.json() except requests.exceptions.RequestException as e: print(f"❌ Expense creation failed: {e}") if hasattr(e, 'response') and e.response is not None: print(f"Response details: {e.response.text}") return None def test_expense_with_org(token, asset_id=None): """Test expense creation with organization_id added (as schema requires).""" url = f"{BASE_URL}/expenses/" headers = {"Authorization": f"Bearer {token}"} payload = { "cost_type": "fuel", "amount_local": 15000, "currency_local": "HUF", "mileage_at_cost": 120000, "date": "2026-03-26T09:00:00Z", "asset_id": asset_id or "00000000-0000-0000-0000-000000000000", "organization_id": 1, # added "description": None, "data": {} } print("\n--- Testing Expense Creation (with organization_id) ---") print(f"URL: {url}") print(f"Payload: {json.dumps(payload, indent=2)}") try: resp = requests.post(url, json=payload, headers=headers, timeout=10) print(f"Response status: {resp.status_code}") print(f"Response body: {resp.text}") resp.raise_for_status() print("✅ Expense creation successful") return resp.json() except requests.exceptions.RequestException as e: print(f"❌ Expense creation failed: {e}") if hasattr(e, 'response') and e.response is not None: print(f"Response details: {e.response.text}") return None def main(): print("🚀 Starting integration verification for tickets #141 and #143") token = get_auth_token() # Test vehicle creation vehicle_result = test_vehicle_creation(token) asset_id = None if vehicle_result and "id" in vehicle_result: asset_id = vehicle_result["id"] print(f"Created asset ID: {asset_id}") else: print("WARNING: No asset ID obtained, using dummy UUID for expense test.") # Test expense creation without organization_id (as frontend does) test_expense_creation(token, asset_id) # Test expense creation with organization_id (should succeed if schema validation passes) test_expense_with_org(token, asset_id) print("\n" + "="*60) print("Verification complete. Check outputs above.") print("If any test failed with 422/500, the integration is broken.") print("="*60) if __name__ == "__main__": main()