190 lines
6.3 KiB
Python
190 lines
6.3 KiB
Python
import unittest
|
|
|
|
from fastapi import HTTPException
|
|
from fastapi.testclient import TestClient
|
|
|
|
from app.api.auth import get_auth_service
|
|
from app.main import app
|
|
|
|
|
|
class StubAuthService:
|
|
def login(self, account, password):
|
|
return {
|
|
"access_token": "token-demo",
|
|
"token_type": "Bearer",
|
|
"expires_in": 7200,
|
|
"user": {
|
|
"id": "user-demo-001",
|
|
"tenant_id": "tenant-demo-001",
|
|
"username": "admin@example.com",
|
|
"display_name": "管理员",
|
|
"role": "admin",
|
|
"status": "active",
|
|
},
|
|
}
|
|
|
|
def register(self, username, password, display_name):
|
|
return {
|
|
"id": "user-member-001",
|
|
"tenant_id": "tenant-demo-001",
|
|
"username": username,
|
|
"display_name": display_name,
|
|
"role": "member",
|
|
"status": "active",
|
|
}
|
|
|
|
def get_current_user(self, authorization):
|
|
if authorization != "Bearer token-demo":
|
|
raise HTTPException(status_code=401, detail="missing bearer token")
|
|
return {
|
|
"id": "user-demo-001",
|
|
"tenant_id": "tenant-demo-001",
|
|
"username": "admin@example.com",
|
|
"display_name": "管理员",
|
|
"role": "admin",
|
|
"status": "active",
|
|
}
|
|
|
|
def update_current_user(self, authorization, display_name, password):
|
|
if authorization != "Bearer token-demo":
|
|
raise HTTPException(status_code=401, detail="missing bearer token")
|
|
if not display_name.strip():
|
|
raise HTTPException(status_code=400, detail="display name is required")
|
|
if password is not None and password.strip() and len(password.strip()) < 6:
|
|
raise HTTPException(status_code=400, detail="password must be at least 6 characters")
|
|
return {
|
|
"id": "user-demo-001",
|
|
"tenant_id": "tenant-demo-001",
|
|
"username": "admin@example.com",
|
|
"display_name": display_name.strip(),
|
|
"role": "admin",
|
|
"status": "active",
|
|
}
|
|
|
|
def seed_default_admin(self):
|
|
return {
|
|
"username": "admin@example.com",
|
|
"password": None,
|
|
"created": False,
|
|
}
|
|
|
|
|
|
class AuthApiTestCase(unittest.TestCase):
|
|
def setUp(self):
|
|
app.dependency_overrides[get_auth_service] = lambda: StubAuthService()
|
|
self.client = TestClient(app)
|
|
|
|
def tearDown(self):
|
|
app.dependency_overrides.clear()
|
|
|
|
def test_register_returns_created_member(self):
|
|
response = self.client.post(
|
|
"/api/v1/auth/register",
|
|
json={
|
|
"username": "member@example.com",
|
|
"password": "123456",
|
|
"display_name": "测试成员",
|
|
},
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
payload = response.json()["data"]
|
|
self.assertEqual(payload["username"], "member@example.com")
|
|
self.assertEqual(payload["display_name"], "测试成员")
|
|
self.assertEqual(payload["role"], "member")
|
|
|
|
def test_register_rejects_invalid_email(self):
|
|
response = self.client.post(
|
|
"/api/v1/auth/register",
|
|
json={
|
|
"username": "not-an-email",
|
|
"password": "123456",
|
|
"display_name": "测试成员",
|
|
},
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
def test_register_rejects_short_password(self):
|
|
response = self.client.post(
|
|
"/api/v1/auth/register",
|
|
json={
|
|
"username": "member@example.com",
|
|
"password": "12345",
|
|
"display_name": "测试成员",
|
|
},
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
def test_register_then_login_uses_same_credentials(self):
|
|
register_response = self.client.post(
|
|
"/api/v1/auth/register",
|
|
json={
|
|
"username": "member@example.com",
|
|
"password": "123456",
|
|
"display_name": "测试成员",
|
|
},
|
|
)
|
|
self.assertEqual(register_response.status_code, 200)
|
|
|
|
login_response = self.client.post(
|
|
"/api/v1/auth/login",
|
|
json={
|
|
"account": "member@example.com",
|
|
"password": "123456",
|
|
},
|
|
)
|
|
|
|
self.assertEqual(login_response.status_code, 200)
|
|
self.assertEqual(login_response.json()["data"]["access_token"], "token-demo")
|
|
|
|
def test_get_current_user(self):
|
|
response = self.client.get("/api/v1/auth/me", headers={"Authorization": "Bearer token-demo"})
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()["data"]["username"], "admin@example.com")
|
|
|
|
def test_update_current_user(self):
|
|
response = self.client.put(
|
|
"/api/v1/auth/me",
|
|
headers={"Authorization": "Bearer token-demo"},
|
|
data={"display_name": "法务负责人", "password": "654321"},
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()["data"]["display_name"], "法务负责人")
|
|
|
|
def test_reject_blank_display_name(self):
|
|
response = self.client.put(
|
|
"/api/v1/auth/me",
|
|
headers={"Authorization": "Bearer token-demo"},
|
|
data={"display_name": " ", "password": ""},
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertEqual(response.json()["message"], "display name is required")
|
|
|
|
def test_reject_short_password(self):
|
|
response = self.client.put(
|
|
"/api/v1/auth/me",
|
|
headers={"Authorization": "Bearer token-demo"},
|
|
data={"display_name": "法务负责人", "password": "12345"},
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertEqual(response.json()["message"], "password must be at least 6 characters")
|
|
|
|
def test_seed_admin_returns_nullable_password(self):
|
|
response = self.client.post("/api/v1/auth/seed-admin")
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
payload = response.json()["data"]
|
|
self.assertEqual(payload["username"], "admin@example.com")
|
|
self.assertIsNone(payload["password"])
|
|
self.assertFalse(payload["created"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|