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

405 lines
11 KiB
Python

#!/usr/bin/env python3
"""
Test all form POST endpoints for Internal Server Errors.
"""
import json
import sys
import httpx
BASE_URL = "http://localhost:8000"
# All form POST endpoints from admin_web.py
FORM_POST_ENDPOINTS = [
# (endpoint, method, form_data, description)
(
"/admin/login",
"POST",
{"username": "admin", "password": "admin123"},
"Admin login",
),
(
"/admin/password",
"POST",
{
"old_password": "admin123",
"new_password": "admin123",
"re_new_password": "admin123",
},
"Change password",
),
(
"/admin/websites",
"POST",
{
"site_name": "Test Site",
"site_url": "https://test.example.com",
},
"Create website",
),
(
"/admin/websites/1/edit",
"POST",
{
"site_name": "Updated Test Site",
"site_url": "https://updated.example.com",
},
"Edit website",
),
("/admin/websites/1/delete", "POST", {}, "Delete website"),
(
"/admin/tryout-import/preview",
"POST",
{
"website_id": "1",
},
"Tryout import preview (no file)",
),
(
"/admin/tryout-import",
"POST",
{
"website_id": "1",
"preview_token": "invalid-token",
},
"Tryout import submit",
),
(
"/admin/snapshot-questions/promote-bulk",
"POST",
{
"snapshot_id": "1",
"snapshot_question_ids": [],
},
"Promote snapshot questions bulk",
),
(
"/admin/basis-items/1/generate",
"POST",
{
"target_level": "mudah",
"ai_model": "",
"generation_count": "1",
"operator_notes": "",
},
"Generate variants for basis item",
),
(
"/admin/basis-items/1/review-bulk",
"POST",
{
"item_ids": ["1"],
"action": "approved",
},
"Review bulk variants",
),
(
"/admin/questions/1/generate",
"POST",
{
"target_level": "mudah",
"ai_model": "meta-llama/llama-4-maverick:free",
"generation_count": "1",
"operator_notes": "",
"include_note_for_admin": True,
"include_note_in_prompt": False,
},
"Generate question variants",
),
(
"/admin/questions/1/generate/review-bulk",
"POST",
{
"item_ids": ["1"],
"action": "approved",
"tab": "review",
},
"Review question variants bulk",
),
]
# API POST endpoints
API_POST_ENDPOINTS = [
(
"/api/v1/session/",
{
"session_id": "test-session-123",
"tryout_id": "test",
"wp_user_id": "123",
"website_id": 1,
"scoring_mode": "ctt",
},
"Create session",
),
(
"/api/v1/session/test-session-123/complete",
{
"end_time": "2024-01-01T00:00:00Z",
"user_answers": [],
},
"Complete session",
),
(
"/api/v1/session/test-session-123/submit_answer",
{
"item_id": 1,
"response": "A",
"time_spent": 10,
},
"Submit answer",
),
(
"/api/v1/wordpress/verify_session",
{
"website_id": 1,
"wp_user_id": "123",
"token": "test",
},
"Verify WordPress session",
),
(
"/api/v1/reports/schedule",
{
"tryout_id": "test",
"report_type": "student_performance",
},
"Schedule report",
),
(
"/api/v1/admin/cat/test",
{
"tryout_id": "test",
"website_id": 1,
},
"Test CAT algorithm",
),
("/api/v1/admin/1/calibrate", {}, "Calibrate tryout"),
("/api/v1/admin/1/toggle-ai-generation", {}, "Toggle AI generation"),
("/api/v1/admin/1/reset-normalization", {}, "Reset normalization"),
]
def get_admin_session():
"""Login and get session cookies for admin access."""
with httpx.Client(base_url=BASE_URL, follow_redirects=True, timeout=30.0) as client:
# Try to login
response = client.post(
"/admin/login",
data={
"username": "admin",
"password": "admin123",
},
)
print(f"Login response: {response.status_code}")
# Check if we have admin access
response = client.get("/admin")
print(f"Admin page response: {response.status_code}")
# Return cookies
return client.cookies
def test_endpoint(
client: httpx.Client, endpoint: str, method: str, data: dict, cookies: dict = None
) -> dict:
"""Test a single endpoint."""
headers = {"X-Website-ID": "1"}
try:
if method == "POST":
# Check if this looks like form data or JSON
if isinstance(data, dict) and all(
isinstance(v, str) or v is None for v in data.values()
):
# Form data
response = client.post(
endpoint,
data=data,
headers=headers,
cookies=cookies,
timeout=30.0,
follow_redirects=True,
)
else:
# JSON data
response = client.post(
endpoint,
json=data,
headers=headers,
cookies=cookies,
timeout=30.0,
follow_redirects=True,
)
else:
response = client.request(
method,
endpoint,
headers=headers,
cookies=cookies,
timeout=30.0,
follow_redirects=True,
)
# Check for internal server error
has_ise = (
response.status_code == 500
or "Internal Server Error" in response.text
or "500 Internal Server Error" in response.text
)
# Check for traceback
has_traceback = "Traceback" in response.text
return {
"endpoint": endpoint,
"method": method,
"status_code": response.status_code,
"has_ise": has_ise,
"has_traceback": has_traceback,
"response_preview": response.text[:500] if response.text else "",
"redirect_location": response.headers.get("location", ""),
}
except httpx.TimeoutException:
return {
"endpoint": endpoint,
"method": method,
"status_code": None,
"has_ise": False,
"has_traceback": False,
"response_preview": "",
"error": "Timeout",
}
except Exception as e:
return {
"endpoint": endpoint,
"method": method,
"status_code": None,
"has_ise": False,
"has_traceback": False,
"response_preview": "",
"error": str(e),
}
def main():
print("=" * 80)
print("Testing all Form POST endpoints for Internal Server Errors")
print("=" * 80)
print()
# Get admin session
print("Getting admin session...")
cookies = get_admin_session()
print()
results = []
has_errors = False
with httpx.Client(base_url=BASE_URL, follow_redirects=True, timeout=30.0) as client:
# Test admin form POST endpoints
print("-" * 80)
print("ADMIN FORM POST ENDPOINTS")
print("-" * 80)
for endpoint, method, data, description in FORM_POST_ENDPOINTS:
print(f"\nTesting: {description}")
print(f" Endpoint: {endpoint}")
result = test_endpoint(client, endpoint, method, data, cookies)
results.append((description, result))
status = result["status_code"]
error_details = ""
if result.get("error"):
error_details = f" [ERROR: {result['error']}]"
has_errors = True
elif result.get("has_traceback"):
error_details = f" [TRACEBACK!]"
has_errors = True
print(f" Response: {result['response_preview'][:1000]}")
elif result.get("has_ise"):
error_details = f" [INTERNAL SERVER ERROR!]"
has_errors = True
print(f" Response: {result['response_preview'][:1000]}")
status_str = str(status) if status else "N/A"
print(f" Status: {status_str}{error_details}")
if result.get("redirect_location"):
print(f" Redirect: {result['redirect_location']}")
# Test API POST endpoints
print()
print("-" * 80)
print("API POST ENDPOINTS")
print("-" * 80)
for endpoint, data, description in API_POST_ENDPOINTS:
print(f"\nTesting: {description}")
print(f" Endpoint: {endpoint}")
result = test_endpoint(client, endpoint, "POST", data, cookies)
results.append((description, result))
status = result["status_code"]
error_details = ""
if result.get("error"):
error_details = f" [ERROR: {result['error']}]"
has_errors = True
elif result.get("has_traceback"):
error_details = f" [TRACEBACK!]"
has_errors = True
print(f" Response: {result['response_preview'][:1000]}")
elif result.get("has_ise"):
error_details = f" [INTERNAL SERVER ERROR!]"
has_errors = True
print(f" Response: {result['response_preview'][:1000]}")
status_str = str(status) if status else "N/A"
print(f" Status: {status_str}{error_details}")
# Summary
print()
print("=" * 80)
print("SUMMARY")
print("=" * 80)
total = len(results)
ise_errors = sum(1 for _, r in results if r.get("has_ise"))
tracebacks = sum(1 for _, r in results if r.get("has_traceback"))
timeouts = sum(1 for _, r in results if r.get("error") == "Timeout")
exceptions = sum(
1 for _, r in results if r.get("error") and r.get("error") != "Timeout"
)
print(f"Total endpoints tested: {total}")
print(f"Internal Server Errors: {ise_errors}")
print(f"Tracebacks: {tracebacks}")
print(f"Timeouts: {timeouts}")
print(f"Exceptions: {exceptions}")
print()
if ise_errors > 0 or tracebacks > 0:
print("Endpoints with issues:")
for desc, r in results:
if r.get("has_ise") or r.get("has_traceback"):
print(f" - {desc}: {r['endpoint']} -> {r['status_code']}")
if r.get("has_traceback"):
print(f" Traceback detected in response")
print()
if has_errors:
print("❌ Some endpoints have issues. Please review the output above.")
return 1
else:
print("✅ All endpoints passed! No Internal Server Errors detected.")
return 0
if __name__ == "__main__":
sys.exit(main())