test_api_contract.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. from datetime import UTC, datetime
  2. from fastapi.testclient import TestClient
  3. from zbt.domains.catalog.repository import InMemoryCatalogRepository
  4. from zbt.domains.identity.repository import InMemoryIdentityRepository
  5. from zbt.main import create_app
  6. def build_client() -> TestClient:
  7. return TestClient(
  8. create_app(
  9. identity_repository=InMemoryIdentityRepository(),
  10. catalog_repository=InMemoryCatalogRepository(),
  11. )
  12. )
  13. def test_success_envelope_contains_request_id_and_utc_server_time() -> None:
  14. with build_client() as client:
  15. response = client.get(
  16. "/api/v1/system/health/live",
  17. headers={"X-Request-ID": "req_contract_success"},
  18. )
  19. assert response.status_code == 200
  20. assert response.headers["X-Request-ID"] == "req_contract_success"
  21. assert response.json()["meta"]["request_id"] == "req_contract_success"
  22. server_time = datetime.fromisoformat(
  23. response.json()["meta"]["server_time"].replace("Z", "+00:00")
  24. )
  25. assert server_time.tzinfo == UTC
  26. def test_request_validation_uses_stable_error_envelope() -> None:
  27. with build_client() as client:
  28. response = client.post(
  29. "/api/v1/h5/auth/login",
  30. json={"mobile": "123", "code": "1"},
  31. headers={"X-Request-ID": "req_contract_validation"},
  32. )
  33. assert response.status_code == 400
  34. assert response.headers["X-Request-ID"] == "req_contract_validation"
  35. assert response.json() == {
  36. "success": False,
  37. "error": {
  38. "code": "VALIDATION_ERROR",
  39. "message": "请求参数无效",
  40. "details": {
  41. "fields": [
  42. {
  43. "field": "body.mobile",
  44. "message": "String should have at least 11 characters",
  45. },
  46. {"field": "body.code", "message": "String should have at least 6 characters"},
  47. ]
  48. },
  49. "retryable": False,
  50. },
  51. "meta": {"request_id": "req_contract_validation"},
  52. }