|
|
@ -1,9 +1,25 @@ |
|
|
|
|
|
import pytest |
|
|
from fastapi import FastAPI |
|
|
from fastapi import FastAPI |
|
|
from pydantic import BaseModel |
|
|
from fastapi.testclient import TestClient |
|
|
from starlette.testclient import TestClient |
|
|
from inline_snapshot import snapshot |
|
|
|
|
|
|
|
|
|
|
|
from .utils import needs_pydanticv1 |
|
|
|
|
|
|
|
|
class Address(BaseModel): |
|
|
|
|
|
|
|
|
@pytest.fixture( |
|
|
|
|
|
name="client", |
|
|
|
|
|
params=[ |
|
|
|
|
|
pytest.param("pydantic-v1", marks=needs_pydanticv1), |
|
|
|
|
|
"pydantic-v2", |
|
|
|
|
|
], |
|
|
|
|
|
) |
|
|
|
|
|
def client_fixture(request: pytest.FixtureRequest) -> TestClient: |
|
|
|
|
|
if request.param == "pydantic-v1": |
|
|
|
|
|
from pydantic.v1 import BaseModel |
|
|
|
|
|
else: |
|
|
|
|
|
from pydantic import BaseModel |
|
|
|
|
|
|
|
|
|
|
|
class Address(BaseModel): |
|
|
""" |
|
|
""" |
|
|
This is a public description of an Address |
|
|
This is a public description of an Address |
|
|
\f |
|
|
\f |
|
|
@ -14,22 +30,44 @@ class Address(BaseModel): |
|
|
city: str |
|
|
city: str |
|
|
state_province: str |
|
|
state_province: str |
|
|
|
|
|
|
|
|
|
|
|
class Facility(BaseModel): |
|
|
class Facility(BaseModel): |
|
|
|
|
|
id: str |
|
|
id: str |
|
|
address: Address |
|
|
address: Address |
|
|
|
|
|
|
|
|
|
|
|
app = FastAPI() |
|
|
|
|
|
|
|
|
app = FastAPI() |
|
|
@app.get("/facilities/{facility_id}") |
|
|
|
|
|
def get_facility(facility_id: str) -> Facility: |
|
|
|
|
|
return Facility( |
|
|
|
|
|
id=facility_id, |
|
|
|
|
|
address=Address(line_1="123 Main St", city="Anytown", state_province="CA"), |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
client = TestClient(app) |
|
|
client = TestClient(app) |
|
|
|
|
|
return client |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/facilities/{facility_id}") |
|
|
def test_get(client: TestClient): |
|
|
def get_facility(facility_id: str) -> Facility: ... |
|
|
response = client.get("/facilities/42") |
|
|
|
|
|
assert response.status_code == 200, response.text |
|
|
|
|
|
assert response.json() == { |
|
|
|
|
|
"id": "42", |
|
|
|
|
|
"address": { |
|
|
|
|
|
"line_1": "123 Main St", |
|
|
|
|
|
"city": "Anytown", |
|
|
|
|
|
"state_province": "CA", |
|
|
|
|
|
}, |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
openapi_schema = { |
|
|
def test_openapi_schema(client: TestClient): |
|
|
|
|
|
""" |
|
|
|
|
|
Sanity check to ensure our app's openapi schema renders as we expect |
|
|
|
|
|
""" |
|
|
|
|
|
response = client.get("/openapi.json") |
|
|
|
|
|
assert response.status_code == 200, response.text |
|
|
|
|
|
assert response.json() == snapshot( |
|
|
|
|
|
{ |
|
|
"components": { |
|
|
"components": { |
|
|
"schemas": { |
|
|
"schemas": { |
|
|
"Address": { |
|
|
"Address": { |
|
|
@ -38,7 +76,10 @@ openapi_schema = { |
|
|
"properties": { |
|
|
"properties": { |
|
|
"city": {"title": "City", "type": "string"}, |
|
|
"city": {"title": "City", "type": "string"}, |
|
|
"line_1": {"title": "Line 1", "type": "string"}, |
|
|
"line_1": {"title": "Line 1", "type": "string"}, |
|
|
"state_province": {"title": "State Province", "type": "string"}, |
|
|
"state_province": { |
|
|
|
|
|
"title": "State Province", |
|
|
|
|
|
"type": "string", |
|
|
|
|
|
}, |
|
|
}, |
|
|
}, |
|
|
"required": ["line_1", "city", "state_province"], |
|
|
"required": ["line_1", "city", "state_province"], |
|
|
"title": "Address", |
|
|
"title": "Address", |
|
|
@ -56,7 +97,9 @@ openapi_schema = { |
|
|
"HTTPValidationError": { |
|
|
"HTTPValidationError": { |
|
|
"properties": { |
|
|
"properties": { |
|
|
"detail": { |
|
|
"detail": { |
|
|
"items": {"$ref": "#/components/schemas/ValidationError"}, |
|
|
"items": { |
|
|
|
|
|
"$ref": "#/components/schemas/ValidationError" |
|
|
|
|
|
}, |
|
|
"title": "Detail", |
|
|
"title": "Detail", |
|
|
"type": "array", |
|
|
"type": "array", |
|
|
} |
|
|
} |
|
|
@ -67,7 +110,9 @@ openapi_schema = { |
|
|
"ValidationError": { |
|
|
"ValidationError": { |
|
|
"properties": { |
|
|
"properties": { |
|
|
"loc": { |
|
|
"loc": { |
|
|
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, |
|
|
"items": { |
|
|
|
|
|
"anyOf": [{"type": "string"}, {"type": "integer"}] |
|
|
|
|
|
}, |
|
|
"title": "Location", |
|
|
"title": "Location", |
|
|
"type": "array", |
|
|
"type": "array", |
|
|
}, |
|
|
}, |
|
|
@ -98,7 +143,9 @@ openapi_schema = { |
|
|
"200": { |
|
|
"200": { |
|
|
"content": { |
|
|
"content": { |
|
|
"application/json": { |
|
|
"application/json": { |
|
|
"schema": {"$ref": "#/components/schemas/Facility"} |
|
|
"schema": { |
|
|
|
|
|
"$ref": "#/components/schemas/Facility" |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
"description": "Successful Response", |
|
|
"description": "Successful Response", |
|
|
@ -118,13 +165,5 @@ openapi_schema = { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
} |
|
|
} |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
def test_openapi_schema(): |
|
|
|
|
|
""" |
|
|
|
|
|
Sanity check to ensure our app's openapi schema renders as we expect |
|
|
|
|
|
""" |
|
|
|
|
|
response = client.get("/openapi.json") |
|
|
|
|
|
assert response.status_code == 200, response.text |
|
|
|
|
|
assert response.json() == openapi_schema |
|
|
|
|
|
|