feat: add per-space timezone settings and improve booking management
- Add timezone configuration per space with fallback to system default - Implement timezone-aware datetime display and editing across frontend - Add migration for per_space_settings table - Update booking service to handle timezone conversions properly - Improve .gitignore to exclude build artifacts - Add comprehensive testing documentation Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
119
test_implementation.py
Normal file
119
test_implementation.py
Normal file
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for Spaces.vue and Dashboard.vue implementation
|
||||
"""
|
||||
import requests
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
BASE_URL = "http://localhost:8000"
|
||||
|
||||
def test_api():
|
||||
"""Test all API endpoints used by the implemented pages"""
|
||||
print("=" * 60)
|
||||
print("Testing API Endpoints")
|
||||
print("=" * 60)
|
||||
|
||||
# 1. Login
|
||||
print("\n✓ Testing login...")
|
||||
login_response = requests.post(
|
||||
f"{BASE_URL}/api/auth/login",
|
||||
json={"email": "admin@example.com", "password": "adminpassword"}
|
||||
)
|
||||
assert login_response.status_code == 200, "Login failed"
|
||||
token = login_response.json()["access_token"]
|
||||
print(f" ✓ Login successful, token: {token[:20]}...")
|
||||
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
# 2. Get current user (used by Dashboard)
|
||||
print("\n✓ Testing /api/users/me...")
|
||||
user_response = requests.get(f"{BASE_URL}/api/users/me", headers=headers)
|
||||
assert user_response.status_code == 200
|
||||
user = user_response.json()
|
||||
print(f" ✓ User: {user['email']} (role: {user['role']})")
|
||||
is_admin = user['role'] == 'admin'
|
||||
|
||||
# 3. Get spaces (used by Spaces.vue and Dashboard.vue)
|
||||
print("\n✓ Testing /api/spaces (Spaces.vue)...")
|
||||
spaces_response = requests.get(f"{BASE_URL}/api/spaces", headers=headers)
|
||||
assert spaces_response.status_code == 200
|
||||
spaces = spaces_response.json()
|
||||
print(f" ✓ Found {len(spaces)} spaces")
|
||||
for space in spaces:
|
||||
print(f" - {space['name']} ({space['type']}, capacity: {space['capacity']}, active: {space['is_active']})")
|
||||
|
||||
# 4. Get user bookings (used by Dashboard.vue)
|
||||
print("\n✓ Testing /api/bookings/my (Dashboard.vue)...")
|
||||
bookings_response = requests.get(f"{BASE_URL}/api/bookings/my", headers=headers)
|
||||
assert bookings_response.status_code == 200
|
||||
bookings = bookings_response.json()
|
||||
print(f" ✓ Found {len(bookings)} bookings")
|
||||
|
||||
# Calculate stats
|
||||
stats = {
|
||||
'total': len(bookings),
|
||||
'pending': len([b for b in bookings if b['status'] == 'pending']),
|
||||
'approved': len([b for b in bookings if b['status'] == 'approved']),
|
||||
'rejected': len([b for b in bookings if b['status'] == 'rejected']),
|
||||
}
|
||||
print(f" Stats: {stats}")
|
||||
|
||||
# Show upcoming bookings
|
||||
now = datetime.now()
|
||||
upcoming = [b for b in bookings if datetime.fromisoformat(b['start_datetime'].replace('Z', '+00:00')) > now]
|
||||
upcoming.sort(key=lambda b: b['start_datetime'])
|
||||
print(f" Upcoming: {len(upcoming)} bookings")
|
||||
for booking in upcoming[:5]:
|
||||
print(f" - {booking['title']} at {booking['start_datetime']} (status: {booking['status']})")
|
||||
|
||||
# 5. Admin endpoints (if user is admin)
|
||||
if is_admin:
|
||||
print("\n✓ Testing admin endpoints (Dashboard.vue - admin features)...")
|
||||
|
||||
# Pending requests
|
||||
pending_response = requests.get(
|
||||
f"{BASE_URL}/api/admin/bookings/pending",
|
||||
headers=headers
|
||||
)
|
||||
assert pending_response.status_code == 200
|
||||
pending = pending_response.json()
|
||||
print(f" ✓ Pending requests: {len(pending)}")
|
||||
|
||||
# Audit logs
|
||||
audit_response = requests.get(
|
||||
f"{BASE_URL}/api/admin/audit-log",
|
||||
headers=headers,
|
||||
params={"limit": 5}
|
||||
)
|
||||
assert audit_response.status_code == 200
|
||||
audit_logs = audit_response.json()
|
||||
print(f" ✓ Recent audit logs: {len(audit_logs)}")
|
||||
for log in audit_logs[:3]:
|
||||
print(f" - {log['action']} by {log['user_name']} at {log['created_at']}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("✅ All API tests passed!")
|
||||
print("=" * 60)
|
||||
|
||||
# Summary
|
||||
print("\n📊 Implementation Summary:")
|
||||
print(f" • Spaces page: ✅ Can display {len(spaces)} spaces with filtering")
|
||||
print(f" • Dashboard stats: ✅ Total: {stats['total']}, Pending: {stats['pending']}, Approved: {stats['approved']}")
|
||||
print(f" • Upcoming bookings: ✅ {len(upcoming)} upcoming bookings")
|
||||
print(f" • Available spaces: ✅ {len([s for s in spaces if s['is_active']])} active spaces")
|
||||
if is_admin:
|
||||
print(f" • Admin features: ✅ {len(pending)} pending requests, {len(audit_logs)} recent logs")
|
||||
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
test_api()
|
||||
print("\n✅ Implementation test completed successfully!")
|
||||
except AssertionError as e:
|
||||
print(f"\n❌ Test failed: {e}")
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
print(f"\n❌ Error: {e}")
|
||||
exit(1)
|
||||
Reference in New Issue
Block a user