chore: 初始化项目结构与登录鉴权模块
后端 FastAPI 六层结构(api/services/repositories/models/schemas/core), 统一响应信封、全局异常、日志脱敏;6 张表经 Alembic 迁移建库,SQL 留存 db/migration;登录鉴权含图形验证码(Redis GETDEL 防重放)、JWT、登录限流、 登出黑名单(TTL=令牌剩余有效期)、登录日志。 前端 Vue3 + TS + Element Plus 骨架,含登录页、路由守卫、请求封装与 Vite 代理。 工程配置:uv 锁定 Python 3.12、ruff 检查与格式化、editorconfig、gitattributes。 测试 184 项(单元 155 / 集成 29)全绿,浏览器端到端 8 项通过。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
commit
273ebf4657
101 files changed
+8725
No files matched your search
@@ -0,0 +1,55 @@
|
||||
"""应用级 HTTP 测试:统一响应格式与全局异常处理。
|
||||
|
||||
归在 integration 下是因为需要构造完整 FastAPI 应用;
|
||||
但用例本身不要求 MySQL/Redis 在跑 —— 健康检查会把依赖状态如实体现在
|
||||
data 中,接口始终返回 200。
|
||||
"""
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
class TestHealthEndpoint:
|
||||
"""健康检查接口。"""
|
||||
|
||||
def test_返回统一响应格式(self, client: TestClient) -> None:
|
||||
response = client.get("/api/health")
|
||||
assert response.status_code == 200
|
||||
body = response.json()
|
||||
assert body["code"] == 200
|
||||
assert body["message"] == "success"
|
||||
assert body["data"]["app"] is True
|
||||
|
||||
def test_上报数据库与Redis状态为布尔值(self, client: TestClient) -> None:
|
||||
data = client.get("/api/health").json()["data"]
|
||||
assert isinstance(data["db"], bool)
|
||||
assert isinstance(data["redis"], bool)
|
||||
|
||||
def test_不要求认证(self, client: TestClient) -> None:
|
||||
assert client.get("/api/health").status_code == 200
|
||||
|
||||
|
||||
class TestGlobalExceptionHandling:
|
||||
"""全局异常处理器:不得把框架默认的 detail 数组泄漏给前端。"""
|
||||
|
||||
def test_未知路由返回统一格式(self, client: TestClient) -> None:
|
||||
response = client.get("/api/definitely-not-exist")
|
||||
assert response.status_code == 404
|
||||
body = response.json()
|
||||
assert body["code"] == 404
|
||||
assert "detail" not in body
|
||||
|
||||
def test_方法不允许返回统一格式(self, client: TestClient) -> None:
|
||||
response = client.post("/api/health")
|
||||
assert response.status_code == 405
|
||||
assert response.json()["code"] == 405
|
||||
|
||||
|
||||
class TestApiDocs:
|
||||
"""接口文档(规范第 10 节要求提供)。文档挂在 /api 下,便于经 Vite 代理访问。"""
|
||||
|
||||
def test_swagger文档可访问(self, client: TestClient) -> None:
|
||||
assert client.get("/api/docs").status_code == 200
|
||||
|
||||
def test_openapi结构可访问(self, client: TestClient) -> None:
|
||||
schema = client.get("/api/openapi.json").json()
|
||||
assert "/api/health" in schema["paths"]
|
||||
Reference in new issue
Block a user