Files
yellow-bank-soal/backend/test_all_post_endpoints.py
2026-06-20 01:43:39 +07:00

276 lines
8.8 KiB
Python

#!/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())