cuatrolabs-tracker-ms / test_checkin.py
Michael-Antony's picture
refactor: Change API context path from /api/v1 to /tracker
3d54c92
"""
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()