import unittest from fastapi import HTTPException from fastapi.testclient import TestClient from app.api.users import get_audit_log_service, get_user_service, require_current_user from app.main import app class StubAuditLogService: def __init__(self): self.events = [] def record_event(self, **kwargs): self.events.append(kwargs) return kwargs class StubUserService: def list_users(self, current_user, page, page_size): if current_user["role"] != "admin": raise HTTPException(status_code=403, detail="forbidden") return { "items": [ { "id": "user-123", "tenant_id": current_user["tenant_id"], "username": "member@example.com", "display_name": "法务同事", "role": "legal", "status": "active", "created_at": "2026-04-16T00:00:00+00:00", } ], "page": page, "page_size": page_size, "total": 1, } def create_user(self, current_user, username, display_name, password, role, status_value): if current_user["role"] != "admin": raise HTTPException(status_code=403, detail="forbidden") return { "id": "user-123", "tenant_id": current_user["tenant_id"], "username": username, "display_name": display_name, "role": role, "status": status_value, "created_at": "2026-04-16T00:00:00+00:00", } def update_user(self, current_user, user_id, username, display_name, password, role, status_value): if current_user["role"] != "admin": raise HTTPException(status_code=403, detail="forbidden") return { "id": user_id, "tenant_id": current_user["tenant_id"], "username": username, "display_name": display_name, "role": role, "status": status_value, "created_at": "2026-04-16T00:00:00+00:00", } class UsersApiTestCase(unittest.TestCase): def setUp(self): self.audit_log_service = StubAuditLogService() app.dependency_overrides[get_user_service] = lambda: StubUserService() app.dependency_overrides[get_audit_log_service] = lambda: self.audit_log_service self.client = TestClient(app) def tearDown(self): app.dependency_overrides.clear() def test_admin_can_list_users(self): app.dependency_overrides[require_current_user] = lambda: { "id": "user-admin", "tenant_id": "tenant-demo-001", "role": "admin", } response = self.client.get("/api/v1/users") self.assertEqual(response.status_code, 200) self.assertEqual(response.json()["data"]["items"][0]["username"], "member@example.com") def test_admin_can_create_user(self): app.dependency_overrides[require_current_user] = lambda: { "id": "user-admin", "tenant_id": "tenant-demo-001", "role": "admin", } response = self.client.post( "/api/v1/users", data={ "username": "new.user@example.com", "display_name": "新同事", "password": "123456", "role": "legal", "status": "active", }, ) self.assertEqual(response.status_code, 200) self.assertEqual(response.json()["data"]["display_name"], "新同事") self.assertEqual(self.audit_log_service.events[0]["action"], "create_user") self.assertEqual( self.audit_log_service.events[0]["detail_json"], { "username": "new.user@example.com", "display_name": "新同事", "role": "legal", "status": "active", }, ) def test_admin_can_update_user(self): app.dependency_overrides[require_current_user] = lambda: { "id": "user-admin", "tenant_id": "tenant-demo-001", "role": "admin", } response = self.client.put( "/api/v1/users/user-123", data={ "username": "member@example.com", "display_name": "法务负责人", "password": "", "role": "business", "status": "disabled", }, ) self.assertEqual(response.status_code, 200) body = response.json() self.assertEqual(body["data"]["role"], "business") self.assertEqual(body["data"]["status"], "disabled") self.assertEqual(self.audit_log_service.events[0]["action"], "update_user") self.assertEqual( self.audit_log_service.events[0]["detail_json"], { "username": "member@example.com", "display_name": "法务负责人", "role": "business", "status": "disabled", "password_changed": False, }, ) def test_member_cannot_access_users(self): app.dependency_overrides[require_current_user] = lambda: { "id": "user-member", "tenant_id": "tenant-demo-001", "role": "member", } response = self.client.get("/api/v1/users") self.assertEqual(response.status_code, 403) self.assertEqual(response.json()["message"], "forbidden") if __name__ == "__main__": unittest.main()