Files
tfm_ainventory/tests/phase6_regression_tests.py
Daniel Bedeleanu cbdb2f04f6 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
2026-04-23 10:39:18 +03:00

305 lines
9.6 KiB
Python

"""
Phase 6 Regression Tests - Automated API Tests
Tests all broken features without manual UI interaction
"""
import requests
import json
import sys
from datetime import datetime
BASE_URL = "http://localhost:8916"
FRONTEND_URL = "http://localhost:8917"
# Test results tracker
results = {
"passed": [],
"failed": [],
"errors": [],
"timestamp": datetime.now().isoformat()
}
def log_result(test_name, passed, details=""):
"""Log test result"""
result = {
"name": test_name,
"details": details,
"timestamp": datetime.now().isoformat()
}
if passed:
results["passed"].append(result)
print(f"✅ PASS: {test_name}")
if details:
print(f" {details}")
else:
results["failed"].append(result)
print(f"❌ FAIL: {test_name}")
if details:
print(f" {details}")
return passed
def log_error(test_name, error):
"""Log exception"""
results["errors"].append({
"name": test_name,
"error": str(error),
"timestamp": datetime.now().isoformat()
})
print(f"⚠️ ERROR: {test_name}")
print(f" {str(error)}")
return False
# ============================================================================
# TEST 1: CREATE ITEM (Foundation - blocks all other tests)
# ============================================================================
def test_create_item():
"""Test creating a new item via API"""
print("\n--- TEST 1: CREATE ITEM ---")
try:
payload = {
"barcode": "TEST-001",
"name": "Test Item",
"category": "Electronics",
"quantity": 5,
"min_quantity": 1
}
response = requests.post(
f"{BASE_URL}/items/",
json=payload,
headers={"Content-Type": "application/json"}
)
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}")
return None
except Exception as e:
log_error("Create Item", e)
return None
# ============================================================================
# TEST 2: READ ITEMS (Verify DB)
# ============================================================================
def test_read_items():
"""Test fetching items from API"""
print("\n--- TEST 2: READ ITEMS ---")
try:
response = requests.get(f"{BASE_URL}/items/")
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_error("Read Items", e)
return []
# ============================================================================
# TEST 3: DELETE ITEM (Test cascade)
# ============================================================================
def test_delete_item(item_id):
"""Test deleting an item"""
print("\n--- TEST 3: DELETE ITEM ---")
if not item_id:
log_result("Delete Item", False, "No item ID provided (create test failed)")
return False
try:
response = requests.delete(f"{BASE_URL}/items/{item_id}")
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}: {response.text}")
return False
except Exception as e:
log_error("Delete Item", e)
return False
# ============================================================================
# TEST 4: SEARCH API (Test backend search)
# ============================================================================
def test_search_items():
"""Test searching items via API"""
print("\n--- TEST 4: SEARCH ITEMS ---")
try:
response = requests.get(
f"{BASE_URL}/items/search",
params={"q": "test"}
)
if response.status_code == 200:
results_list = response.json()
log_result("Search Items", True, f"Search returned {len(results_list)} results")
return True
elif response.status_code == 404:
log_result("Search Items", False, "Endpoint /api/items/search not found")
return False
else:
log_result("Search Items", False, f"Status {response.status_code}")
return False
except Exception as e:
log_error("Search Items", e)
return False
# ============================================================================
# TEST 5: ADMIN API (Test admin data)
# ============================================================================
def test_admin_stats():
"""Test admin stats endpoint"""
print("\n--- TEST 5: ADMIN STATS ---")
try:
response = requests.get(f"{BASE_URL}/admin/db/stats")
if response.status_code == 200:
stats = response.json()
log_result("Admin Stats", True, f"Stats: {stats}")
return True
elif response.status_code == 404:
log_result("Admin Stats", False, "Endpoint /api/admin/stats not found")
return False
else:
log_result("Admin Stats", False, f"Status {response.status_code}: {response.text}")
return False
except Exception as e:
log_error("Admin Stats", e)
return False
# ============================================================================
# TEST 6: EXPORT ENDPOINT (Test Excel export)
# ============================================================================
def test_export_snapshot():
"""Test export snapshot endpoint"""
print("\n--- TEST 6: EXPORT SNAPSHOT ---")
try:
response = requests.get(f"{BASE_URL}/admin/db/export")
if response.status_code == 200:
# Check if response is binary (Excel file)
if response.headers.get("content-type", "").startswith("application/vnd"):
log_result("Export Snapshot", True, f"Exported {len(response.content)} bytes")
return True
else:
log_result("Export Snapshot", False, "Response not Excel file")
return False
elif response.status_code == 404:
log_result("Export Snapshot", False, "Endpoint not found")
return False
else:
log_result("Export Snapshot", False, f"Status {response.status_code}")
return False
except Exception as e:
log_error("Export Snapshot", e)
return False
# ============================================================================
# TEST 7: BACKEND HEALTH
# ============================================================================
def test_backend_health():
"""Test backend health endpoint"""
print("\n--- TEST 7: BACKEND HEALTH ---")
try:
response = requests.get(f"{BASE_URL}/health")
if response.status_code == 200:
log_result("Backend Health", True, "Backend responding")
return True
else:
log_result("Backend Health", False, f"Status {response.status_code}")
return False
except Exception as e:
log_error("Backend Health", e)
return False
# ============================================================================
# TEST 8: FRONTEND LOADS
# ============================================================================
def test_frontend_loads():
"""Test frontend HTML loads"""
print("\n--- TEST 8: FRONTEND LOADS ---")
try:
response = requests.get(FRONTEND_URL)
if response.status_code == 200 and "Inventory" in response.text:
log_result("Frontend Loads", True, "Frontend HTML responding")
return True
else:
log_result("Frontend Loads", False, f"Status {response.status_code}")
return False
except Exception as e:
log_error("Frontend Loads", e)
return False
# ============================================================================
# MAIN TEST EXECUTION
# ============================================================================
if __name__ == "__main__":
print("=" * 70)
print(" PHASE 6 REGRESSION TEST SUITE - Automated API Tests")
print("=" * 70)
print(f"Backend: {BASE_URL}")
print(f"Frontend: {FRONTEND_URL}")
print(f"Time: {datetime.now().isoformat()}")
print("=" * 70)
# Run tests in order
print("\n[PHASE A: Infrastructure Tests]")
test_backend_health()
test_frontend_loads()
print("\n[PHASE B: Core CRUD Operations]")
item_id = test_create_item()
items = test_read_items()
if item_id:
test_delete_item(item_id)
print("\n[PHASE C: Feature Tests]")
test_search_items()
test_admin_stats()
test_export_snapshot()
# Summary
print("\n" + "=" * 70)
print(" TEST SUMMARY")
print("=" * 70)
print(f"✅ Passed: {len(results['passed'])}")
print(f"❌ Failed: {len(results['failed'])}")
print(f"⚠️ Errors: {len(results['errors'])}")
print("=" * 70)
# Write results to file
with open("tests/PHASE6_TEST_RESULTS.json", "w") as f:
json.dump(results, f, indent=2)
print(f"\nResults saved to: tests/PHASE6_TEST_RESULTS.json")
# Exit with appropriate code
sys.exit(0 if len(results["failed"]) == 0 and len(results["errors"]) == 0 else 1)