Spaces:
Sleeping
Sleeping
File size: 4,173 Bytes
b84ea83 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | """
Tests for JWT Authentication endpoints.
Tests:
1. POST /auth/register β 501 when pyjwt/passlib not installed
2. POST /auth/login β 501 when pyjwt/passlib not installed
3. POST /auth/login β 422 when missing email/password
4. POST /auth/register β 422 when missing fields
5. POST /auth/register β 422 when password too short
6. GET /auth/me β 401 when no Authorization header
7. Regression: existing endpoints unaffected by auth routes
These tests validate the graceful degradation pattern:
auth deps (pyjwt, passlib) are optional β endpoints return 501
with clear instructions when they're not installed.
"""
import pytest
import httpx
BASE = "http://localhost:5000/api/v1"
@pytest.fixture
def client():
with httpx.Client(base_url=BASE, timeout=10) as c:
yield c
class TestAuthRegister:
"""Tests for POST /auth/register."""
def test_register_returns_501_without_deps(self, client):
"""Should return 501 with clear message about missing auth deps."""
r = client.post("/auth/register", json={
"email": "test@example.com",
"password": "testpassword123", # pragma: allowlist secret
"full_name": "Test User",
})
# If deps ARE installed, this will be 200.
# If deps are NOT installed, this will be 501.
assert r.status_code in (200, 501, 409)
if r.status_code == 501:
body = r.json()
assert body["detail"]["code"] == "AUTH_NOT_CONFIGURED"
assert "pyjwt" in body["detail"]["message"] or "passlib" in body["detail"]["message"]
def test_register_requires_fields(self, client):
"""Should return 422 when required fields are missing."""
r = client.post("/auth/register", json={})
assert r.status_code == 422
body = r.json()
assert body["detail"]["code"] == "VALIDATION_ERROR"
def test_register_password_min_length(self, client):
"""Should return 422 when password is too short."""
r = client.post("/auth/register", json={
"email": "test@example.com",
"password": "short", # pragma: allowlist secret
"full_name": "Test User",
})
assert r.status_code == 422
body = r.json()
assert "8 characters" in body["detail"]["message"]
class TestAuthLogin:
"""Tests for POST /auth/login."""
def test_login_returns_501_without_deps(self, client):
"""Should return 501 with clear message about missing auth deps."""
r = client.post("/auth/login", json={
"email": "test@example.com",
"password": "testpassword123", # pragma: allowlist secret
})
assert r.status_code in (200, 401, 501)
if r.status_code == 501:
body = r.json()
assert body["detail"]["code"] == "AUTH_NOT_CONFIGURED"
def test_login_requires_fields(self, client):
"""Should return 422 when email or password missing."""
r = client.post("/auth/login", json={})
assert r.status_code == 422
body = r.json()
assert body["detail"]["code"] == "VALIDATION_ERROR"
class TestAuthMe:
"""Tests for GET /auth/me."""
def test_me_requires_authorization(self, client):
"""Should return 401 when no auth header provided."""
r = client.get("/auth/me")
assert r.status_code == 401
body = r.json()
assert body["detail"]["code"] == "UNAUTHORIZED"
def test_me_rejects_invalid_token(self, client):
"""Should return 401 with an invalid token."""
r = client.get("/auth/me", headers={
"Authorization": "Bearer invalid.token.here",
})
assert r.status_code in (401, 501)
class TestAuthRegression:
"""Ensure auth routes don't break existing endpoints."""
def test_existing_endpoints_still_work(self, client):
r = client.get("/health")
assert r.status_code == 200
r = client.get("/visits", params={"page": 1, "per_page": 1})
assert r.status_code == 200
r = client.get("/outlets")
assert r.status_code == 200
|