chore: add test infrastructure and update risk router
- Add vitest config and unit tests for components, api, stores - Add Playwright e2e test for user flows - Add backend test files - Update risk.py with LOD grid KDTree optimization
This commit is contained in:
116
backend/tests/test_auth.py
Normal file
116
backend/tests/test_auth.py
Normal file
@@ -0,0 +1,116 @@
|
||||
"""US-003: Authentication and security tests."""
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
class TestLogin:
|
||||
def test_login_success(self, client: TestClient):
|
||||
resp = client.post("/api/auth/login", json={
|
||||
"username": "admin", "password": "admin123"
|
||||
})
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert "access_token" in data
|
||||
assert len(data["access_token"]) > 0
|
||||
|
||||
def test_login_wrong_password(self, client: TestClient):
|
||||
resp = client.post("/api/auth/login", json={
|
||||
"username": "admin", "password": "wrongpassword"
|
||||
})
|
||||
assert resp.status_code == 401
|
||||
assert "Incorrect username or password" in resp.json()["detail"]
|
||||
|
||||
def test_login_nonexistent_user(self, client: TestClient):
|
||||
resp = client.post("/api/auth/login", json={
|
||||
"username": "nonexistent_user_xyz", "password": "password"
|
||||
})
|
||||
assert resp.status_code == 401
|
||||
|
||||
def test_login_empty_username(self, client: TestClient):
|
||||
resp = client.post("/api/auth/login", json={
|
||||
"username": "", "password": "password"
|
||||
})
|
||||
assert resp.status_code in (401, 422)
|
||||
|
||||
|
||||
class TestRegister:
|
||||
def test_register_new_user(self, client: TestClient):
|
||||
resp = client.post("/api/auth/register", json={
|
||||
"username": "testuser_001", "password": "testpass123"
|
||||
})
|
||||
assert resp.status_code == 201
|
||||
assert resp.json()["username"] == "testuser_001"
|
||||
|
||||
def test_register_duplicate(self, client: TestClient):
|
||||
client.post("/api/auth/register", json={
|
||||
"username": "dup_user", "password": "testpass123"
|
||||
})
|
||||
resp = client.post("/api/auth/register", json={
|
||||
"username": "dup_user", "password": "testpass123"
|
||||
})
|
||||
assert resp.status_code == 409
|
||||
assert "already exists" in resp.json()["detail"]
|
||||
|
||||
def test_register_missing_password(self, client: TestClient):
|
||||
resp = client.post("/api/auth/register", json={"username": "user"})
|
||||
assert resp.status_code == 422
|
||||
|
||||
|
||||
class TestTokenAuth:
|
||||
def test_me_with_valid_token(self, client: TestClient, auth_token):
|
||||
resp = client.get(
|
||||
"/api/auth/me",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["username"] == "admin"
|
||||
|
||||
def test_me_without_token(self, client: TestClient):
|
||||
resp = client.get("/api/auth/me")
|
||||
assert resp.status_code in (401, 403)
|
||||
|
||||
def test_me_with_invalid_token(self, client: TestClient):
|
||||
resp = client.get(
|
||||
"/api/auth/me",
|
||||
headers={"Authorization": "Bearer invalid.token.here"}
|
||||
)
|
||||
assert resp.status_code in (401, 403)
|
||||
|
||||
def test_me_with_malformed_header(self, client: TestClient):
|
||||
resp = client.get(
|
||||
"/api/auth/me",
|
||||
headers={"Authorization": "NotBearer token"}
|
||||
)
|
||||
assert resp.status_code in (401, 403)
|
||||
|
||||
def test_me_with_expired_token(self, client: TestClient):
|
||||
"""Token with past expiration should be rejected."""
|
||||
expired = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTcwMDAwMDAwMH0.fake"
|
||||
resp = client.get(
|
||||
"/api/auth/me",
|
||||
headers={"Authorization": f"Bearer {expired}"}
|
||||
)
|
||||
assert resp.status_code in (401, 403)
|
||||
|
||||
def test_login_then_access_protected(self, client: TestClient):
|
||||
login_resp = client.post("/api/auth/login", json={
|
||||
"username": "admin", "password": "admin123"
|
||||
})
|
||||
token = login_resp.json()["access_token"]
|
||||
|
||||
resp = client.get(
|
||||
"/api/auth/me",
|
||||
headers={"Authorization": f"Bearer {token}"}
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["username"] == "admin"
|
||||
|
||||
|
||||
class TestPasswordHashing:
|
||||
def test_bcrypt_not_plaintext(self, client: TestClient):
|
||||
"""Passwords should be hashed, not stored as plaintext."""
|
||||
from auth.service import hash_password, verify_password
|
||||
hashed = hash_password("test_password")
|
||||
assert hashed != "test_password"
|
||||
assert verify_password("test_password", hashed)
|
||||
assert not verify_password("wrong_password", hashed)
|
||||
Reference in New Issue
Block a user