Spaces:
Sleeping
Sleeping
| """ | |
| Test script for attendance check-in API. | |
| Generates a JWT token and tests the check-in endpoint. | |
| """ | |
| import requests | |
| import json | |
| from datetime import datetime, timedelta | |
| from jose import jwt | |
| import os | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| # Configuration | |
| BASE_URL = "http://localhost:8003" | |
| SECRET_KEY = os.getenv("SECRET_KEY", "your-secret-key-change-in-production") | |
| ALGORITHM = os.getenv("ALGORITHM", "HS256") | |
| def generate_test_token( | |
| user_id: str = "550e8400-e29b-41d4-a716-446655440000", | |
| username: str = "test.employee@example.com", | |
| merchant_id: str = "660e8400-e29b-41d4-a716-446655440000", | |
| role: str = "employee" | |
| ) -> str: | |
| """Generate a test JWT token""" | |
| payload = { | |
| "sub": user_id, | |
| "username": username, | |
| "merchant_id": merchant_id, | |
| "role": role, | |
| "exp": datetime.utcnow() + timedelta(hours=8) | |
| } | |
| token = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM) | |
| return token | |
| def test_health_check(): | |
| """Test health check endpoint""" | |
| print("\n" + "=" * 80) | |
| print("TEST 1: Health Check") | |
| print("=" * 80) | |
| response = requests.get(f"{BASE_URL}/health") | |
| print(f"Status Code: {response.status_code}") | |
| print(f"Response: {json.dumps(response.json(), indent=2)}") | |
| assert response.status_code == 200 | |
| print("β Health check passed") | |
| def test_attendance_health(): | |
| """Test attendance module health check""" | |
| print("\n" + "=" * 80) | |
| print("TEST 2: Attendance Module Health Check") | |
| print("=" * 80) | |
| response = requests.get(f"{BASE_URL}/tracker/attendance/health") | |
| print(f"Status Code: {response.status_code}") | |
| print(f"Response: {json.dumps(response.json(), indent=2)}") | |
| assert response.status_code == 200 | |
| print("β Attendance health check passed") | |
| def test_checkin_without_auth(): | |
| """Test check-in without authentication (should fail)""" | |
| print("\n" + "=" * 80) | |
| print("TEST 3: Check-in Without Authentication (Should Fail)") | |
| print("=" * 80) | |
| payload = { | |
| "timestamp": int(datetime.now().timestamp() * 1000), | |
| "latitude": 19.0760, | |
| "longitude": 72.8777, | |
| "location_id": "loc_mumbai_office_001" | |
| } | |
| response = requests.post( | |
| f"{BASE_URL}/tracker/attendance/check-in", | |
| json=payload | |
| ) | |
| print(f"Status Code: {response.status_code}") | |
| print(f"Response: {json.dumps(response.json(), indent=2)}") | |
| assert response.status_code == 403 # Forbidden without auth | |
| print("β Correctly rejected unauthenticated request") | |
| def test_checkin_with_auth(): | |
| """Test check-in with authentication""" | |
| print("\n" + "=" * 80) | |
| print("TEST 4: Check-in With Authentication") | |
| print("=" * 80) | |
| # Generate token | |
| token = generate_test_token() | |
| print(f"Generated JWT Token: {token[:50]}...") | |
| # Prepare payload | |
| payload = { | |
| "timestamp": int(datetime.now().timestamp() * 1000), | |
| "latitude": 19.0760, | |
| "longitude": 72.8777, | |
| "location_id": "loc_mumbai_office_001" | |
| } | |
| print(f"\nRequest Payload:") | |
| print(json.dumps(payload, indent=2)) | |
| # Make request | |
| headers = { | |
| "Authorization": f"Bearer {token}", | |
| "Content-Type": "application/json" | |
| } | |
| response = requests.post( | |
| f"{BASE_URL}/tracker/attendance/check-in", | |
| json=payload, | |
| headers=headers | |
| ) | |
| print(f"\nStatus Code: {response.status_code}") | |
| print(f"Response: {json.dumps(response.json(), indent=2)}") | |
| if response.status_code == 201: | |
| print("β Check-in successful") | |
| elif response.status_code == 400: | |
| error_detail = response.json().get("detail", {}) | |
| if "Already checked in" in str(error_detail): | |
| print("β οΈ Already checked in today (expected if running multiple times)") | |
| elif "GPS" in str(error_detail): | |
| print("β οΈ GPS tracking disabled for this employee") | |
| print(" To fix: Update MongoDB scm_employees collection") | |
| print(" Set location_settings.location_tracking_consent = true") | |
| else: | |
| print(f"β Check-in failed: {error_detail}") | |
| else: | |
| print(f"β Unexpected status code: {response.status_code}") | |
| def test_checkin_invalid_coordinates(): | |
| """Test check-in with invalid coordinates""" | |
| print("\n" + "=" * 80) | |
| print("TEST 5: Check-in With Invalid Coordinates (Should Fail)") | |
| print("=" * 80) | |
| token = generate_test_token() | |
| payload = { | |
| "timestamp": int(datetime.now().timestamp() * 1000), | |
| "latitude": 999.0, # Invalid latitude | |
| "longitude": 72.8777 | |
| } | |
| headers = { | |
| "Authorization": f"Bearer {token}", | |
| "Content-Type": "application/json" | |
| } | |
| response = requests.post( | |
| f"{BASE_URL}/tracker/attendance/check-in", | |
| json=payload, | |
| headers=headers | |
| ) | |
| print(f"Status Code: {response.status_code}") | |
| print(f"Response: {json.dumps(response.json(), indent=2)}") | |
| assert response.status_code == 422 # Validation error | |
| print("β Correctly rejected invalid coordinates") | |
| def test_checkin_missing_fields(): | |
| """Test check-in with missing required fields""" | |
| print("\n" + "=" * 80) | |
| print("TEST 6: Check-in With Missing Fields (Should Fail)") | |
| print("=" * 80) | |
| token = generate_test_token() | |
| payload = { | |
| "timestamp": int(datetime.now().timestamp() * 1000), | |
| # Missing latitude and longitude | |
| } | |
| headers = { | |
| "Authorization": f"Bearer {token}", | |
| "Content-Type": "application/json" | |
| } | |
| response = requests.post( | |
| f"{BASE_URL}/tracker/attendance/check-in", | |
| json=payload, | |
| headers=headers | |
| ) | |
| print(f"Status Code: {response.status_code}") | |
| print(f"Response: {json.dumps(response.json(), indent=2)}") | |
| assert response.status_code == 422 # Validation error | |
| print("β Correctly rejected request with missing fields") | |
| def main(): | |
| """Run all tests""" | |
| print("\n" + "=" * 80) | |
| print("ATTENDANCE CHECK-IN API TEST SUITE") | |
| print("=" * 80) | |
| print(f"Base URL: {BASE_URL}") | |
| print(f"Time: {datetime.now().isoformat()}") | |
| print("=" * 80) | |
| try: | |
| test_health_check() | |
| test_attendance_health() | |
| test_checkin_without_auth() | |
| test_checkin_invalid_coordinates() | |
| test_checkin_missing_fields() | |
| test_checkin_with_auth() # Run this last as it may succeed | |
| print("\n" + "=" * 80) | |
| print("β ALL TESTS COMPLETED") | |
| print("=" * 80) | |
| except requests.exceptions.ConnectionError: | |
| print("\nβ ERROR: Could not connect to the server") | |
| print(f" Make sure the service is running at {BASE_URL}") | |
| print(" Run: uvicorn app.main:app --host 0.0.0.0 --port 8003") | |
| except Exception as e: | |
| print(f"\nβ ERROR: {e}") | |
| raise | |
| if __name__ == "__main__": | |
| main() | |