fix(auth): use actual hostname instead of localhost in frontend API client
- Modified frontend/lib/api.ts to use window.location.hostname as fallback - Ensures browser on external IP reaches correct backend HTTPS port - Allows admin/admin login to work from any access point - Auth is fully functional and working
This commit is contained in:
199
tests/phase6_with_auth.py
Normal file
199
tests/phase6_with_auth.py
Normal file
@@ -0,0 +1,199 @@
|
||||
"""
|
||||
Phase 6 Regression Tests WITH AUTHENTICATION
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
BASE_URL = "http://localhost:8916"
|
||||
FRONTEND_URL = "http://localhost:8917"
|
||||
|
||||
results = {"passed": [], "failed": [], "errors": [], "timestamp": datetime.now().isoformat()}
|
||||
auth_token = None
|
||||
|
||||
def log_result(test_name, passed, details=""):
|
||||
result = {"name": test_name, "details": details, "timestamp": datetime.now().isoformat()}
|
||||
if passed:
|
||||
results["passed"].append(result)
|
||||
print(f"✅ PASS: {test_name}")
|
||||
else:
|
||||
results["failed"].append(result)
|
||||
print(f"❌ FAIL: {test_name}")
|
||||
if details:
|
||||
print(f" {details}")
|
||||
return passed
|
||||
|
||||
# ============================================================================
|
||||
# AUTHENTICATION
|
||||
# ============================================================================
|
||||
def test_login():
|
||||
print("\n--- STEP 0: AUTHENTICATE ---")
|
||||
global auth_token
|
||||
|
||||
# Try default admin login (LDAP disabled or fallback)
|
||||
try:
|
||||
payload = {"username": "admin", "password": "admin"}
|
||||
response = requests.post(f"{BASE_URL}/users/login", json=payload)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
auth_token = data.get("access_token")
|
||||
log_result("Login", True, f"Got auth token: {auth_token[:20]}...")
|
||||
return auth_token
|
||||
else:
|
||||
log_result("Login", False, f"Status {response.status_code}: {response.text[:100]}")
|
||||
# Try without auth (check if endpoints allow public access)
|
||||
log_result("Login", False, "Will try endpoints without auth")
|
||||
return None
|
||||
except Exception as e:
|
||||
log_result("Login", False, str(e))
|
||||
return None
|
||||
|
||||
def get_headers():
|
||||
"""Get request headers with auth if available"""
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if auth_token:
|
||||
headers["Authorization"] = f"Bearer {auth_token}"
|
||||
return headers
|
||||
|
||||
# ============================================================================
|
||||
# TESTS WITH AUTH
|
||||
# ============================================================================
|
||||
def test_create_item():
|
||||
print("\n--- TEST 1: CREATE ITEM ---")
|
||||
try:
|
||||
payload = {
|
||||
"barcode": "TEST-002",
|
||||
"name": "Test Item with Auth",
|
||||
"category": "Electronics",
|
||||
"quantity": 5,
|
||||
"min_quantity": 1
|
||||
}
|
||||
response = requests.post(f"{BASE_URL}/items/", json=payload, headers=get_headers())
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
item_id = data.get("id")
|
||||
log_result("Create Item", True, f"Created item ID {item_id}")
|
||||
return item_id
|
||||
else:
|
||||
log_result("Create Item", False, f"Status {response.status_code}: {response.text[:100]}")
|
||||
return None
|
||||
except Exception as e:
|
||||
log_result("Create Item", False, str(e))
|
||||
return None
|
||||
|
||||
def test_read_items():
|
||||
print("\n--- TEST 2: READ ITEMS ---")
|
||||
try:
|
||||
response = requests.get(f"{BASE_URL}/items/", headers=get_headers())
|
||||
|
||||
if response.status_code == 200:
|
||||
items = response.json()
|
||||
log_result("Read Items", True, f"Found {len(items)} items")
|
||||
return items
|
||||
else:
|
||||
log_result("Read Items", False, f"Status {response.status_code}")
|
||||
return []
|
||||
except Exception as e:
|
||||
log_result("Read Items", False, str(e))
|
||||
return []
|
||||
|
||||
def test_delete_item(item_id):
|
||||
print("\n--- TEST 3: DELETE ITEM ---")
|
||||
if not item_id:
|
||||
log_result("Delete Item", False, "No item ID")
|
||||
return False
|
||||
try:
|
||||
response = requests.delete(f"{BASE_URL}/items/{item_id}", headers=get_headers())
|
||||
if response.status_code == 200:
|
||||
log_result("Delete Item", True, f"Deleted item ID {item_id}")
|
||||
return True
|
||||
else:
|
||||
log_result("Delete Item", False, f"Status {response.status_code}")
|
||||
return False
|
||||
except Exception as e:
|
||||
log_result("Delete Item", False, str(e))
|
||||
return False
|
||||
|
||||
def test_search_items():
|
||||
print("\n--- TEST 4: SEARCH ITEMS ---")
|
||||
try:
|
||||
response = requests.get(f"{BASE_URL}/items/search", params={"q": "test"}, headers=get_headers())
|
||||
if response.status_code == 200:
|
||||
results_list = response.json()
|
||||
log_result("Search Items", True, f"Search returned {len(results_list)} results")
|
||||
return True
|
||||
else:
|
||||
log_result("Search Items", False, f"Status {response.status_code}")
|
||||
return False
|
||||
except Exception as e:
|
||||
log_result("Search Items", False, str(e))
|
||||
return False
|
||||
|
||||
def test_admin_stats():
|
||||
print("\n--- TEST 5: ADMIN STATS ---")
|
||||
try:
|
||||
response = requests.get(f"{BASE_URL}/admin/db/stats", headers=get_headers())
|
||||
if response.status_code == 200:
|
||||
log_result("Admin Stats", True, "Stats loaded")
|
||||
return True
|
||||
else:
|
||||
log_result("Admin Stats", False, f"Status {response.status_code}")
|
||||
return False
|
||||
except Exception as e:
|
||||
log_result("Admin Stats", False, str(e))
|
||||
return False
|
||||
|
||||
def test_export_snapshot():
|
||||
print("\n--- TEST 6: EXPORT SNAPSHOT ---")
|
||||
try:
|
||||
response = requests.get(f"{BASE_URL}/admin/db/export", headers=get_headers())
|
||||
if response.status_code == 200:
|
||||
log_result("Export Snapshot", True, f"Exported {len(response.content)} bytes")
|
||||
return True
|
||||
else:
|
||||
log_result("Export Snapshot", False, f"Status {response.status_code}")
|
||||
return False
|
||||
except Exception as e:
|
||||
log_result("Export Snapshot", False, str(e))
|
||||
return False
|
||||
|
||||
# ============================================================================
|
||||
# MAIN
|
||||
# ============================================================================
|
||||
if __name__ == "__main__":
|
||||
print("=" * 70)
|
||||
print(" PHASE 6 REGRESSION TEST SUITE - WITH AUTHENTICATION")
|
||||
print("=" * 70)
|
||||
|
||||
auth_token = test_login()
|
||||
|
||||
if not auth_token:
|
||||
print("\n⚠️ NO AUTH TOKEN - Trying endpoints anyway (may all fail with 401)")
|
||||
|
||||
print("\n[Core CRUD Operations]")
|
||||
item_id = test_create_item()
|
||||
items = test_read_items()
|
||||
if item_id:
|
||||
test_delete_item(item_id)
|
||||
|
||||
print("\n[Feature Tests]")
|
||||
test_search_items()
|
||||
test_admin_stats()
|
||||
test_export_snapshot()
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
passed = len(results['passed'])
|
||||
failed = len(results['failed'])
|
||||
total = passed + failed
|
||||
print(f"Results: {passed}/{total} passed")
|
||||
print(f"✅ {passed} | ❌ {failed}")
|
||||
print("=" * 70)
|
||||
|
||||
with open("tests/PHASE6_TEST_RESULTS_WITH_AUTH.json", "w") as f:
|
||||
json.dump(results, f, indent=2)
|
||||
|
||||
print(f"Details: tests/PHASE6_TEST_RESULTS_WITH_AUTH.json")
|
||||
Reference in New Issue
Block a user