#!/usr/bin/env python3 """ Comprehensive test of all form POST endpoints with proper authentication. """ import re import sys import httpx BASE_URL = "http://localhost:8000" def login(client: httpx.Client) -> bool: """Login and maintain session.""" response = client.get("/admin/login") if response.status_code != 200: return False match = re.search(r'name="csrf_token" value="([^"]+)"', response.text) csrf_token = match.group(1) if match else "" if not csrf_token: return False response = client.post( "/admin/login", data={ "username": "admin", "password": "admin123", "csrf_token": csrf_token, }, follow_redirects=True, ) return response.status_code == 200 and "/admin/dashboard" in str(response.url) def get_csrf_token(client: httpx.Client, page_url: str) -> str: """Extract CSRF token from a page.""" response = client.get(page_url) if response.status_code == 200: match = re.search(r'name="csrf_token" value="([^"]+)"', response.text) if match: return match.group(1) return "" def test_endpoint(client: httpx.Client, name: str, url: str, data: dict) -> dict: """Test a single POST endpoint.""" csrf_token = get_csrf_token(client, url) # Get the base URL (strip query params) for CSRF token extraction base_url = url.split("?")[0] if "?" in url else url # If we're on a different page, get CSRF token from there if not csrf_token: # Try to get CSRF from dashboard if it's a subpage csrf_token = get_csrf_token(client, "/admin/dashboard") if not csrf_token: return { "name": name, "status_code": None, "has_ise": False, "has_traceback": False, "error": "Could not get CSRF token", "response_preview": "", } # Add CSRF token to data test_data = data.copy() test_data["csrf_token"] = csrf_token response = client.post( url, data=test_data, follow_redirects=True, ) has_ise = response.status_code == 500 or "Internal Server Error" in response.text has_traceback = "Traceback" in response.text if has_traceback: idx = response.text.find("Traceback") traceback_text = response.text[idx : idx + 2000] print(f"\n ⚠️ TRACEBACK on {name}:") print(f" {traceback_text[:500]}...") return { "name": name, "status_code": response.status_code, "has_ise": has_ise, "has_traceback": has_traceback, "error": None, "response_preview": response.text[:500], } def main(): print("=" * 80) print("Testing All Form POST Endpoints for Internal Server Errors") print("=" * 80) results = [] with httpx.Client(base_url=BASE_URL, timeout=60.0) as client: print("\nStep 1: Logging in...") if not login(client): print("❌ Login failed") return 1 print("✅ Login successful") # Test 1: Variant approval (with item ID 4) print("\nStep 2: Testing variant approval...") result = test_endpoint( client, "Variant approval (/admin/questions/4/generate/review-bulk)", "/admin/questions/4/generate?tab=review", {"item_ids": "4", "action": "approved", "tab": "review"}, ) results.append(result) print( f" Status: {result['status_code']} {'✅' if result['status_code'] in [200, 303] else '❌'}" ) # Test 2: Basis item review print("\nStep 3: Testing basis item review...") result = test_endpoint( client, "Basis item review (/admin/basis-items/4/review-bulk)", "/admin/basis-items/4", {"item_ids": "4", "action": "approved"}, ) results.append(result) print( f" Status: {result['status_code']} {'✅' if result['status_code'] in [200, 303] else '❌'}" ) # Test 3: Generate variants for question print("\nStep 4: Testing generate variants...") result = test_endpoint( client, "Generate variants (/admin/questions/4/generate)", "/admin/questions/4/generate?tab=generate", { "target_level": "mudah", "ai_model": "meta-llama/llama-4-maverick:free", "generation_count": "1", "operator_notes": "", "include_note_for_admin": "on", "include_note_in_prompt": "", }, ) results.append(result) print( f" Status: {result['status_code']} {'✅' if result['status_code'] in [200, 303] else '❌'}" ) # Test 5: Website creation print("\nStep 5: Testing website creation...") result = test_endpoint( client, "Website creation (/admin/websites)", "/admin/websites", {"site_name": "Test Site API", "site_url": "https://test-api.example.com"}, ) results.append(result) print( f" Status: {result['status_code']} {'✅' if result['status_code'] in [200, 303] else '❌'}" ) # Test 6: Website deletion (with test ID) print("\nStep 6: Testing website deletion...") # First create a website result_create = test_endpoint( client, "Create test website", "/admin/websites", { "site_name": "Delete Test Site", "site_url": "https://delete-test.example.com", }, ) # Now delete it (using website ID 2 if exists) result = test_endpoint( client, "Website deletion (/admin/websites/2/delete)", "/admin/websites/2/delete", {}, ) results.append(result) print( f" Status: {result['status_code']} {'✅' if result['status_code'] in [200, 303] else '❌'}" ) # Test 7: Tryout import preview (without file - should get validation error not server error) print("\nStep 7: Testing tryout import preview...") result = test_endpoint( client, "Tryout import preview (/admin/tryout-import/preview)", "/admin/tryout-import", {"website_id": "1"}, ) results.append(result) print(f" Status: {result['status_code']} (validation error expected: 422)") # Test 8: Snapshot promote bulk print("\nStep 8: Testing snapshot promote bulk...") result = test_endpoint( client, "Snapshot promote (/admin/snapshot-questions/promote-bulk)", "/admin/snapshot-questions", {"snapshot_id": "1", "snapshot_question_ids": ""}, ) results.append(result) print( f" Status: {result['status_code']} {'✅' if result['status_code'] in [200, 303] else '❌'}" ) # Test 9: AI generation basis item print("\nStep 9: Testing AI generation for basis item...") result = test_endpoint( client, "Basis item generate (/admin/basis-items/4/generate)", "/admin/basis-items/4", { "target_level": "mudah", "ai_model": "", "generation_count": "1", "operator_notes": "", }, ) results.append(result) print( f" Status: {result['status_code']} {'✅' if result['status_code'] in [200, 303] else '❌'}" ) # Summary print("\n" + "=" * 80) print("RESULTS SUMMARY") print("=" * 80) errors = [] for result in results: if result.get("has_traceback"): errors.append(f"❌ {result['name']}: TRACEBACK") print(f"❌ {result['name']}: TRACEBACK") elif result.get("has_ise"): errors.append(f"❌ {result['name']}: INTERNAL SERVER ERROR") print(f"❌ {result['name']}: INTERNAL SERVER ERROR") elif result.get("error"): print(f"⚠️ {result['name']}: {result['error']}") elif result["status_code"] in [200, 303]: print(f"✅ {result['name']}: OK ({result['status_code']})") elif result["status_code"] == 422: print(f"✅ {result['name']}: Validation Error (expected)") else: print(f"⚠️ {result['name']}: Status {result['status_code']}") print() if errors: print("❌ Some endpoints have INTERNAL SERVER ERRORS:") for error in errors: print(f" {error}") return 1 else: print("✅ All form POST endpoints tested successfully!") print(" No Internal Server Errors detected.") return 0 if __name__ == "__main__": sys.exit(main())