276 lines
8.8 KiB
Python
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())
|