""" 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()