| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- from datetime import UTC, datetime
- from fastapi.testclient import TestClient
- from app.domains.catalog.repository import InMemoryCatalogRepository
- from app.domains.identity.repository import InMemoryIdentityRepository
- from app.main import create_app
- def build_client() -> TestClient:
- return TestClient(
- create_app(
- identity_repository=InMemoryIdentityRepository(),
- catalog_repository=InMemoryCatalogRepository(),
- )
- )
- def test_success_envelope_contains_request_id_and_utc_server_time() -> None:
- with build_client() as client:
- response = client.get(
- "/api/v1/system/health/live",
- headers={"X-Request-ID": "req_contract_success"},
- )
- assert response.status_code == 200
- assert response.headers["X-Request-ID"] == "req_contract_success"
- assert response.json()["meta"]["request_id"] == "req_contract_success"
- server_time = datetime.fromisoformat(
- response.json()["meta"]["server_time"].replace("Z", "+00:00")
- )
- assert server_time.tzinfo == UTC
- def test_request_validation_uses_stable_error_envelope() -> None:
- with build_client() as client:
- response = client.post(
- "/api/v1/h5/auth/login",
- json={"mobile": "123", "code": "1"},
- headers={"X-Request-ID": "req_contract_validation"},
- )
- assert response.status_code == 400
- assert response.headers["X-Request-ID"] == "req_contract_validation"
- assert response.json() == {
- "success": False,
- "error": {
- "code": "VALIDATION_ERROR",
- "message": "请求参数无效",
- "details": {
- "fields": [
- {
- "field": "body.mobile",
- "message": "String should have at least 11 characters",
- },
- {"field": "body.code", "message": "String should have at least 6 characters"},
- ]
- },
- "retryable": False,
- },
- "meta": {"request_id": "req_contract_validation"},
- }
|