Files
service-finder/backend/app/tests/test_issues_176_177_internal.py
2026-03-30 06:32:22 +00:00

266 lines
9.7 KiB
Python

#!/usr/bin/env python3
"""
Internal test script for Issues #176 and #177
This script runs inside the sf_api container using only Python standard library.
"""
import urllib.request
import urllib.error
import urllib.parse
import json
import sys
# Configuration - internal Docker network
BASE_URL = "http://sf_api:8000/api/v1"
# Using a test user that should exist in the dev database
TEST_EMAIL = "tester_pro@profibot.hu"
TEST_PASSWORD = "Password123!"
def make_request(method, url, data=None, headers=None, is_form_data=False):
"""Make HTTP request using urllib"""
if headers is None:
headers = {}
req = urllib.request.Request(url, method=method)
for key, value in headers.items():
req.add_header(key, value)
if data is not None:
if is_form_data:
# For form data (application/x-www-form-urlencoded)
data_bytes = urllib.parse.urlencode(data).encode('utf-8')
req.add_header('Content-Type', 'application/x-www-form-urlencoded')
else:
# For JSON data
req.add_header('Content-Type', 'application/json')
data_bytes = json.dumps(data).encode('utf-8')
req.data = data_bytes
try:
with urllib.request.urlopen(req) as response:
response_data = response.read().decode('utf-8')
return response.status, response_data
except urllib.error.HTTPError as e:
return e.code, e.read().decode('utf-8')
except Exception as e:
return 0, str(e)
def login():
"""Login and get JWT token"""
print("🔐 Logging in...")
login_data = {
"username": TEST_EMAIL,
"password": TEST_PASSWORD
}
# Login endpoint expects form data, not JSON
status, response = make_request("POST", f"{BASE_URL}/auth/login", data=login_data, is_form_data=True)
if status == 200:
data = json.loads(response)
token = data.get("access_token")
if token:
print(f"✅ Login successful")
return token
else:
print(f"❌ No access_token in response")
print(f"Response: {response}")
return None
else:
print(f"❌ Login failed with status {status}")
print(f"Response: {response}")
return None
def test_issue_176_organization_switch(token):
"""Test Issue #176: PATCH /api/v1/users/me/active-organization endpoint"""
print("\n" + "="*60)
print("🧪 Testing Issue #176: Organization Switch (500 Error Fix)")
print("="*60)
headers = {"Authorization": f"Bearer {token}"}
# Step 1: Get current user info
print("\n1. Getting current user info...")
status, response = make_request("GET", f"{BASE_URL}/users/me", headers=headers)
if status == 200:
user_data = json.loads(response)
current_scope_id = user_data.get("scope_id")
print(f" Current scope_id: {current_scope_id}")
else:
print(f"❌ Failed to get user info: {status}")
print(f" Response: {response}")
return False
# Step 2: Try to switch to null (personal mode)
print("\n2. Testing switch to null (personal mode)...")
switch_data = {"organization_id": None}
status, response = make_request("PATCH", f"{BASE_URL}/users/me/active-organization",
data=switch_data, headers=headers)
if status == 200:
print(f"✅ Switch to null successful (200 OK)")
result = json.loads(response)
print(f" New scope_id: {result.get('scope_id')}")
else:
print(f"❌ Switch to null failed with status {status}")
print(f" Response: {response}")
return False
# Step 3: Get organizations to test switching
print("\n3. Checking user's organizations...")
status, response = make_request("GET", f"{BASE_URL}/organizations/my", headers=headers)
if status == 200:
orgs = json.loads(response)
if orgs and len(orgs) > 0:
org_id = orgs[0].get("id")
print(f" Found organization with ID: {org_id}")
# Try to switch to this organization
switch_data = {"organization_id": org_id}
status, response = make_request("PATCH", f"{BASE_URL}/users/me/active-organization",
data=switch_data, headers=headers)
if status == 200:
print(f"✅ Switch to organization successful (200 OK)")
result = json.loads(response)
print(f" New scope_id: {result.get('scope_id')}")
elif status == 403:
print(f"⚠️ Switch to organization failed with 403 (not a member)")
print(f" This is expected if user is not a member of this org")
else:
print(f"❌ Switch to organization failed with status {status}")
print(f" Response: {response}")
# Don't fail the test if we can't switch to org (might not be a member)
else:
print(" No organizations found for user, skipping organization switch test")
else:
print(f" Could not fetch organizations: {status}")
# Step 4: Verify final state
print("\n4. Verifying final user state...")
status, response = make_request("GET", f"{BASE_URL}/users/me", headers=headers)
if status == 200:
user_data = json.loads(response)
final_scope_id = user_data.get("scope_id")
print(f" Final scope_id: {final_scope_id}")
print(f"✅ Issue #176 test completed successfully!")
return True
else:
print(f"❌ Failed to verify user info: {status}")
return False
def test_issue_177_garage_dynamic_data(token):
"""Test Issue #177: GET /api/v1/assets/vehicles with dynamic data fields"""
print("\n" + "="*60)
print("🧪 Testing Issue #177: Garage Dynamic Data")
print("="*60)
headers = {"Authorization": f"Bearer {token}"}
# Get user's vehicles
print("\n1. Fetching user's vehicles...")
status, response = make_request("GET", f"{BASE_URL}/assets/vehicles", headers=headers)
if status == 200:
vehicles = json.loads(response)
print(f" Found {len(vehicles)} vehicles")
if len(vehicles) == 0:
print(" No vehicles found, but endpoint works correctly")
print(" ✅ GET /api/v1/assets/vehicles endpoint is working (200 OK)")
return True
# Check first vehicle
first_vehicle = vehicles[0]
print(f"\n2. Checking first vehicle:")
print(f" Vehicle ID: {first_vehicle.get('id')}")
print(f" License plate: {first_vehicle.get('license_plate')}")
# Check for profile_completion_percentage field
profile_completion = first_vehicle.get("profile_completion_percentage")
if profile_completion is not None:
print(f" ✅ profile_completion_percentage field found: {profile_completion}%")
else:
print(f" ❌ profile_completion_percentage field MISSING!")
return False
# Check all fields
print(f"\n3. Available fields in vehicle response:")
for key in first_vehicle.keys():
print(f" - {key}")
# Check for data_status field
if "data_status" in first_vehicle:
print(f" ✅ data_status field found: {first_vehicle['data_status']}")
else:
print(f" ⚠️ data_status field not in response")
# Check if it might be in a nested structure
for key, value in first_vehicle.items():
if isinstance(value, dict) and "data_status" in value:
print(f" ✅ data_status found in nested {key}: {value['data_status']}")
break
# Check required fields
required_fields = ["id", "status", "is_verified", "created_at"]
missing_fields = []
for field in required_fields:
if field not in first_vehicle:
missing_fields.append(field)
if missing_fields:
print(f" ❌ Missing required fields: {missing_fields}")
return False
else:
print(f" ✅ All required fields present")
print(f"\n✅ Issue #177 test completed successfully!")
return True
else:
print(f"❌ Failed to get vehicles: {status}")
print(f" Response: {response}")
return False
def main():
"""Main test function"""
print("🚀 Starting Internal QA Tests for Issues #176 and #177")
print("="*60)
# Login
token = login()
if not token:
print("❌ Cannot proceed without authentication token")
return False
# Test Issue #176
issue_176_passed = test_issue_176_organization_switch(token)
# Test Issue #177
issue_177_passed = test_issue_177_garage_dynamic_data(token)
# Summary
print("\n" + "="*60)
print("📊 TEST SUMMARY")
print("="*60)
print(f"Issue #176 (Organization Switch): {'✅ PASSED' if issue_176_passed else '❌ FAILED'}")
print(f"Issue #177 (Garage Dynamic Data): {'✅ PASSED' if issue_177_passed else '❌ FAILED'}")
overall_passed = issue_176_passed and issue_177_passed
print(f"\nOverall Result: {'✅ ALL TESTS PASSED' if overall_passed else '❌ SOME TESTS FAILED'}")
return overall_passed
if __name__ == "__main__":
try:
success = main()
sys.exit(0 if success else 1)
except KeyboardInterrupt:
print("\n\n⚠️ Test interrupted by user")
sys.exit(1)
except Exception as e:
print(f"\n❌ Unexpected error: {e}")
import traceback
traceback.print_exc()
sys.exit(1)